From 897d278160630a2f84e96d6f468284e0fd7dab95 Mon Sep 17 00:00:00 2001 From: Hsiang-Cheng Yang Date: Tue, 10 Sep 2019 15:35:38 +0800 Subject: [PATCH 001/545] libstd: Fix typos in doc --- src/libstd/path.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index fd6ff1032bb8..966aaec4f0c4 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -1627,7 +1627,7 @@ impl<'a> From> for PathBuf { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Arc { - /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. + /// Converts a `PathBuf` into an `Arc` by moving the `PathBuf` data into a new `Arc` buffer. #[inline] fn from(s: PathBuf) -> Arc { let arc: Arc = Arc::from(s.into_os_string()); @@ -1637,7 +1637,7 @@ impl From for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&Path> for Arc { - /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. + /// Converts a `Path` into an `Arc` by copying the `Path` data into a new `Arc` buffer. #[inline] fn from(s: &Path) -> Arc { let arc: Arc = Arc::from(s.as_os_str()); @@ -1647,7 +1647,7 @@ impl From<&Path> for Arc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From for Rc { - /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. + /// Converts a `PathBuf` into an `Rc` by moving the `PathBuf` data into a new `Rc` buffer. #[inline] fn from(s: PathBuf) -> Rc { let rc: Rc = Rc::from(s.into_os_string()); @@ -1657,7 +1657,7 @@ impl From for Rc { #[stable(feature = "shared_from_slice2", since = "1.24.0")] impl From<&Path> for Rc { - /// Converts a Path into a Rc by copying the Path data into a new Rc buffer. + /// Converts a `Path` into an `Rc` by copying the `Path` data into a new `Rc` buffer. #[inline] fn from(s: &Path) -> Rc { let rc: Rc = Rc::from(s.as_os_str()); From 0797712e295e6c67b39d57d0801de9d0c6f9b100 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 23 Sep 2019 15:51:25 +0200 Subject: [PATCH 002/545] Stabilize Option::deref and Option::deref_mut The tracking issue https://github.com/rust-lang/rust/issues/50264 still has unresolved question for the corresponding `Result` methods. --- src/libcore/option.rs | 8 ++------ src/librustc/lib.rs | 1 - src/librustc_resolve/lib.rs | 1 - src/librustc_save_analysis/lib.rs | 1 - src/librustc_typeck/lib.rs | 1 - src/librustdoc/lib.rs | 1 - .../issue-50264-inner-deref-trait/option-as_deref.rs | 2 -- .../issue-50264-inner-deref-trait/option-as_deref.stderr | 2 +- .../issue-50264-inner-deref-trait/option-as_deref_mut.rs | 2 -- .../option-as_deref_mut.stderr | 2 +- 10 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 5569d99f8d81..a80070d2a916 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1102,7 +1102,6 @@ impl Option { } } -#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Option { /// Converts from `Option` (or `&Option`) to `Option<&T::Target>`. /// @@ -1114,20 +1113,18 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(inner_deref)] - /// /// let x: Option = Some("hey".to_owned()); /// assert_eq!(x.as_deref(), Some("hey")); /// /// let x: Option = None; /// assert_eq!(x.as_deref(), None); /// ``` + #[stable(feature = "option_deref", since = "1.40.0")] pub fn as_deref(&self) -> Option<&T::Target> { self.as_ref().map(|t| t.deref()) } } -#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")] impl Option { /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. /// @@ -1137,14 +1134,13 @@ impl Option { /// # Examples /// /// ``` - /// #![feature(inner_deref)] - /// /// let mut x: Option = Some("hey".to_owned()); /// assert_eq!(x.as_deref_mut().map(|x| { /// x.make_ascii_uppercase(); /// x /// }), Some("HEY".to_owned().as_mut_str())); /// ``` + #[stable(feature = "option_deref", since = "1.40.0")] pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> { self.as_mut().map(|t| t.deref_mut()) } diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 7a01ae6b6d9c..fc397a87d403 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -35,7 +35,6 @@ #![feature(const_transmute)] #![feature(core_intrinsics)] #![feature(drain_filter)] -#![feature(inner_deref)] #![cfg_attr(windows, feature(libc))] #![feature(never_type)] #![feature(exhaustive_patterns)] diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 74f68e514712..d5fdf833bffb 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -9,7 +9,6 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(inner_deref)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] #![feature(mem_take)] diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 055ccf6c2c4f..1e9916d5396e 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -1,6 +1,5 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(nll)] -#![feature(inner_deref)] #![recursion_limit="256"] diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 959483e4439f..beb188fb85a5 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -67,7 +67,6 @@ This API is completely unstable and subject to change. #![feature(nll)] #![feature(slice_patterns)] #![feature(never_type)] -#![feature(inner_deref)] #![feature(mem_take)] #![recursion_limit="256"] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 0b9e717221f2..e7a7efa93578 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -15,7 +15,6 @@ #![feature(crate_visibility_modifier)] #![feature(const_fn)] #![feature(drain_filter)] -#![feature(inner_deref)] #![feature(never_type)] #![feature(mem_take)] #![feature(unicode_internals)] diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs index 67feb3ff6aec..24c61425b8e2 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.rs @@ -1,5 +1,3 @@ -#![feature(inner_deref)] - fn main() { let _result = &Some(42).as_deref(); //~^ ERROR no method named `as_deref` found for type `std::option::Option<{integer}>` 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 345f91437b82..0eb7bf024756 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 @@ -1,5 +1,5 @@ error[E0599]: no method named `as_deref` found for type `std::option::Option<{integer}>` in the current scope - --> $DIR/option-as_deref.rs:4:29 + --> $DIR/option-as_deref.rs:2:29 | LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs index 56aead8d0e00..67ad73f58477 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.rs @@ -1,5 +1,3 @@ -#![feature(inner_deref)] - fn main() { let _result = &mut Some(42).as_deref_mut(); //~^ ERROR no method named `as_deref_mut` found for type `std::option::Option<{integer}>` 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 29fd15fb396e..845ddb52319c 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 @@ -1,5 +1,5 @@ error[E0599]: no method named `as_deref_mut` found for type `std::option::Option<{integer}>` in the current scope - --> $DIR/option-as_deref_mut.rs:4:33 + --> $DIR/option-as_deref_mut.rs:2:33 | LL | let _result = &mut Some(42).as_deref_mut(); | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` From f1835bc517d97e5f3cf9d5a8f361dcd31cb39bef Mon Sep 17 00:00:00 2001 From: messense Date: Tue, 24 Sep 2019 15:10:18 +0800 Subject: [PATCH 003/545] Stabilize UdpSocket::peer_addr --- src/libstd/net/udp.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index a5e7cd992f22..ac00d2af3acf 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -185,7 +185,6 @@ impl UdpSocket { /// # Examples /// /// ```no_run - /// #![feature(udp_peer_addr)] /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4, UdpSocket}; /// /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); @@ -199,14 +198,13 @@ impl UdpSocket { /// [`NotConnected`]: ../../std/io/enum.ErrorKind.html#variant.NotConnected /// /// ```no_run - /// #![feature(udp_peer_addr)] /// use std::net::UdpSocket; /// /// let socket = UdpSocket::bind("127.0.0.1:34254").expect("couldn't bind to address"); /// assert_eq!(socket.peer_addr().unwrap_err().kind(), /// ::std::io::ErrorKind::NotConnected); /// ``` - #[unstable(feature = "udp_peer_addr", issue = "59127")] + #[stable(feature = "udp_peer_addr", since = "1.39.0")] pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } From 1d06058a77beffb6347c77b51e12889b7bd9fc76 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Wed, 25 Sep 2019 06:43:49 -0700 Subject: [PATCH 004/545] std: Reduce checks for `feature = "backtrace"` This is a stylistic change to libstd to reduce the number of checks of `feature = "backtrace"` now that we unconditionally depend on the `backtrace` crate and rely on it having an empty implementation. otherwise. --- src/libstd/panicking.rs | 34 ++++++++--------- src/libstd/rt.rs | 3 -- src/libstd/sys_common/backtrace.rs | 60 +++++++++++++++++------------- src/libstd/thread/mod.rs | 3 -- 4 files changed, 50 insertions(+), 50 deletions(-) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 28fb40244043..638ce1679b8e 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -15,9 +15,11 @@ use crate::intrinsics; use crate::mem; use crate::ptr; use crate::raw; +use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::stdio::panic_output; use crate::sys_common::rwlock::RWLock; -use crate::sys_common::{thread_info, util, backtrace}; +use crate::sys_common::{thread_info, util}; +use crate::sys_common::backtrace::{self, RustBacktrace}; use crate::thread; #[cfg(not(test))] @@ -158,16 +160,10 @@ pub fn take_hook() -> Box) + 'static + Sync + Send> { fn default_hook(info: &PanicInfo<'_>) { // If this is a double panic, make sure that we print a backtrace // for this panic. Otherwise only print it if logging is enabled. - let log_backtrace = if cfg!(feature = "backtrace") { - let panics = update_panic_count(0); - - if panics >= 2 { - Some(backtrace_rs::PrintFmt::Full) - } else { - backtrace::log_enabled() - } + let backtrace_env = if update_panic_count(0) >= 2 { + RustBacktrace::Print(backtrace_rs::PrintFmt::Full) } else { - None + backtrace::rust_backtrace_env() }; // The current implementation always returns `Some`. @@ -187,16 +183,16 @@ fn default_hook(info: &PanicInfo<'_>) { let _ = writeln!(err, "thread '{}' panicked at '{}', {}", name, msg, location); - if cfg!(feature = "backtrace") { - use crate::sync::atomic::{AtomicBool, Ordering}; + static FIRST_PANIC: AtomicBool = AtomicBool::new(true); - static FIRST_PANIC: AtomicBool = AtomicBool::new(true); - - if let Some(format) = log_backtrace { - let _ = backtrace::print(err, format); - } else if FIRST_PANIC.compare_and_swap(true, false, Ordering::SeqCst) { - let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \ - environment variable to display a backtrace."); + match backtrace_env { + RustBacktrace::Print(format) => drop(backtrace::print(err, format)), + RustBacktrace::Disabled => {} + RustBacktrace::RuntimeDisabled => { + if FIRST_PANIC.swap(false, Ordering::SeqCst) { + let _ = writeln!(err, "note: run with `RUST_BACKTRACE=1` \ + environment variable to display a backtrace."); + } } } }; diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index cf45eb0daba3..63e35d5ed919 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -44,12 +44,9 @@ fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindS sys::args::init(argc, argv); // Let's run some code! - #[cfg(feature = "backtrace")] let exit_code = panic::catch_unwind(|| { sys_common::backtrace::__rust_begin_short_backtrace(move || main()) }); - #[cfg(not(feature = "backtrace"))] - let exit_code = panic::catch_unwind(move || main()); sys_common::cleanup(); exit_code.unwrap_or(101) as isize diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 01711d415d86..9c406ec39cc4 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -7,6 +7,7 @@ use crate::io; use crate::borrow::Cow; use crate::io::prelude::*; use crate::path::{self, Path, PathBuf}; +use crate::sync::atomic::{self, Ordering}; use crate::sys::mutex::Mutex; use backtrace_rs::{BacktraceFmt, BytesOrWideString, PrintFmt}; @@ -115,8 +116,10 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: Ok(()) } -/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. -#[inline(never)] +/// Fixed frame used to clean the backtrace with `RUST_BACKTRACE=1`. Note that +/// this is only inline(never) when backtraces in libstd are enabled, otherwise +/// it's fine to optimize away. +#[cfg_attr(feature = "backtrace", inline(never))] pub fn __rust_begin_short_backtrace(f: F) -> T where F: FnOnce() -> T, @@ -126,42 +129,49 @@ where f() } +pub enum RustBacktrace { + Print(PrintFmt), + Disabled, + RuntimeDisabled, +} + // For now logging is turned off by default, and this function checks to see // whether the magical environment variable is present to see if it's turned on. -pub fn log_enabled() -> Option { - use crate::sync::atomic::{self, Ordering}; +pub fn rust_backtrace_env() -> RustBacktrace { + // If the `backtrace` feature of this crate isn't enabled quickly return + // `None` so this can be constant propagated all over the place to turn + // optimize away callers. + if !cfg!(feature = "backtrace") { + return RustBacktrace::Disabled; + } // Setting environment variables for Fuchsia components isn't a standard // or easily supported workflow. For now, always display backtraces. if cfg!(target_os = "fuchsia") { - return Some(PrintFmt::Full); + return RustBacktrace::Print(PrintFmt::Full); } static ENABLED: atomic::AtomicIsize = atomic::AtomicIsize::new(0); match ENABLED.load(Ordering::SeqCst) { 0 => {} - 1 => return None, - 2 => return Some(PrintFmt::Short), - _ => return Some(PrintFmt::Full), + 1 => return RustBacktrace::RuntimeDisabled, + 2 => return RustBacktrace::Print(PrintFmt::Short), + _ => return RustBacktrace::Print(PrintFmt::Full), } - let val = env::var_os("RUST_BACKTRACE").and_then(|x| { - if &x == "0" { - None - } else if &x == "full" { - Some(PrintFmt::Full) - } else { - Some(PrintFmt::Short) - } - }); - ENABLED.store( - match val { - Some(v) => v as isize, - None => 1, - }, - Ordering::SeqCst, - ); - val + let (format, cache) = env::var_os("RUST_BACKTRACE") + .map(|x| { + if &x == "0" { + (RustBacktrace::RuntimeDisabled, 1) + } else if &x == "full" { + (RustBacktrace::Print(PrintFmt::Full), 3) + } else { + (RustBacktrace::Print(PrintFmt::Short), 2) + } + }) + .unwrap_or((RustBacktrace::RuntimeDisabled, 1)); + ENABLED.store(cache, Ordering::SeqCst); + format } /// Prints the filename of the backtrace frame. diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 764041d2f423..0ffa6ace2e4d 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -465,12 +465,9 @@ impl Builder { } thread_info::set(imp::guard::current(), their_thread); - #[cfg(feature = "backtrace")] let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { crate::sys_common::backtrace::__rust_begin_short_backtrace(f) })); - #[cfg(not(feature = "backtrace"))] - let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f)); *their_packet.get() = Some(try_result); }; From 640c261a1f2b6bdd994670246772c15af199c65a Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Wed, 25 Sep 2019 20:23:26 +0200 Subject: [PATCH 005/545] Only add sanitizer runtimes when linking an executable (#64629). --- src/librustc_codegen_ssa/back/link.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 9b044d9b4537..dc73ee35aa64 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1372,7 +1372,9 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, _ if codegen_results.crate_info.profiler_runtime == Some(cnum) => { add_static_crate::(cmd, sess, codegen_results, tmpdir, crate_type, cnum); } - _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum) => { + _ if codegen_results.crate_info.sanitizer_runtime == Some(cnum) && + crate_type == config::CrateType::Executable => { + // Link the sanitizer runtimes only if we are actually producing an executable link_sanitizer_runtime::(cmd, sess, codegen_results, tmpdir, cnum); } // compiler-builtins are always placed last to ensure that they're From 1de6f74ca47718ae22d7d76eff2986847c659390 Mon Sep 17 00:00:00 2001 From: messense Date: Thu, 26 Sep 2019 09:14:45 +0800 Subject: [PATCH 006/545] Update src/libstd/net/udp.rs Co-Authored-By: Mazdak Farrokhzad --- src/libstd/net/udp.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/net/udp.rs b/src/libstd/net/udp.rs index ac00d2af3acf..46bbd8855ded 100644 --- a/src/libstd/net/udp.rs +++ b/src/libstd/net/udp.rs @@ -204,7 +204,7 @@ impl UdpSocket { /// assert_eq!(socket.peer_addr().unwrap_err().kind(), /// ::std::io::ErrorKind::NotConnected); /// ``` - #[stable(feature = "udp_peer_addr", since = "1.39.0")] + #[stable(feature = "udp_peer_addr", since = "1.40.0")] pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } From f71e0daa29b232d8f689f77fecb84dcb87fce6da Mon Sep 17 00:00:00 2001 From: Xiang Fan Date: Thu, 6 Jun 2019 08:39:20 +0800 Subject: [PATCH 007/545] Add llvm.sideeffect to potential infinite loops and recursions LLVM assumes that a thread will eventually cause side effect. This is not true in Rust if a loop or recursion does nothing in its body, causing undefined behavior even in common cases like `loop {}`. Inserting llvm.sideeffect fixes the undefined behavior. As a micro-optimization, only insert llvm.sideeffect when jumping back in blocks or calling a function. A patch for LLVM is expected to allow empty non-terminate code by default and fix this issue from LLVM side. https://github.com/rust-lang/rust/issues/28728 --- src/librustc_codegen_llvm/context.rs | 1 + src/librustc_codegen_llvm/intrinsic.rs | 6 ++++ src/librustc_codegen_ssa/mir/block.rs | 36 ++++++++++++++++++- src/librustc_codegen_ssa/mir/rvalue.rs | 1 + src/librustc_codegen_ssa/traits/intrinsic.rs | 1 + src/test/codegen/alloc-optimisation.rs | 3 +- src/test/codegen/dealloc-no-unwind.rs | 2 +- src/test/codegen/issue-34947-pow-i32.rs | 9 +++-- src/test/codegen/issue-45222.rs | 6 ++++ src/test/codegen/naked-functions.rs | 10 +++--- .../codegen/non-terminate/infinite-loop-1.rs | 17 +++++++++ .../codegen/non-terminate/infinite-loop-2.rs | 19 ++++++++++ .../non-terminate/infinite-recursion.rs | 14 ++++++++ src/test/codegen/repeat-trusted-len.rs | 6 +++- src/test/codegen/vec-clear.rs | 6 ++++ src/test/codegen/vec-iter-collect-len.rs | 4 +-- src/test/codegen/vec-optimizes-away.rs | 2 +- .../inline-always-many-cgu/Makefile | 2 +- 18 files changed, 127 insertions(+), 18 deletions(-) create mode 100644 src/test/codegen/non-terminate/infinite-loop-1.rs create mode 100644 src/test/codegen/non-terminate/infinite-loop-2.rs create mode 100644 src/test/codegen/non-terminate/infinite-recursion.rs diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 58ce97039099..bac37369a29a 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -537,6 +537,7 @@ impl CodegenCx<'b, 'tcx> { ifn!("llvm.trap", fn() -> void); ifn!("llvm.debugtrap", fn() -> void); ifn!("llvm.frameaddress", fn(t_i32) -> i8p); + ifn!("llvm.sideeffect", fn() -> void); ifn!("llvm.powi.f32", fn(t_f32, t_i32) -> t_f32); ifn!("llvm.powi.v2f32", fn(t_v2f32, t_i32) -> t_v2f32); diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index b7a410c3760c..a8734d338df1 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -124,6 +124,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.call(expect, &[args[0].immediate(), self.const_bool(false)], None) } "try" => { + self.sideeffect(); try_intrinsic(self, args[0].immediate(), args[1].immediate(), @@ -724,6 +725,11 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.call(expect, &[cond, self.const_bool(expected)], None) } + fn sideeffect(&mut self) { + let fnname = self.get_intrinsic(&("llvm.sideeffect")); + self.call(fnname, &[], None); + } + fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value { let intrinsic = self.cx().get_intrinsic("llvm.va_start"); self.call(intrinsic, &[va_list], None) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 3069199a2125..99d70e6bb825 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -148,6 +148,24 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { } } } + + // Generate sideeffect intrinsic if jumping to any of the targets can form + // a loop. + fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( + &self, + mir: &'b mir::Body<'tcx>, + bx: &mut Bx, + targets: &[mir::BasicBlock], + ) { + if targets.iter().any(|target| { + *target <= *self.bb + && target + .start_location() + .is_predecessor_of(self.bb.start_location(), mir) + }) { + bx.sideeffect(); + } + } } /// Codegen implementations for some terminator variants. @@ -196,6 +214,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let lltrue = helper.llblock(self, targets[0]); let llfalse = helper.llblock(self, targets[1]); if switch_ty == bx.tcx().types.bool { + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); // Don't generate trivial icmps when switching on bool if let [0] = values[..] { bx.cond_br(discr.immediate(), llfalse, lltrue); @@ -209,9 +228,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); let llval = bx.const_uint_big(switch_llty, values[0]); let cmp = bx.icmp(IntPredicate::IntEQ, discr.immediate(), llval); + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); bx.cond_br(cmp, lltrue, llfalse); } } else { + helper.maybe_sideeffect(self.mir, &mut bx, targets.as_slice()); let (otherwise, targets) = targets.split_last().unwrap(); bx.switch( discr.immediate(), @@ -310,6 +331,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def { // we don't actually need to drop anything. + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return } @@ -340,6 +362,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { FnType::of_instance(&bx, drop_fn)) } }; + bx.sideeffect(); helper.do_call(self, &mut bx, fn_ty, drop_fn, args, Some((ReturnDest::Nothing, target)), unwind); @@ -375,6 +398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Don't codegen the panic block if success if known. if const_cond == Some(expected) { + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return; } @@ -385,6 +409,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Create the failure block and the conditional branch to it. let lltarget = helper.llblock(self, target); let panic_block = self.new_block("panic"); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); if expected { bx.cond_br(cond, lltarget, panic_block.llbb()); } else { @@ -437,6 +462,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_ty = FnType::of_instance(&bx, instance); let llfn = bx.get_fn(instance); + bx.sideeffect(); // Codegen the actual panic invoke/call. helper.do_call(self, &mut bx, fn_ty, llfn, &args, None, cleanup); } @@ -488,6 +514,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let Some(destination_ref) = destination.as_ref() { let &(ref dest, target) = destination_ref; self.codegen_transmute(&mut bx, &args[0], dest); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } else { // If we are trying to transmute to an uninhabited type, @@ -518,6 +545,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Some(ty::InstanceDef::DropGlue(_, None)) => { // Empty drop glue; a no-op. let &(_, target) = destination.as_ref().unwrap(); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); return; } @@ -554,6 +582,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_ty = FnType::of_instance(&bx, instance); let llfn = bx.get_fn(instance); + bx.sideeffect(); // Codegen the actual panic invoke/call. helper.do_call( self, @@ -566,7 +595,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); } else { // a NOP - helper.funclet_br(self, &mut bx, destination.as_ref().unwrap().1) + let target = destination.as_ref().unwrap().1; + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); + helper.funclet_br(self, &mut bx, target); } return; } @@ -675,6 +706,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } if let Some((_, target)) = *destination { + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } else { bx.unreachable(); @@ -786,6 +818,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => span_bug!(span, "no llfn for call"), }; + bx.sideeffect(); helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, destination.as_ref().map(|&(_, target)| (ret_dest, target)), cleanup); @@ -835,6 +868,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::TerminatorKind::Goto { target } => { + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.funclet_br(self, &mut bx, target); } diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 9b69383b455c..11a75c6f38c7 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -486,6 +486,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let instance = ty::Instance::mono(bx.tcx(), def_id); let r = bx.cx().get_fn(instance); + bx.sideeffect(); let call = bx.call(r, &[llsize, llalign], None); let val = bx.pointercast(call, llty_ptr); diff --git a/src/librustc_codegen_ssa/traits/intrinsic.rs b/src/librustc_codegen_ssa/traits/intrinsic.rs index 7c79cd602103..2c484084c4a2 100644 --- a/src/librustc_codegen_ssa/traits/intrinsic.rs +++ b/src/librustc_codegen_ssa/traits/intrinsic.rs @@ -20,6 +20,7 @@ pub trait IntrinsicCallMethods<'tcx>: BackendTypes { fn abort(&mut self); fn assume(&mut self, val: Self::Value); fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value; + fn sideeffect(&mut self); /// Trait method used to inject `va_start` on the "spoofed" `VaListImpl` in /// Rust defined C-variadic functions. fn va_start(&mut self, val: Self::Value) -> Self::Value; diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs index c3ffaeb9547b..c1e36a17ec29 100644 --- a/src/test/codegen/alloc-optimisation.rs +++ b/src/test/codegen/alloc-optimisation.rs @@ -7,7 +7,8 @@ pub fn alloc_test(data: u32) { // CHECK-LABEL: @alloc_test // CHECK-NEXT: start: - // CHECK-NEXT: ret void + // CHECK-NOT: alloc + // CHECK: ret void let x = Box::new(data); drop(x); } diff --git a/src/test/codegen/dealloc-no-unwind.rs b/src/test/codegen/dealloc-no-unwind.rs index ff21b4caa83c..f8fc663169d9 100644 --- a/src/test/codegen/dealloc-no-unwind.rs +++ b/src/test/codegen/dealloc-no-unwind.rs @@ -17,7 +17,7 @@ impl Drop for A { pub fn a(a: Box) { // CHECK-LABEL: define void @a // CHECK: call void @__rust_dealloc - // CHECK-NEXT: call void @foo + // CHECK: call void @foo let _a = A; drop(a); } diff --git a/src/test/codegen/issue-34947-pow-i32.rs b/src/test/codegen/issue-34947-pow-i32.rs index 653da8e8b5f7..bd8b79adf43b 100644 --- a/src/test/codegen/issue-34947-pow-i32.rs +++ b/src/test/codegen/issue-34947-pow-i32.rs @@ -6,8 +6,11 @@ #[no_mangle] pub fn issue_34947(x: i32) -> i32 { // CHECK: mul - // CHECK-NEXT: mul - // CHECK-NEXT: mul - // CHECK-NEXT: ret + // CHECK-NOT: br label + // CHECK: mul + // CHECK-NOT: br label + // CHECK: mul + // CHECK-NOT: br label + // CHECK: ret x.pow(5) } diff --git a/src/test/codegen/issue-45222.rs b/src/test/codegen/issue-45222.rs index 7aadc8a09549..894927c5c335 100644 --- a/src/test/codegen/issue-45222.rs +++ b/src/test/codegen/issue-45222.rs @@ -1,3 +1,9 @@ +// ignore-test + +// FIXME: +// LLVM can't optimize some loops with a large number of iterations because of +// @llvm.sideeffect() (see also #59546) + // compile-flags: -O // ignore-debug: the debug assertions get in the way diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs index 2050193b61b5..fb683a49a8a8 100644 --- a/src/test/codegen/naked-functions.rs +++ b/src/test/codegen/naked-functions.rs @@ -1,5 +1,3 @@ -// ignore-tidy-linelength - // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] @@ -53,7 +51,7 @@ pub fn naked_with_args_and_return(a: isize) -> isize { #[naked] pub fn naked_recursive() { // CHECK-NEXT: {{.+}}: - // CHECK-NEXT: call void @naked_empty() + // CHECK: call void @naked_empty() // FIXME(#39685) Avoid one block per call. // CHECK-NEXT: br label %bb1 @@ -61,19 +59,19 @@ pub fn naked_recursive() { naked_empty(); - // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return() + // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return() // FIXME(#39685) Avoid one block per call. // CHECK-NEXT: br label %bb2 // CHECK: bb2: - // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}}) // FIXME(#39685) Avoid one block per call. // CHECK-NEXT: br label %bb3 // CHECK: bb3: - // CHECK-NEXT: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}}) + // CHECK: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}}) // FIXME(#39685) Avoid one block per call. // CHECK-NEXT: br label %bb4 diff --git a/src/test/codegen/non-terminate/infinite-loop-1.rs b/src/test/codegen/non-terminate/infinite-loop-1.rs new file mode 100644 index 000000000000..fa9c66b47c0a --- /dev/null +++ b/src/test/codegen/non-terminate/infinite-loop-1.rs @@ -0,0 +1,17 @@ +// compile-flags: -C opt-level=3 + +#![crate_type = "lib"] + +fn infinite_loop() -> u8 { + loop {} +} + +// CHECK-LABEL: @test +#[no_mangle] +fn test() -> u8 { + // CHECK-NOT: unreachable + // CHECK: br label %{{.+}} + // CHECK-NOT: unreachable + let x = infinite_loop(); + x +} diff --git a/src/test/codegen/non-terminate/infinite-loop-2.rs b/src/test/codegen/non-terminate/infinite-loop-2.rs new file mode 100644 index 000000000000..81d62ab33d77 --- /dev/null +++ b/src/test/codegen/non-terminate/infinite-loop-2.rs @@ -0,0 +1,19 @@ +// compile-flags: -C opt-level=3 + +#![crate_type = "lib"] + +fn infinite_loop() -> u8 { + let i = 2; + while i > 1 {} + 1 +} + +// CHECK-LABEL: @test +#[no_mangle] +fn test() -> u8 { + // CHECK-NOT: unreachable + // CHECK: br label %{{.+}} + // CHECK-NOT: unreachable + let x = infinite_loop(); + x +} diff --git a/src/test/codegen/non-terminate/infinite-recursion.rs b/src/test/codegen/non-terminate/infinite-recursion.rs new file mode 100644 index 000000000000..6d1f2d4bf8f4 --- /dev/null +++ b/src/test/codegen/non-terminate/infinite-recursion.rs @@ -0,0 +1,14 @@ +// compile-flags: -C opt-level=3 + +#![crate_type = "lib"] + +#![allow(unconditional_recursion)] + +// CHECK-LABEL: @infinite_recursion +#[no_mangle] +fn infinite_recursion() -> u8 { + // CHECK-NOT: ret i8 undef + // CHECK: br label %{{.+}} + // CHECK-NOT: ret i8 undef + infinite_recursion() +} diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs index 87f29f6047c6..40399e8f76f0 100644 --- a/src/test/codegen/repeat-trusted-len.rs +++ b/src/test/codegen/repeat-trusted-len.rs @@ -14,6 +14,10 @@ pub fn helper(_: usize) { // CHECK-LABEL: @repeat_take_collect #[no_mangle] pub fn repeat_take_collect() -> Vec { -// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false) +// FIXME: At the time of writing LLVM transforms this loop into a single +// `store` and then a `memset` with size = 99999. The correct check should be: +// call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[a-z0-9.]+}}, i8 42, [[USIZE]] 100000, i1 false) + +// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[a-z0-9.]+}}, i8 42, [[USIZE]] 99999, i1 false) iter::repeat(42).take(100000).collect() } diff --git a/src/test/codegen/vec-clear.rs b/src/test/codegen/vec-clear.rs index b9ffce8b0cb3..22e1248907a7 100644 --- a/src/test/codegen/vec-clear.rs +++ b/src/test/codegen/vec-clear.rs @@ -1,3 +1,9 @@ +// ignore-test + +// FIXME: +// LLVM can't optimize some loops with unknown number of iterations because of +// @llvm.sideeffect() (see also #59546) + // ignore-debug: the debug assertions get in the way // compile-flags: -O diff --git a/src/test/codegen/vec-iter-collect-len.rs b/src/test/codegen/vec-iter-collect-len.rs index 73348ddd063d..893d1b50a4a9 100644 --- a/src/test/codegen/vec-iter-collect-len.rs +++ b/src/test/codegen/vec-iter-collect-len.rs @@ -5,8 +5,6 @@ #[no_mangle] pub fn get_len() -> usize { - // CHECK-LABEL: @get_len - // CHECK-NOT: call - // CHECK-NOT: invoke + // CHECK-COUNT-1: {{^define}} [1, 2, 3].iter().collect::>().len() } diff --git a/src/test/codegen/vec-optimizes-away.rs b/src/test/codegen/vec-optimizes-away.rs index ebede0908c6c..08d0332651cb 100644 --- a/src/test/codegen/vec-optimizes-away.rs +++ b/src/test/codegen/vec-optimizes-away.rs @@ -8,6 +8,6 @@ pub fn sum_me() -> i32 { // CHECK-LABEL: @sum_me // CHECK-NEXT: {{^.*:$}} - // CHECK-NEXT: ret i32 6 + // CHECK: ret i32 6 vec![1, 2, 3].iter().sum::() } diff --git a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile index 0cab955f6442..fd09df78ffa8 100644 --- a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile +++ b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile @@ -2,7 +2,7 @@ all: $(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 - if cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b'; then \ + if cat $(TMPDIR)/*.ll | grep -v 'call void @llvm.sideeffect()' | $(CGREP) -e '\bcall\b'; then \ echo "found call instruction when one wasn't expected"; \ exit 1; \ fi From 10c668190cb419b539a36214237382c6689f7daf Mon Sep 17 00:00:00 2001 From: Xiang Fan Date: Sat, 28 Sep 2019 07:13:53 +0800 Subject: [PATCH 008/545] Gate llvm.sideeffect under -Z insert-sideeffect --- src/librustc/session/config.rs | 3 +++ src/librustc_codegen_llvm/intrinsic.rs | 6 ++++-- src/librustc_codegen_ssa/mir/block.rs | 16 +++++++++------- src/test/codegen/alloc-optimisation.rs | 3 +-- src/test/codegen/dealloc-no-unwind.rs | 2 +- src/test/codegen/issue-34947-pow-i32.rs | 9 +++------ src/test/codegen/issue-45222.rs | 6 ------ src/test/codegen/naked-functions.rs | 10 ++++++---- .../codegen/non-terminate/infinite-loop-1.rs | 2 +- .../codegen/non-terminate/infinite-loop-2.rs | 2 +- .../codegen/non-terminate/infinite-recursion.rs | 2 +- src/test/codegen/repeat-trusted-len.rs | 6 +----- src/test/codegen/vec-clear.rs | 6 ------ src/test/codegen/vec-iter-collect-len.rs | 4 +++- src/test/codegen/vec-optimizes-away.rs | 2 +- .../inline-always-many-cgu/Makefile | 2 +- 16 files changed, 36 insertions(+), 45 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 73b731b07619..abfbba53b593 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1472,6 +1472,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "which mangling version to use for symbol names"), binary_dep_depinfo: bool = (false, parse_bool, [TRACKED], "include artifacts (sysroot, crate dependencies) used during compilation in dep-info"), + insert_sideeffect: bool = (false, parse_bool, [TRACKED], + "fix undefined behavior when a thread doesn't eventually make progress \ + (such as entering an empty infinite loop) by inserting llvm.sideeffect"), } pub fn default_lib_output() -> CrateType { diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index a8734d338df1..e4ac17657605 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -726,8 +726,10 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { } fn sideeffect(&mut self) { - let fnname = self.get_intrinsic(&("llvm.sideeffect")); - self.call(fnname, &[], None); + if self.tcx.sess.opts.debugging_opts.insert_sideeffect { + let fnname = self.get_intrinsic(&("llvm.sideeffect")); + self.call(fnname, &[], None); + } } fn va_start(&mut self, va_list: &'ll Value) -> &'ll Value { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 99d70e6bb825..8e3243f5e7bd 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -157,13 +157,15 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'a, 'tcx> { bx: &mut Bx, targets: &[mir::BasicBlock], ) { - if targets.iter().any(|target| { - *target <= *self.bb - && target - .start_location() - .is_predecessor_of(self.bb.start_location(), mir) - }) { - bx.sideeffect(); + if bx.tcx().sess.opts.debugging_opts.insert_sideeffect { + if targets.iter().any(|target| { + *target <= *self.bb + && target + .start_location() + .is_predecessor_of(self.bb.start_location(), mir) + }) { + bx.sideeffect(); + } } } } diff --git a/src/test/codegen/alloc-optimisation.rs b/src/test/codegen/alloc-optimisation.rs index c1e36a17ec29..c3ffaeb9547b 100644 --- a/src/test/codegen/alloc-optimisation.rs +++ b/src/test/codegen/alloc-optimisation.rs @@ -7,8 +7,7 @@ pub fn alloc_test(data: u32) { // CHECK-LABEL: @alloc_test // CHECK-NEXT: start: - // CHECK-NOT: alloc - // CHECK: ret void + // CHECK-NEXT: ret void let x = Box::new(data); drop(x); } diff --git a/src/test/codegen/dealloc-no-unwind.rs b/src/test/codegen/dealloc-no-unwind.rs index f8fc663169d9..ff21b4caa83c 100644 --- a/src/test/codegen/dealloc-no-unwind.rs +++ b/src/test/codegen/dealloc-no-unwind.rs @@ -17,7 +17,7 @@ impl Drop for A { pub fn a(a: Box) { // CHECK-LABEL: define void @a // CHECK: call void @__rust_dealloc - // CHECK: call void @foo + // CHECK-NEXT: call void @foo let _a = A; drop(a); } diff --git a/src/test/codegen/issue-34947-pow-i32.rs b/src/test/codegen/issue-34947-pow-i32.rs index bd8b79adf43b..653da8e8b5f7 100644 --- a/src/test/codegen/issue-34947-pow-i32.rs +++ b/src/test/codegen/issue-34947-pow-i32.rs @@ -6,11 +6,8 @@ #[no_mangle] pub fn issue_34947(x: i32) -> i32 { // CHECK: mul - // CHECK-NOT: br label - // CHECK: mul - // CHECK-NOT: br label - // CHECK: mul - // CHECK-NOT: br label - // CHECK: ret + // CHECK-NEXT: mul + // CHECK-NEXT: mul + // CHECK-NEXT: ret x.pow(5) } diff --git a/src/test/codegen/issue-45222.rs b/src/test/codegen/issue-45222.rs index 894927c5c335..7aadc8a09549 100644 --- a/src/test/codegen/issue-45222.rs +++ b/src/test/codegen/issue-45222.rs @@ -1,9 +1,3 @@ -// ignore-test - -// FIXME: -// LLVM can't optimize some loops with a large number of iterations because of -// @llvm.sideeffect() (see also #59546) - // compile-flags: -O // ignore-debug: the debug assertions get in the way diff --git a/src/test/codegen/naked-functions.rs b/src/test/codegen/naked-functions.rs index fb683a49a8a8..2050193b61b5 100644 --- a/src/test/codegen/naked-functions.rs +++ b/src/test/codegen/naked-functions.rs @@ -1,3 +1,5 @@ +// ignore-tidy-linelength + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] @@ -51,7 +53,7 @@ pub fn naked_with_args_and_return(a: isize) -> isize { #[naked] pub fn naked_recursive() { // CHECK-NEXT: {{.+}}: - // CHECK: call void @naked_empty() + // CHECK-NEXT: call void @naked_empty() // FIXME(#39685) Avoid one block per call. // CHECK-NEXT: br label %bb1 @@ -59,19 +61,19 @@ pub fn naked_recursive() { naked_empty(); - // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return() + // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_return() // FIXME(#39685) Avoid one block per call. // CHECK-NEXT: br label %bb2 // CHECK: bb2: - // CHECK: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}}) + // CHECK-NEXT: %{{[0-9]+}} = call i{{[0-9]+}} @naked_with_args_and_return(i{{[0-9]+}} %{{[0-9]+}}) // FIXME(#39685) Avoid one block per call. // CHECK-NEXT: br label %bb3 // CHECK: bb3: - // CHECK: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}}) + // CHECK-NEXT: call void @naked_with_args(i{{[0-9]+}} %{{[0-9]+}}) // FIXME(#39685) Avoid one block per call. // CHECK-NEXT: br label %bb4 diff --git a/src/test/codegen/non-terminate/infinite-loop-1.rs b/src/test/codegen/non-terminate/infinite-loop-1.rs index fa9c66b47c0a..56b360e0a7f4 100644 --- a/src/test/codegen/non-terminate/infinite-loop-1.rs +++ b/src/test/codegen/non-terminate/infinite-loop-1.rs @@ -1,4 +1,4 @@ -// compile-flags: -C opt-level=3 +// compile-flags: -C opt-level=3 -Z insert-sideeffect #![crate_type = "lib"] diff --git a/src/test/codegen/non-terminate/infinite-loop-2.rs b/src/test/codegen/non-terminate/infinite-loop-2.rs index 81d62ab33d77..2921ab6dc04a 100644 --- a/src/test/codegen/non-terminate/infinite-loop-2.rs +++ b/src/test/codegen/non-terminate/infinite-loop-2.rs @@ -1,4 +1,4 @@ -// compile-flags: -C opt-level=3 +// compile-flags: -C opt-level=3 -Z insert-sideeffect #![crate_type = "lib"] diff --git a/src/test/codegen/non-terminate/infinite-recursion.rs b/src/test/codegen/non-terminate/infinite-recursion.rs index 6d1f2d4bf8f4..1f292ce379fc 100644 --- a/src/test/codegen/non-terminate/infinite-recursion.rs +++ b/src/test/codegen/non-terminate/infinite-recursion.rs @@ -1,4 +1,4 @@ -// compile-flags: -C opt-level=3 +// compile-flags: -C opt-level=3 -Z insert-sideeffect #![crate_type = "lib"] diff --git a/src/test/codegen/repeat-trusted-len.rs b/src/test/codegen/repeat-trusted-len.rs index 40399e8f76f0..87f29f6047c6 100644 --- a/src/test/codegen/repeat-trusted-len.rs +++ b/src/test/codegen/repeat-trusted-len.rs @@ -14,10 +14,6 @@ pub fn helper(_: usize) { // CHECK-LABEL: @repeat_take_collect #[no_mangle] pub fn repeat_take_collect() -> Vec { -// FIXME: At the time of writing LLVM transforms this loop into a single -// `store` and then a `memset` with size = 99999. The correct check should be: -// call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[a-z0-9.]+}}, i8 42, [[USIZE]] 100000, i1 false) - -// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[a-z0-9.]+}}, i8 42, [[USIZE]] 99999, i1 false) +// CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1 %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false) iter::repeat(42).take(100000).collect() } diff --git a/src/test/codegen/vec-clear.rs b/src/test/codegen/vec-clear.rs index 22e1248907a7..b9ffce8b0cb3 100644 --- a/src/test/codegen/vec-clear.rs +++ b/src/test/codegen/vec-clear.rs @@ -1,9 +1,3 @@ -// ignore-test - -// FIXME: -// LLVM can't optimize some loops with unknown number of iterations because of -// @llvm.sideeffect() (see also #59546) - // ignore-debug: the debug assertions get in the way // compile-flags: -O diff --git a/src/test/codegen/vec-iter-collect-len.rs b/src/test/codegen/vec-iter-collect-len.rs index 893d1b50a4a9..73348ddd063d 100644 --- a/src/test/codegen/vec-iter-collect-len.rs +++ b/src/test/codegen/vec-iter-collect-len.rs @@ -5,6 +5,8 @@ #[no_mangle] pub fn get_len() -> usize { - // CHECK-COUNT-1: {{^define}} + // CHECK-LABEL: @get_len + // CHECK-NOT: call + // CHECK-NOT: invoke [1, 2, 3].iter().collect::>().len() } diff --git a/src/test/codegen/vec-optimizes-away.rs b/src/test/codegen/vec-optimizes-away.rs index 08d0332651cb..ebede0908c6c 100644 --- a/src/test/codegen/vec-optimizes-away.rs +++ b/src/test/codegen/vec-optimizes-away.rs @@ -8,6 +8,6 @@ pub fn sum_me() -> i32 { // CHECK-LABEL: @sum_me // CHECK-NEXT: {{^.*:$}} - // CHECK: ret i32 6 + // CHECK-NEXT: ret i32 6 vec![1, 2, 3].iter().sum::() } diff --git a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile index fd09df78ffa8..0cab955f6442 100644 --- a/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile +++ b/src/test/run-make-fulldeps/inline-always-many-cgu/Makefile @@ -2,7 +2,7 @@ all: $(RUSTC) foo.rs --emit llvm-ir -C codegen-units=2 - if cat $(TMPDIR)/*.ll | grep -v 'call void @llvm.sideeffect()' | $(CGREP) -e '\bcall\b'; then \ + if cat $(TMPDIR)/*.ll | $(CGREP) -e '\bcall\b'; then \ echo "found call instruction when one wasn't expected"; \ exit 1; \ fi From e9acfa306f47a40be27e8cf72c55dbec35d94017 Mon Sep 17 00:00:00 2001 From: Xiang Fan Date: Sat, 28 Sep 2019 07:14:21 +0800 Subject: [PATCH 009/545] Generate llvm.sideeffect at function entry instead of call --- src/librustc_codegen_llvm/intrinsic.rs | 4 +++- src/librustc_codegen_ssa/mir/block.rs | 11 +++++++---- src/librustc_codegen_ssa/mir/mod.rs | 2 ++ src/librustc_codegen_ssa/mir/rvalue.rs | 1 - 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index e4ac17657605..68d9af09c42b 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -124,7 +124,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { self.call(expect, &[args[0].immediate(), self.const_bool(false)], None) } "try" => { - self.sideeffect(); try_intrinsic(self, args[0].immediate(), args[1].immediate(), @@ -818,6 +817,7 @@ fn codegen_msvc_try( ) { let llfn = get_rust_try_fn(bx, &mut |mut bx| { bx.set_personality_fn(bx.eh_personality()); + bx.sideeffect(); let mut normal = bx.build_sibling_block("normal"); let mut catchswitch = bx.build_sibling_block("catchswitch"); @@ -941,6 +941,8 @@ fn codegen_gnu_try( // 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"); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 8e3243f5e7bd..d95c0b2d87b4 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -364,7 +364,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { FnType::of_instance(&bx, drop_fn)) } }; - bx.sideeffect(); + helper.maybe_sideeffect(self.mir, &mut bx, &[target]); helper.do_call(self, &mut bx, fn_ty, drop_fn, args, Some((ReturnDest::Nothing, target)), unwind); @@ -464,7 +464,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_ty = FnType::of_instance(&bx, instance); let llfn = bx.get_fn(instance); - bx.sideeffect(); // Codegen the actual panic invoke/call. helper.do_call(self, &mut bx, fn_ty, llfn, &args, None, cleanup); } @@ -584,7 +583,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_ty = FnType::of_instance(&bx, instance); let llfn = bx.get_fn(instance); - bx.sideeffect(); + 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, @@ -820,7 +821,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => span_bug!(span, "no llfn for call"), }; - bx.sideeffect(); + if let Some((_, target)) = destination.as_ref() { + helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); + } helper.do_call(self, &mut bx, fn_ty, fn_ptr, &llargs, destination.as_ref().map(|&(_, target)| (ret_dest, target)), cleanup); diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index c341c0685c6a..e4fdf0a09bbf 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -204,6 +204,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx.set_personality_fn(cx.eh_personality()); } + bx.sideeffect(); + let cleanup_kinds = analyze::cleanup_kinds(&mir); // Allocate a `Block` for every basic block, except // the start block, if nothing loops back to it. diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 11a75c6f38c7..9b69383b455c 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -486,7 +486,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let instance = ty::Instance::mono(bx.tcx(), def_id); let r = bx.cx().get_fn(instance); - bx.sideeffect(); let call = bx.call(r, &[llsize, llalign], None); let val = bx.pointercast(call, llty_ptr); From 1dfc3e79628e8faa67617adc02928af809602cd9 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 29 Sep 2019 15:08:57 +0100 Subject: [PATCH 010/545] Get the type of a local from `local_decls` in `schedule_drop` Passing around a separate type is unnecessary and error-prone. --- src/librustc_mir/build/expr/as_rvalue.rs | 2 -- src/librustc_mir/build/expr/as_temp.rs | 1 - src/librustc_mir/build/matches/mod.rs | 5 +---- src/librustc_mir/build/mod.rs | 4 ++-- src/librustc_mir/build/scope.rs | 14 ++++++-------- 5 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 7dfe98cbebfc..7e8c83fe9d3c 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -128,7 +128,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span, scope, result, - expr.ty, ); } @@ -569,7 +568,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { upvar_span, temp_lifetime, temp, - upvar_ty, ); } diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index dbcc330eca38..c56a149d8614 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -103,7 +103,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span, temp_lifetime, temp, - expr_ty, DropKind::Storage, ); } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 8db06aa375e2..b223d528d72f 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -535,21 +535,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { kind: StatementKind::StorageLive(local_id), }, ); - let var_ty = self.local_decls[local_id].ty; let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); - self.schedule_drop(span, region_scope, local_id, var_ty, DropKind::Storage); + self.schedule_drop(span, region_scope, local_id, DropKind::Storage); Place::from(local_id) } pub fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) { let local_id = self.var_local_id(var, for_guard); - let var_ty = self.local_decls[local_id].ty; let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); self.schedule_drop( span, region_scope, local_id, - var_ty, DropKind::Value, ); } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 17932ae85576..9414113cefb5 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -829,12 +829,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Function arguments always get the first Local indices after the return place let local = Local::new(index + 1); let place = Place::from(local); - let &ArgInfo(ty, opt_ty_info, arg_opt, ref self_binding) = arg_info; + let &ArgInfo(_, opt_ty_info, arg_opt, ref self_binding) = arg_info; // Make sure we drop (parts of) the argument even when not matched on. self.schedule_drop( arg_opt.as_ref().map_or(ast_body.span, |arg| arg.pat.span), - argument_scope, local, ty, DropKind::Value, + argument_scope, local, DropKind::Value, ); if let Some(arg) = arg_opt { diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index a26ec72584bd..9b4ea175e2a9 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -85,7 +85,6 @@ should go to. use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; use crate::hair::{Expr, ExprRef, LintLevel}; use rustc::middle::region; -use rustc::ty::Ty; use rustc::hir; use rustc::mir::*; use syntax_pos::{DUMMY_SP, Span}; @@ -173,11 +172,11 @@ struct BreakableScope<'tcx> { region_scope: region::Scope, /// Where the body of the loop begins. `None` if block continue_block: Option, - /// Block to branch into when the loop or block terminates (either by being `break`-en out - /// from, or by having its condition to become false) + /// Block to branch into when the loop or block terminates (either by being + /// `break`-en out from, or by having its condition to become false) break_block: BasicBlock, - /// The destination of the loop/block expression itself (i.e., where to put the result of a - /// `break` expression) + /// The destination of the loop/block expression itself (i.e., where to put + /// the result of a `break` expression) break_destination: Place<'tcx>, } @@ -728,10 +727,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, region_scope: region::Scope, local: Local, - place_ty: Ty<'tcx>, ) { - self.schedule_drop(span, region_scope, local, place_ty, DropKind::Storage); - self.schedule_drop(span, region_scope, local, place_ty, DropKind::Value); + self.schedule_drop(span, region_scope, local, DropKind::Storage); + self.schedule_drop(span, region_scope, local, DropKind::Value); } /// Indicates that `place` should be dropped on exit from From 75a297573f4dea4bc6c6898f36d8cecb212ef8e7 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Sat, 28 Sep 2019 17:07:18 +0300 Subject: [PATCH 011/545] Enhance report-time option --- src/librustdoc/test.rs | 1 + src/libsyntax_ext/test.rs | 44 +++++ src/libtest/formatters/json.rs | 9 + src/libtest/formatters/pretty.rs | 136 ++++++++----- src/libtest/formatters/terse.rs | 2 +- src/libtest/lib.rs | 324 +++++++++++++++++++++++++++---- src/libtest/stats.rs | 2 +- src/libtest/tests.rs | 125 +++++++++++- 8 files changed, 547 insertions(+), 96 deletions(-) diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 6576165b6ce7..d7cec02f8aeb 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -702,6 +702,7 @@ impl Tester for Collector { // compiler failures are test failures should_panic: testing::ShouldPanic::No, allow_fail: config.allow_fail, + test_type: testing::TestType::DocTest, }, testfn: testing::DynTestFn(box move || { let res = run_test( diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 5d68a92579f9..d4638c45473b 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -106,6 +106,11 @@ pub fn expand_test_or_bench( cx.path(sp, vec![test_id, cx.ident_of("ShouldPanic", sp), cx.ident_of(name, sp)]) }; + // creates test::TestType::$name + let test_type_path = |name| { + cx.path(sp, vec![test_id, cx.ident_of("TestType", sp), cx.ident_of(name, sp)]) + }; + // creates $name: $expr let field = |name, expr| cx.field_imm(sp, cx.ident_of(name, sp), expr); @@ -181,6 +186,17 @@ pub fn expand_test_or_bench( 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(...) @@ -261,6 +277,34 @@ fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { } } +enum TestType { + UnitTest, + IntegrationTest, + Unknown, +} + +/// Attempts to determine the type of test. +/// Since doctests are created without macro expanding, only possible variants here +/// are `UnitTest`, `IntegrationTest` or `Unknown`. +fn test_type(cx: &ExtCtxt<'_>) -> TestType { + // Root path from context contains the topmost sources directory of the crate. + // I.e., for `project` with sources in `src` and tests in `tests` folders + // (no matter how many nested folders lie inside), + // there will be two different root paths: `/project/src` and `/project/tests`. + let crate_path = cx.root_path.as_path(); + + if crate_path.ends_with("src") { + // `/src` folder contains unit-tests. + TestType::UnitTest + } else if crate_path.ends_with("tests") { + // `/tests` folder contains integration tests. + TestType::IntegrationTest + } else { + // Crate layout doesn't match expected one, test type is unknown. + TestType::Unknown + } +} + 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; diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs index d9e4abf61c3d..dcd733620bf9 100644 --- a/src/libtest/formatters/json.rs +++ b/src/libtest/formatters/json.rs @@ -94,6 +94,15 @@ impl OutputFormatter for JsonFormatter { self.write_event("test", desc.name.as_slice(), "failed", exec_time, stdout, None) } + TrTimedFail => self.write_event( + "test", + desc.name.as_slice(), + "failed", + exec_time, + stdout, + Some(r#""reason": "time limit exceeded""#), + ), + TrFailedMsg(ref m) => self.write_event( "test", desc.name.as_slice(), diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs index 184726c67d3f..58824a3952ac 100644 --- a/src/libtest/formatters/pretty.rs +++ b/src/libtest/formatters/pretty.rs @@ -3,6 +3,7 @@ use super::*; pub(crate) struct PrettyFormatter { out: OutputLocation, use_color: bool, + time_options: Option, /// Number of columns to fill when aligning names max_name_len: usize, @@ -16,12 +17,14 @@ impl PrettyFormatter { use_color: bool, max_name_len: usize, is_multithreaded: bool, + time_options: Option, ) -> Self { PrettyFormatter { out, use_color, max_name_len, is_multithreaded, + time_options } } @@ -30,20 +33,24 @@ impl PrettyFormatter { &self.out } - pub fn write_ok(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> { - self.write_short_result("ok", term::color::GREEN, exec_time) + pub fn write_ok(&mut self) -> io::Result<()> { + self.write_short_result("ok", term::color::GREEN) } - pub fn write_failed(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> { - self.write_short_result("FAILED", term::color::RED, exec_time) + pub fn write_failed(&mut self) -> io::Result<()> { + self.write_short_result("FAILED", term::color::RED) } - pub fn write_ignored(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> { - self.write_short_result("ignored", term::color::YELLOW, exec_time) + pub fn write_ignored(&mut self) -> io::Result<()> { + self.write_short_result("ignored", term::color::YELLOW) } - pub fn write_allowed_fail(&mut self, exec_time: Option<&TestExecTime>) -> io::Result<()> { - self.write_short_result("FAILED (allowed)", term::color::YELLOW, exec_time) + pub fn write_allowed_fail(&mut self) -> io::Result<()> { + self.write_short_result("FAILED (allowed)", term::color::YELLOW) + } + + pub fn write_time_failed(&mut self) -> io::Result<()> { + self.write_short_result("FAILED (time limit exceeded)", term::color::RED) } pub fn write_bench(&mut self) -> io::Result<()> { @@ -54,13 +61,8 @@ impl PrettyFormatter { &mut self, result: &str, color: term::color::Color, - exec_time: Option<&TestExecTime>, ) -> io::Result<()> { - self.write_pretty(result, color)?; - if let Some(exec_time) = exec_time { - self.write_plain(format!(" {}", exec_time))?; - } - self.write_plain("\n") + self.write_pretty(result, color) } pub fn write_pretty(&mut self, word: &str, color: term::color::Color) -> io::Result<()> { @@ -88,12 +90,48 @@ impl PrettyFormatter { self.out.flush() } - pub fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> { - self.write_plain("\nsuccesses:\n")?; - let mut successes = Vec::new(); + fn write_time( + &mut self, + desc: &TestDesc, + exec_time: Option<&TestExecTime> + ) -> io::Result<()> { + if let (Some(opts), Some(time)) = (self.time_options, exec_time) { + let time_str = format!(" <{}>", time); + + let color = if opts.colored { + if opts.is_critical(desc, time) { + Some(term::color::RED) + } else if opts.is_warn(desc, time) { + Some(term::color::YELLOW) + } else { + None + } + } else { + None + }; + + match color { + Some(color) => self.write_pretty(&time_str, color)?, + None => self.write_plain(&time_str)? + } + } + + Ok(()) + } + + fn write_results( + &mut self, + inputs: &Vec<(TestDesc, Vec)>, + results_type: &str + ) -> io::Result<()> { + let results_out_str = format!("\n{}:\n", results_type); + + self.write_plain(&results_out_str)?; + + let mut results = Vec::new(); let mut stdouts = String::new(); - for &(ref f, ref stdout) in &state.not_failures { - successes.push(f.name.to_string()); + for &(ref f, ref stdout) in inputs { + results.push(f.name.to_string()); if !stdout.is_empty() { stdouts.push_str(&format!("---- {} stdout ----\n", f.name)); let output = String::from_utf8_lossy(stdout); @@ -106,38 +144,24 @@ impl PrettyFormatter { self.write_plain(&stdouts)?; } - self.write_plain("\nsuccesses:\n")?; - successes.sort(); - for name in &successes { + self.write_plain(&results_out_str)?; + results.sort(); + for name in &results { self.write_plain(&format!(" {}\n", name))?; } Ok(()) } - pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> { - self.write_plain("\nfailures:\n")?; - let mut failures = Vec::new(); - let mut fail_out = String::new(); - for &(ref f, ref stdout) in &state.failures { - failures.push(f.name.to_string()); - if !stdout.is_empty() { - fail_out.push_str(&format!("---- {} stdout ----\n", f.name)); - let output = String::from_utf8_lossy(stdout); - fail_out.push_str(&output); - fail_out.push_str("\n"); - } - } - if !fail_out.is_empty() { - self.write_plain("\n")?; - self.write_plain(&fail_out)?; - } + pub fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> { + self.write_results(&state.not_failures, "successes") + } - self.write_plain("\nfailures:\n")?; - failures.sort(); - for name in &failures { - self.write_plain(&format!(" {}\n", name))?; - } - Ok(()) + pub fn write_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> { + self.write_results(&state.failures, "failures") + } + + pub fn write_time_failures(&mut self, state: &ConsoleTestState) -> io::Result<()> { + self.write_results(&state.time_failures, "failures (time limit exceeded)") } fn write_test_name(&mut self, desc: &TestDesc) -> io::Result<()> { @@ -179,15 +203,19 @@ impl OutputFormatter for PrettyFormatter { } match *result { - TrOk => self.write_ok(exec_time), - TrFailed | TrFailedMsg(_) => self.write_failed(exec_time), - TrIgnored => self.write_ignored(exec_time), - TrAllowedFail => self.write_allowed_fail(exec_time), + TrOk => self.write_ok()?, + TrFailed | TrFailedMsg(_) => self.write_failed()?, + TrIgnored => self.write_ignored()?, + TrAllowedFail => self.write_allowed_fail()?, TrBench(ref bs) => { self.write_bench()?; - self.write_plain(&format!(": {}\n", fmt_bench_samples(bs))) + self.write_plain(&format!(": {}\n", fmt_bench_samples(bs)))?; } + TrTimedFail => self.write_time_failed()?, } + + self.write_time(desc, exec_time)?; + self.write_plain("\n") } fn write_timeout(&mut self, desc: &TestDesc) -> io::Result<()> { @@ -207,7 +235,13 @@ impl OutputFormatter for PrettyFormatter { } let success = state.failed == 0; if !success { - self.write_failures(state)?; + if !state.failures.is_empty() { + self.write_failures(state)?; + } + + if !state.time_failures.is_empty() { + self.write_time_failures(state)?; + } } self.write_plain("\ntest result: ")?; diff --git a/src/libtest/formatters/terse.rs b/src/libtest/formatters/terse.rs index 1812c20904c8..8914e7b6b568 100644 --- a/src/libtest/formatters/terse.rs +++ b/src/libtest/formatters/terse.rs @@ -180,7 +180,7 @@ impl OutputFormatter for TerseFormatter { ) -> io::Result<()> { match *result { TrOk => self.write_ok(), - TrFailed | TrFailedMsg(_) => self.write_failed(), + TrFailed | TrFailedMsg(_) | TrTimedFail => self.write_failed(), TrIgnored => self.write_ignored(), TrAllowedFail => self.write_allowed_fail(), TrBench(ref bs) => { diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index f04d289c4ef3..729bc4a51499 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -56,6 +56,7 @@ use std::panic::{self, catch_unwind, AssertUnwindSafe, PanicInfo}; use std::path::PathBuf; use std::process; use std::process::{ExitStatus, Command, Termination}; +use std::str::FromStr; use std::sync::mpsc::{channel, Sender}; use std::sync::{Arc, Mutex}; use std::thread; @@ -75,13 +76,54 @@ const SECONDARY_TEST_INVOKER_VAR: &'static str = "__RUST_TEST_INVOKE"; const TR_OK: i32 = 50; const TR_FAILED: i32 = 51; +/// This small module contains constants used by `report-time` option. +/// Those constants values will be used if corresponding environment variables are not set. +/// +/// To override values for unit-tests, use a constant `RUST_TEST_TIME_UNIT`, +/// To override values for integration tests, use a constant `RUST_TEST_TIME_INTEGRATION`, +/// To override values for doctests, use a constant `RUST_TEST_TIME_DOCTEST`. +/// +/// Example of the expected format is `RUST_TEST_TIME_xxx=100,200`, where 100 means +/// warn time, and 200 means critical time. +pub mod time_constants { + use std::time::Duration; + use super::TEST_WARN_TIMEOUT_S; + + /// Environment variable for overriding default threshold for unit-tests. + pub const UNIT_ENV_NAME: &str = "RUST_TEST_TIME_UNIT"; + + // Unit tests are supposed to be really quick. + pub const UNIT_WARN: Duration = Duration::from_millis(50); + pub const UNIT_CRITICAL: Duration = Duration::from_millis(100); + + /// Environment variable for overriding default threshold for unit-tests. + pub const INTEGRATION_ENV_NAME: &str = "RUST_TEST_TIME_INTEGRATION"; + + // Integration tests may have a lot of work, so they can take longer to execute. + pub const INTEGRATION_WARN: Duration = Duration::from_millis(500); + pub const INTEGRATION_CRITICAL: Duration = Duration::from_millis(1000); + + /// Environment variable for overriding default threshold for unit-tests. + pub const DOCTEST_ENV_NAME: &str = "RUST_TEST_TIME_DOCTEST"; + + // Doctests are similar to integration tests, because they can include a lot of + // initialization code. + pub const DOCTEST_WARN: Duration = INTEGRATION_WARN; + pub const DOCTEST_CRITICAL: Duration = INTEGRATION_CRITICAL; + + // Do not suppose anything about unknown tests, base limits on the + // `TEST_WARN_TIMEOUT_S` constant. + pub const UNKNOWN_WARN: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S); + pub const UNKNOWN_CRITICAL: Duration = Duration::from_secs(TEST_WARN_TIMEOUT_S * 2); +} + // to be used by rustc to compile tests in libtest pub mod test { pub use crate::{ assert_test_result, filter_tests, parse_opts, run_test, test_main, test_main_static, Bencher, DynTestFn, DynTestName, Metric, MetricMap, Options, RunIgnored, RunStrategy, ShouldPanic, StaticBenchFn, StaticTestFn, StaticTestName, TestDesc, TestDescAndFn, TestName, - TestOpts, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk, + TestOpts, TestTimeOptions, TestType, TestResult, TrFailed, TrFailedMsg, TrIgnored, TrOk, }; } @@ -97,6 +139,21 @@ pub enum Concurrent { No, } +/// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html) +/// conventions. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +pub enum TestType { + /// Unit-tests are expected to be in the `src` folder of the crate. + UnitTest, + /// Integration-style tests are expected to be in the `tests` folder of the crate. + IntegrationTest, + /// Doctests are created by the `librustdoc` manually, so it's a different type of test. + DocTest, + /// Tests for the sources that don't follow the project layout convention + /// (e.g. tests in raw `main.rs` compiled by calling `rustc --test` directly). + Unknown, +} + // The name of a test. By convention this follows the rules for rust // paths; i.e., it should be a series of identifiers separated by double // colons. This way if some test runner wants to arrange the tests @@ -232,6 +289,7 @@ pub struct TestDesc { pub ignore: bool, pub should_panic: ShouldPanic, pub allow_fail: bool, + pub test_type: TestType, } #[derive(Debug)] @@ -403,6 +461,133 @@ pub enum RunIgnored { Only, } +/// Structure denoting time limits for test execution. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct TimeThreshold { + pub warn: Duration, + pub critical: Duration, +} + +impl TimeThreshold { + /// Creates a new `TimeThreshold` instance with provided durations. + pub fn new(warn: Duration, critical: Duration) -> Self { + Self { + warn, + critical, + } + } + + /// Attempts to create a `TimeThreshold` instance with values obtained + /// from the environment variable, and returns `None` if the variable + /// is not set. + /// Environment variable format is expected to match `\d+,\d+`. + /// + /// # Panics + /// + /// Panics if variable with provided name is set but contains inappropriate + /// value. + pub fn from_env_var(env_var_name: &str) -> Option { + let durations_str = env::var(env_var_name).ok()?; + + // Split string into 2 substrings by comma and try to parse numbers. + let durations: Vec = durations_str + .splitn(2, ',') + .map(|v| { + u64::from_str(v).unwrap_or_else(|_| { + panic!( + "Duration value in variable {} is expected to be a number, but got {}", + env_var_name, v + ) + }) + }) + .collect(); + + // Check that we have exactly 2 numbers. + if durations.len() != 2 { + panic!( + "Duration variable {} expected to have 2 numbers separated by comma, but got {}", + env_var_name, durations.len() + ); + } + + let (warn, critical) = (durations[0], durations[1]); + + Some(Self::new(Duration::from_millis(warn), Duration::from_millis(critical))) + } +} + +/// Structure with parameters for calculating test execution time. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct TestTimeOptions { + pub error_on_excess: bool, + pub colored: bool, + pub unit_threshold: TimeThreshold, + pub integration_threshold: TimeThreshold, + pub doctest_threshold: TimeThreshold, +} + +impl TestTimeOptions { + pub fn new_from_env(error_on_excess: bool, colored: bool) -> Self { + let unit_threshold = + TimeThreshold::from_env_var(time_constants::UNIT_ENV_NAME) + .unwrap_or_else(Self::default_unit); + + let integration_threshold = + TimeThreshold::from_env_var(time_constants::INTEGRATION_ENV_NAME) + .unwrap_or_else(Self::default_integration); + + let doctest_threshold = + TimeThreshold::from_env_var(time_constants::DOCTEST_ENV_NAME) + .unwrap_or_else(Self::default_doctest); + + Self { + error_on_excess, + colored, + unit_threshold, + integration_threshold, + doctest_threshold, + } + } + + pub fn is_warn(&self, test: &TestDesc, exec_time: &TestExecTime) -> bool { + exec_time.0 >= self.warn_time(test) + } + + pub fn is_critical(&self, test: &TestDesc, exec_time: &TestExecTime) -> bool { + exec_time.0 >= self.critical_time(test) + } + + fn warn_time(&self, test: &TestDesc) -> Duration { + match test.test_type { + TestType::UnitTest => self.unit_threshold.warn, + TestType::IntegrationTest => self.integration_threshold.warn, + TestType::DocTest => self.doctest_threshold.warn, + TestType::Unknown => time_constants::UNKNOWN_WARN, + } + } + + fn critical_time(&self, test: &TestDesc) -> Duration { + match test.test_type { + TestType::UnitTest => self.unit_threshold.critical, + TestType::IntegrationTest => self.integration_threshold.critical, + TestType::DocTest => self.doctest_threshold.critical, + TestType::Unknown => time_constants::UNKNOWN_CRITICAL, + } + } + + fn default_unit() -> TimeThreshold { + TimeThreshold::new(time_constants::UNIT_WARN, time_constants::UNIT_CRITICAL) + } + + fn default_integration() -> TimeThreshold { + TimeThreshold::new(time_constants::INTEGRATION_WARN, time_constants::INTEGRATION_CRITICAL) + } + + fn default_doctest() -> TimeThreshold { + TimeThreshold::new(time_constants::DOCTEST_WARN, time_constants::DOCTEST_CRITICAL) + } +} + #[derive(Debug)] pub struct TestOpts { pub list: bool, @@ -418,7 +603,7 @@ pub struct TestOpts { pub format: OutputFormat, pub test_threads: Option, pub skip: Vec, - pub report_time: bool, + pub time_options: Option, pub options: Options, } @@ -502,10 +687,28 @@ fn optgroups() -> getopts::Options { unstable-options = Allow use of experimental features", "unstable-options", ) - .optflag( + .optflagopt( "", "report-time", - "Show execution time of each test. Not available for --format=terse" + "Show execution time of each test. Awailable values: + plain = do not colorize the execution time (default); + colored = colorize output according to the `color` parameter value; + + Threshold values for colorized output can be configured via + `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and + `RUST_TEST_TIME_DOCTEST` environment variables. + + Not available for --format=terse", + "plain|colored" + ) + .optflag( + "", + "ensure-test-time", + "Treat excess of the test execution time limit as error. + + Threshold values for this option can be configured via + `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and + `RUST_TEST_TIME_DOCTEST` environment variables." ); return opts; } @@ -554,6 +757,21 @@ fn is_nightly() -> bool { bootstrap || !disable_unstable_features } +// Gets the option value and checks if unstable features are enabled. +macro_rules! unstable_optflag { + ($matches:ident, $allow_unstable:ident, $option_name:literal) => {{ + let opt = $matches.opt_present($option_name); + if !$allow_unstable && opt { + return Some(Err(format!( + "The \"{}\" flag is only accepted on the nightly compiler", + $option_name + ))); + } + + opt + }}; +} + // Parses command line arguments into test options pub fn parse_opts(args: &[String]) -> Option { let mut allow_unstable = false; @@ -592,26 +810,9 @@ pub fn parse_opts(args: &[String]) -> Option { None }; - let exclude_should_panic = matches.opt_present("exclude-should-panic"); - if !allow_unstable && exclude_should_panic { - return Some(Err( - "The \"exclude-should-panic\" flag is only accepted on the nightly compiler".into(), - )); - } + let exclude_should_panic = unstable_optflag!(matches, allow_unstable, "exclude-should-panic"); - let include_ignored = matches.opt_present("include-ignored"); - if !allow_unstable && include_ignored { - return Some(Err( - "The \"include-ignored\" flag is only accepted on the nightly compiler".into(), - )); - } - - let report_time = matches.opt_present("report-time"); - if !allow_unstable && report_time { - return Some(Err( - "The \"report-time\" flag is only accepted on the nightly compiler".into(), - )); - } + let include_ignored = unstable_optflag!(matches, allow_unstable, "include-ignored"); let run_ignored = match (include_ignored, matches.opt_present("ignored")) { (true, true) => { @@ -641,6 +842,19 @@ pub fn parse_opts(args: &[String]) -> Option { }; } + let report_time = unstable_optflag!(matches, allow_unstable, "report-time"); + let colored_opt_str = matches.opt_str("report-time"); + let report_time_colored = report_time && colored_opt_str == Some("colored".into()); + let ensure_test_time = unstable_optflag!(matches, allow_unstable, "ensure-test-time"); + + // If `ensure-test-time` option is provided, time output is enforced, + // so user won't be confused if any of tests will silently fail. + let time_options = if report_time || ensure_test_time { + Some(TestTimeOptions::new_from_env(ensure_test_time, report_time_colored)) + } else { + None + }; + let test_threads = match matches.opt_str("test-threads") { Some(n_str) => match n_str.parse::() { Ok(0) => return Some(Err("argument for --test-threads must not be 0".to_string())), @@ -706,20 +920,20 @@ pub fn parse_opts(args: &[String]) -> Option { format, test_threads, skip: matches.opt_strs("skip"), - report_time, + time_options, options: Options::new().display_output(matches.opt_present("show-output")), }; Some(Ok(test_opts)) } -#[derive(Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub struct BenchSamples { ns_iter_summ: stats::Summary, mb_s: usize, } -#[derive(Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub enum TestResult { TrOk, TrFailed, @@ -727,6 +941,7 @@ pub enum TestResult { TrIgnored, TrAllowedFail, TrBench(BenchSamples), + TrTimedFail, } unsafe impl Send for TestResult {} @@ -774,6 +989,7 @@ struct ConsoleTestState { metrics: MetricMap, failures: Vec<(TestDesc, Vec)>, not_failures: Vec<(TestDesc, Vec)>, + time_failures: Vec<(TestDesc, Vec)>, options: Options, } @@ -796,6 +1012,7 @@ impl ConsoleTestState { metrics: MetricMap::new(), failures: Vec::new(), not_failures: Vec::new(), + time_failures: Vec::new(), options: opts.options, }) } @@ -831,11 +1048,12 @@ impl ConsoleTestState { TrIgnored => "ignored".to_owned(), TrAllowedFail => "failed (allowed)".to_owned(), TrBench(ref bs) => fmt_bench_samples(bs), + TrTimedFail => "failed (time limit exceeded)".to_owned(), }, test.name, ))?; if let Some(exec_time) = exec_time { - self.write_log(|| format!(" {}", exec_time))?; + self.write_log(|| format!(" <{}>", exec_time))?; } self.write_log(|| "\n") } @@ -993,6 +1211,10 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu stdout.extend_from_slice(format!("note: {}", msg).as_bytes()); st.failures.push((test, stdout)); } + TrTimedFail => { + st.failed += 1; + st.time_failures.push((test, stdout)); + } } Ok(()) } @@ -1018,6 +1240,7 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec) -> io::Resu use_color(opts), max_name_len, is_multithreaded, + opts.time_options, )), OutputFormat::Terse => Box::new(TerseFormatter::new( output, @@ -1487,15 +1710,20 @@ pub fn run_test( return; } + struct TestRunOpts { + pub nocapture: bool, + pub concurrency: Concurrent, + pub time: Option, + } + fn run_test_inner( desc: TestDesc, - nocapture: bool, - report_time: bool, strategy: RunStrategy, monitor_ch: Sender, testfn: Box, - concurrency: Concurrent, + opts: TestRunOpts, ) { + let concurrency = opts.concurrency; let name = desc.name.clone(); let runtest = move || { @@ -1518,6 +1746,12 @@ pub fn run_test( } } + let test_run_opts = TestRunOpts { + nocapture: opts.nocapture, + concurrency, + time: opts.time_options + }; + match testfn { DynBenchFn(bencher) => { // Benchmarks aren't expected to panic, so we run them all in-process. @@ -1538,8 +1772,6 @@ pub fn run_test( }; run_test_inner( desc, - opts.nocapture, - opts.report_time, strategy, monitor_ch, Box::new(move || __rust_begin_short_backtrace(f)), @@ -1548,12 +1780,10 @@ pub fn run_test( } StaticTestFn(f) => run_test_inner( desc, - opts.nocapture, - opts.report_time, strategy, monitor_ch, Box::new(move || __rust_begin_short_backtrace(f)), - concurrency, + test_run_opts, ), } } @@ -1564,10 +1794,13 @@ fn __rust_begin_short_backtrace(f: F) { f() } -fn calc_result<'a>(desc: &TestDesc, - task_result: Result<(), &'a (dyn Any + 'static + Send)>) +fn calc_result<'a>( + desc: &TestDesc, + task_result: Result<(), &'a (dyn Any + 'static + Send)>) + time_opts: &Option, + exec_time: &Option) -> TestResult { - match (&desc.should_panic, task_result) { + let result = match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk, (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => { if err @@ -1589,7 +1822,22 @@ fn calc_result<'a>(desc: &TestDesc, (&ShouldPanic::Yes, Ok(())) => TrFailedMsg("test did not panic as expected".to_string()), _ if desc.allow_fail => TrAllowedFail, _ => TrFailed, + }; + + + // If test is already failed (or allowed to fail), do not change the result. + if result != TrOk { + return result; } + + // Check if test is failed due to timeout. + if let (Some(opts), Some(time)) = (time_opts, exec_time) { + if opts.error_on_excess && opts.is_critical(desc, time) { + return TrTimedFail; + } + } + + result } fn get_result_from_exit_code(desc: &TestDesc, code: i32) -> TestResult { diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 6577ec8ad239..aab8d012fdf6 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -115,7 +115,7 @@ pub trait Stats { } /// Extracted collection of all the summary statistics of a sample set. -#[derive(Clone, PartialEq, Copy)] +#[derive(Debug, Clone, PartialEq, Copy)] #[allow(missing_docs)] pub struct Summary { pub sum: f64, diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs index b95fb5df710d..d345c8503812 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -2,10 +2,11 @@ use super::*; use crate::test::{ filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, RunStrategy, - ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailedMsg, - TrIgnored, TrOk, + ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TestTimeOptions, + TestType, TrFailedMsg, TrIgnored, TrOk, }; use std::sync::mpsc::channel; +use std::time::Duration; impl TestOpts { fn new() -> TestOpts { @@ -23,7 +24,7 @@ impl TestOpts { format: OutputFormat::Pretty, test_threads: None, skip: vec![], - report_time: false, + time_options: None, options: Options::new(), } } @@ -37,6 +38,7 @@ fn one_ignored_one_unignored_test() -> Vec { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(move || {})), }, @@ -46,6 +48,7 @@ fn one_ignored_one_unignored_test() -> Vec { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(move || {})), }, @@ -63,6 +66,7 @@ pub fn do_not_run_ignored_tests() { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -81,6 +85,7 @@ pub fn ignored_tests_result_in_ignored() { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -101,6 +106,7 @@ fn test_should_panic() { ignore: false, should_panic: ShouldPanic::Yes, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -121,6 +127,7 @@ fn test_should_panic_good_message() { ignore: false, should_panic: ShouldPanic::YesWithMessage("error message"), allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -143,6 +150,7 @@ fn test_should_panic_bad_message() { ignore: false, should_panic: ShouldPanic::YesWithMessage(expected), allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -161,6 +169,7 @@ fn test_should_panic_but_succeeds() { ignore: false, should_panic: ShouldPanic::Yes, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -178,11 +187,18 @@ fn report_time_test_template(report_time: bool) -> Option { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; + let time_options = if report_time { + Some(TestTimeOptions::default()) + } else { + None + }; + let test_opts = TestOpts { - report_time, + time_options, ..TestOpts::new() }; let (tx, rx) = channel(); @@ -203,6 +219,97 @@ fn test_should_report_time() { assert!(exec_time.is_some()); } +fn time_test_failure_template(test_type: TestType) -> TestResult { + fn f() {} + let desc = TestDescAndFn { + desc: TestDesc { + name: StaticTestName("whatever"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + test_type + }, + testfn: DynTestFn(Box::new(f)), + }; + // `Default` will initialize all the thresholds to 0 milliseconds. + let mut time_options = TestTimeOptions::default(); + time_options.error_on_excess = true; + + let test_opts = TestOpts { + time_options: Some(time_options), + ..TestOpts::new() + }; + let (tx, rx) = channel(); + run_test(&test_opts, false, desc, tx, Concurrent::No); + let (_, result, _, _) = rx.recv().unwrap(); + + result +} + +#[test] +fn test_error_on_exceed() { + let types = [TestType::UnitTest, TestType::IntegrationTest, TestType::DocTest]; + + for test_type in types.into_iter() { + let result = time_test_failure_template(*test_type); + + assert_eq!(result, TestResult::TrTimedFail); + } + + // Check that for unknown tests thresholds aren't applied. + let result = time_test_failure_template(TestType::Unknown); + assert_eq!(result, TestResult::TrOk); +} + +fn typed_test_desc(test_type: TestType) -> TestDesc { + TestDesc { + name: StaticTestName("whatever"), + ignore: false, + should_panic: ShouldPanic::No, + allow_fail: false, + test_type + } +} + +fn test_exec_time(millis: u64) -> TestExecTime { + TestExecTime(Duration::from_millis(millis)) +} + +#[test] +fn test_time_options_threshold() { + let unit = TimeThreshold::new(Duration::from_millis(50), Duration::from_millis(100)); + let integration = TimeThreshold::new(Duration::from_millis(500), Duration::from_millis(1000)); + let doc = TimeThreshold::new(Duration::from_millis(5000), Duration::from_millis(10000)); + + let options = TestTimeOptions { + error_on_excess: false, + colored: false, + unit_threshold: unit.clone(), + integration_threshold: integration.clone(), + doctest_threshold: doc.clone(), + }; + + let test_vector = [ + (TestType::UnitTest, unit.warn.as_millis() - 1, false, false), + (TestType::UnitTest, unit.warn.as_millis(), true, false), + (TestType::UnitTest, unit.critical.as_millis(), true, true), + (TestType::IntegrationTest, integration.warn.as_millis() - 1, false, false), + (TestType::IntegrationTest, integration.warn.as_millis(), true, false), + (TestType::IntegrationTest, integration.critical.as_millis(), true, true), + (TestType::DocTest, doc.warn.as_millis() - 1, false, false), + (TestType::DocTest, doc.warn.as_millis(), true, false), + (TestType::DocTest, doc.critical.as_millis(), true, true), + ]; + + for (test_type, time, expected_warn, expected_critical) in test_vector.into_iter() { + let test_desc = typed_test_desc(*test_type); + let exec_time = test_exec_time(*time as u64); + + assert_eq!(options.is_warn(&test_desc, &exec_time), *expected_warn); + assert_eq!(options.is_critical(&test_desc, &exec_time), *expected_critical); + } +} + #[test] fn parse_ignored_flag() { let args = vec![ @@ -284,6 +391,7 @@ pub fn exclude_should_panic_option() { ignore: false, should_panic: ShouldPanic::Yes, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(move || {})), }); @@ -305,6 +413,7 @@ pub fn exact_filter_match() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(move || {})), }) @@ -416,6 +525,7 @@ pub fn sort_tests() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(testfn)), }; @@ -492,6 +602,7 @@ pub fn test_bench_no_iter() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }; crate::bench::benchmark(desc, tx, true, f); @@ -511,6 +622,7 @@ pub fn test_bench_iter() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }; crate::bench::benchmark(desc, tx, true, f); @@ -524,6 +636,7 @@ fn should_sort_failures_before_printing_them() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }; let test_b = TestDesc { @@ -531,9 +644,10 @@ fn should_sort_failures_before_printing_them() { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }; - let mut out = PrettyFormatter::new(Raw(Vec::new()), false, 10, false); + let mut out = PrettyFormatter::new(Raw(Vec::new()), false, 10, false, None); let st = ConsoleTestState { log_out: None, @@ -548,6 +662,7 @@ fn should_sort_failures_before_printing_them() { failures: vec![(test_b, Vec::new()), (test_a, Vec::new())], options: Options::new(), not_failures: Vec::new(), + time_failures: Vec::new(), }; out.write_failures(&st).unwrap(); From f2b84788fb01ffec92d3b6eac5908bd892fc1576 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Sun, 29 Sep 2019 08:52:32 +0300 Subject: [PATCH 012/545] libtest: encapsulate time-related logic and avoid unnecessary allocations --- src/libtest/lib.rs | 58 +++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 729bc4a51499..8a8ea7452932 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -490,7 +490,7 @@ impl TimeThreshold { let durations_str = env::var(env_var_name).ok()?; // Split string into 2 substrings by comma and try to parse numbers. - let durations: Vec = durations_str + let mut durations = durations_str .splitn(2, ',') .map(|v| { u64::from_str(v).unwrap_or_else(|_| { @@ -499,18 +499,20 @@ impl TimeThreshold { env_var_name, v ) }) - }) - .collect(); + }); - // Check that we have exactly 2 numbers. - if durations.len() != 2 { + // Callback to be called if the environment variable has unexpected structure. + let panic_on_incorrect_value = || { panic!( "Duration variable {} expected to have 2 numbers separated by comma, but got {}", - env_var_name, durations.len() + env_var_name, durations_str ); - } + }; - let (warn, critical) = (durations[0], durations[1]); + let (warn, critical) = ( + durations.next().unwrap_or_else(panic_on_incorrect_value), + durations.next().unwrap_or_else(panic_on_incorrect_value) + ); Some(Self::new(Duration::from_millis(warn), Duration::from_millis(critical))) } @@ -519,6 +521,8 @@ impl TimeThreshold { /// Structure with parameters for calculating test execution time. #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub struct TestTimeOptions { + /// Denotes if the test critical execution time limit excess should be considered + /// a test failure. pub error_on_excess: bool, pub colored: bool, pub unit_threshold: TimeThreshold, @@ -609,6 +613,8 @@ pub struct TestOpts { /// Result of parsing the options. pub type OptRes = Result; +/// Result of parsing the option part. +type OptPartRes = Result, String>; fn optgroups() -> getopts::Options { let mut opts = getopts::Options::new(); @@ -772,6 +778,27 @@ macro_rules! unstable_optflag { }}; } +// Gets the CLI options assotiated with `report-time` feature. +fn get_time_options( + matches: &getopts::Matches, + allow_unstable: bool) +-> Option> { + let report_time = unstable_optflag!(matches, allow_unstable, "report-time"); + let colored_opt_str = matches.opt_str("report-time"); + let report_time_colored = report_time && colored_opt_str == Some("colored".into()); + let ensure_test_time = unstable_optflag!(matches, allow_unstable, "ensure-test-time"); + + // If `ensure-test-time` option is provided, time output is enforced, + // so user won't be confused if any of tests will silently fail. + let options = if report_time || ensure_test_time { + Some(TestTimeOptions::new_from_env(ensure_test_time, report_time_colored)) + } else { + None + }; + + Some(Ok(options)) +} + // Parses command line arguments into test options pub fn parse_opts(args: &[String]) -> Option { let mut allow_unstable = false; @@ -842,17 +869,10 @@ pub fn parse_opts(args: &[String]) -> Option { }; } - let report_time = unstable_optflag!(matches, allow_unstable, "report-time"); - let colored_opt_str = matches.opt_str("report-time"); - let report_time_colored = report_time && colored_opt_str == Some("colored".into()); - let ensure_test_time = unstable_optflag!(matches, allow_unstable, "ensure-test-time"); - - // If `ensure-test-time` option is provided, time output is enforced, - // so user won't be confused if any of tests will silently fail. - let time_options = if report_time || ensure_test_time { - Some(TestTimeOptions::new_from_env(ensure_test_time, report_time_colored)) - } else { - None + let time_options = match get_time_options(&matches, allow_unstable) { + Some(Ok(val)) => val, + Some(Err(e)) => return Some(Err(e)), + x => panic!("Unexpected output from `get_time_options`: {:?}", x), }; let test_threads = match matches.opt_str("test-threads") { From f04ea6c7e1cdac012b31efcd97973f426571a97a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 30 Sep 2019 10:59:32 -0700 Subject: [PATCH 013/545] Document JSON message output. --- src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/command-line-arguments.md | 9 +- src/doc/rustc/src/json.md | 231 ++++++++++++++++++++ 3 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 src/doc/rustc/src/json.md diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 3cda8d927973..d5564fd798f3 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -10,6 +10,7 @@ - [Warn-by-default lints](lints/listing/warn-by-default.md) - [Deny-by-default lints](lints/listing/deny-by-default.md) - [Codegen options](codegen-options/index.md) +- [JSON Output](json.md) - [Targets](targets/index.md) - [Built-in Targets](targets/built-in.md) - [Custom Targets](targets/custom.md) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 5eea9c868790..b2cc65c11fd2 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -92,6 +92,7 @@ information about editions may be found in the [edition guide]. [edition guide]: ../edition-guide/introduction.html ## `--emit`: specifies the types of output files to generate + This flag controls the types of output files generated by the compiler. It accepts a comma-separated list of values, and may be specified multiple times. @@ -241,12 +242,13 @@ The "sysroot" is where `rustc` looks for the crates that come with the Rust distribution; this flag allows that to be overridden. ## `--error-format`: control how errors are produced + This flag lets you control the format of messages. Messages are printed to stderr. The valid options are: - `human` — Human-readable output. This is the default. -- `json` — Structured JSON output. +- `json` — Structured JSON output. See [the JSON chapter] for more detail. - `short` — Short, one-line messages. ## `--color`: configure coloring of output @@ -273,6 +275,7 @@ pathname syntax. For example `--remap-path-prefix foo=bar` will match `foo/lib.rs` but not `./foo/lib.rs`. ## `--json`: configure json messages printed by the compiler + When the `--error-format=json` option is passed to rustc then all of the compiler's diagnostic output will be emitted in the form of JSON blobs. The @@ -305,9 +308,13 @@ to customize the output: Note that it is invalid to combine the `--json` argument with the `--color` argument, and it is required to combine `--json` with `--error-format=json`. +See [the JSON chapter] for more detail. + ## `@path`: load command-line flags from a path If you specify `@path` on the command-line, then it will open `path` and read command line options from it. These options are one per line; a blank line indicates an empty option. The file can use Unix or Windows style line endings, and must be encoded as UTF-8. + +[the JSON chapter]: json.md diff --git a/src/doc/rustc/src/json.md b/src/doc/rustc/src/json.md new file mode 100644 index 000000000000..b73784951631 --- /dev/null +++ b/src/doc/rustc/src/json.md @@ -0,0 +1,231 @@ +# JSON Output + +This chapter documents the JSON structures emitted by `rustc`. JSON may be +enabled with the [`--error-format=json` flag][option-error-format]. Additional +options may be specified with the [`--json` flag][option-json] which can +change which messages are generated, and the format of the messages. + +JSON messages are emitted one per line to stderr. + +If parsing the output with Rust, the +[`cargo_metadata`](https://crates.io/crates/cargo_metadata) crate provides +some support for parsing the messages. + +When parsing, care should be taken to be forwards-compatible with future changes +to the format. Optional values may be `null`. New fields may be added. Enumerated +fields like "level" or "suggestion_applicability" may add new values. + +## Diagnostics + +Diagnostic messages provide errors or possible concerns generated during +compilation. `rustc` provides detailed information about where the diagnostic +originates, along with hints and suggestions. + +Diagnostics are arranged in a parent/child relationship where the parent +diagnostic value is the core of the diagnostic, and the attached children +provide additional context, help, and information. + +Diagnostics have the following format: + +```javascript +{ + /* The primary message. */ + "message": "unused variable: `x`", + /* The diagnostic code. + Some messages may set this value to null. + */ + "code": { + /* A unique string identifying which diagnostic triggered. */ + "code": "unused_variables", + /* An optional string explaining more detail about the diagnostic code. */ + "explanation": null + }, + /* The severity of the diagnostic. + Values may be: + - "error": A fatal error that prevents compilation. + - "warning": A possible error or concern. + - "note": Additional information or context about the diagnostic. + - "help": A suggestion on how to resolve the diagnostic. + - "failure-note": A note attached to the message for further information. + - "error: internal compiler error": Indicates a bug within the compiler. + */ + "level": "warning", + /* An array of source code locations to point out specific details about + where the diagnostic originates from. This may be empty, for example + for some global messages, or child messages attached to a parent. + + Character offsets are offsets of Unicode Scalar Values. + */ + "spans": [ + { + /* The file where the span is located. + For spans located within a macro expansion, this will be the + name of the expanded macro in the format "". + */ + "file_name": "lib.rs", + /* The byte offset where the span starts (0-based, inclusive). */ + "byte_start": 21, + /* The byte offset where the span ends (0-based, exclusive). */ + "byte_end": 22, + /* The first line number of the span (1-based, inclusive). */ + "line_start": 2, + /* The last line number of the span (1-based, inclusive). */ + "line_end": 2, + /* The first character offset of the line_start (1-based, inclusive). */ + "column_start": 9, + /* The last character offset of the line_end (1-based, exclusive). */ + "column_end": 10, + /* Whether or not this is the "primary" span. + + This indicates that this span is the focal point of the + diagnostic. + + There are rare cases where multiple spans may be marked as + primary. For example, "immutable borrow occurs here" and + "mutable borrow ends here" can be two separate primary spans. + + The top (parent) message should always have at least one + primary span, unless it has zero spans. Child messages may have + zero or more primary spans. + */ + "is_primary": true, + /* An array of objects showing the original source code for this + span. This shows the entire lines of text where the span is + located. A span across multiple lines will have a separate + value for each line. + */ + "text": [ + { + /* The entire line of the original source code. */ + "text": " let x = 123;", + /* The first character offset of the line of + where the span covers this line (1-based, inclusive). */ + "highlight_start": 9, + /* The last character offset of the line of + where the span covers this line (1-based, exclusive). */ + "highlight_end": 10 + } + ], + /* An optional message to display at this span location. + This is typically null for primary spans. + */ + "label": null, + /* An optional string of a suggested replacement for this span to + solve the issue. Tools may try to replace the contents of the + span with this text. + */ + "suggested_replacement": null, + /* An optional string that indicates the confidence of the + "suggested_replacement". Tools may use this value to determine + whether or not suggestions should be automatically applied. + + Possible values may be: + - "MachineApplicable": The suggestion is definitely what the + user intended. This suggestion should be automatically + applied. + - "MaybeIncorrect": The suggestion may be what the user + intended, but it is uncertain. The suggestion should result + in valid Rust code if it is applied. + - "HasPlaceholders": The suggestion contains placeholders like + `(...)`. The suggestion cannot be applied automatically + because it will not result in valid Rust code. The user will + need to fill in the placeholders. + - "Unspecified": The applicability of the suggestion is unknown. + */ + "suggestion_applicability": null, + /* An optional object indicating the expansion of a macro within + this span. + + If a message occurs within a macro invocation, this object will + provide details of where within the macro expansion the message + is located. + */ + "expansion": { + /* The span of the macro invocation. + Uses the same span definition as the "spans" array. + */ + "span": {/*...*/} + /* Name of the macro, such as "foo!" or "#[derive(Eq)]". */ + "macro_decl_name": "some_macro!", + /* Optional span where the relevant part of the macro is + defined. */ + "def_site_span": {/*...*/}, + } + } + ], + /* Array of attached diagnostic messages. + This is an array of objects using the same format as the parent + message. Children are not nested (children do not themselves + contain "children" definitions). + */ + "children": [ + { + "message": "`#[warn(unused_variables)]` on by default", + "code": null, + "level": "note", + "spans": [], + "children": [], + "rendered": null + }, + { + "message": "consider prefixing with an underscore", + "code": null, + "level": "help", + "spans": [ + { + "file_name": "lib.rs", + "byte_start": 21, + "byte_end": 22, + "line_start": 2, + "line_end": 2, + "column_start": 9, + "column_end": 10, + "is_primary": true, + "text": [ + { + "text": " let x = 123;", + "highlight_start": 9, + "highlight_end": 10 + } + ], + "label": null, + "suggested_replacement": "_x", + "suggestion_applicability": "MachineApplicable", + "expansion": null + } + ], + "children": [], + "rendered": null + } + ], + /* Optional string of the rendered version of the diagnostic as displayed + by rustc. Note that this may be influenced by the `--json` flag. + */ + "rendered": "warning: unused variable: `x`\n --> lib.rs:2:9\n |\n2 | let x = 123;\n | ^ help: consider prefixing with an underscore: `_x`\n |\n = note: `#[warn(unused_variables)]` on by default\n\n" +} +``` + +## Artifact notifications + +Artifact notifications are emitted when the [`--json=artifacts` +flag][option-json] is used. They indicate that a file artifact has been saved +to disk. More information about emit kinds may be found in the [`--emit` +flag][option-emit] documentation. + +```javascript +{ + /* The filename that was generated. */ + "artifact": "libfoo.rlib", + /* The kind of artifact that was generated. Possible values: + - "link": The generated crate as specified by the crate-type. + - "dep-info": The `.d` file with dependency information in a Makefile-like syntax. + - "metadata": The Rust `.rmeta` file containing metadata about the crate. + - "save-analysis": A JSON file emitted by the `-Zsave-analysis` feature. + */ + "emit": "link" +} +``` + +[option-emit]: command-line-arguments.md#option-emit +[option-error-format]: command-line-arguments.md#option-error-format +[option-json]: command-line-arguments.md#option-json From 14192607d38f5501c75abea7a4a0e46349df5b5f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2019 10:25:45 +1000 Subject: [PATCH 014/545] Avoid `SmallVec::collect()` in `SubstsRef::super_fold_with()`. This commit reduces instruction counts for several benchmarks by up to 5%. --- src/librustc/ty/subst.rs | 43 ++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index e5bee3cfbd06..7d03881fff2c 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -383,14 +383,41 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { impl<'tcx> TypeFoldable<'tcx> for SubstsRef<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { - let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); - - // If folding doesn't change the substs, it's faster to avoid - // calling `mk_substs` and instead reuse the existing substs. - if params[..] == self[..] { - self - } else { - folder.tcx().intern_substs(¶ms) + // This code is hot enough that it's worth specializing for the most + // common length lists, to avoid the overhead of `SmallVec` creation. + // The match arms are in order of frequency. The 1, 2, and 0 cases are + // typically hit in 90--99.99% of cases. When folding doesn't change + // the substs, it's faster to reuse the existing substs rather than + // calling `intern_substs`. + match self.len() { + 1 => { + let param0 = self[0].fold_with(folder); + if param0 == self[0] { + self + } else { + folder.tcx().intern_substs(&[param0]) + } + } + 2 => { + let param0 = self[0].fold_with(folder); + let param1 = self[1].fold_with(folder); + if param0 == self[0] && param1 == self[1] { + self + } else { + folder.tcx().intern_substs(&[param0, param1]) + } + } + 0 => { + self + } + _ => { + let params: SmallVec<[_; 8]> = self.iter().map(|k| k.fold_with(folder)).collect(); + if params[..] == self[..] { + self + } else { + folder.tcx().intern_substs(¶ms) + } + } } } From 1937c200cd04e01e0a75cf694b9d6736972b921e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2019 11:57:36 +1000 Subject: [PATCH 015/545] Avoid `SmallVec::collect()` in `Result::intern_with()`. This commit reduces instruction counts for several benchmarks by up to 5%. --- src/librustc/ty/context.rs | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6c5d9a6dfdf2..f42cb88ded19 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2848,8 +2848,29 @@ impl<'a, T, R> InternIteratorElement for &'a T impl InternIteratorElement for Result { type Output = Result; - fn intern_with, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> Self::Output { - Ok(f(&iter.collect::, _>>()?)) + fn intern_with, F: FnOnce(&[T]) -> R>(mut iter: I, f: F) + -> Self::Output { + // This code is hot enough that it's worth specializing for the most + // common length lists, to avoid the overhead of `SmallVec` creation. + // The match arms are in order of frequency. The 1, 2, and 0 cases are + // typically hit in ~95% of cases. We assume that if the upper and + // lower bounds from `size_hint` agree they are correct. + Ok(match iter.size_hint() { + (1, Some(1)) => { + f(&[iter.next().unwrap()?]) + } + (2, Some(2)) => { + let t0 = iter.next().unwrap()?; + let t1 = iter.next().unwrap()?; + f(&[t0, t1]) + } + (0, Some(0)) => { + f(&[]) + } + _ => { + f(&iter.collect::, _>>()?) + } + }) } } From d1a7bb36ad0a5932384eac03d3fb834efc0317e5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Oct 2019 14:39:24 +1000 Subject: [PATCH 016/545] Avoid `SmallVec::collect()` in `List::super_fold_with()`. Also avoid interning when it's not necessary. This commit reduces instruction counts for a couple of benchmarks by up to 1%. --- src/librustc/ty/structural_impls.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 42d632d120ea..626d2e51b060 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -1223,8 +1223,21 @@ BraceStructTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with>(&self, folder: &mut F) -> Self { - let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); - folder.tcx().intern_predicates(&v) + // This code is hot enough that it's worth specializing for a list of + // length 0. (No other length is common enough to be worth singling + // out). + if self.len() == 0 { + self + } else { + // Don't bother interning if nothing changed, which is the common + // case. + let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); + if v[..] == self[..] { + self + } else { + folder.tcx().intern_predicates(&v) + } + } } fn super_visit_with>(&self, visitor: &mut V) -> bool { From e541b2ece9951fb00612e4fc14739634725cbf36 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 30 Sep 2019 13:44:13 +0200 Subject: [PATCH 017/545] Add E0551 long error explanation --- src/libsyntax/error_codes.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs index 8a78daee6e49..b0b898eccd6f 100644 --- a/src/libsyntax/error_codes.rs +++ b/src/libsyntax/error_codes.rs @@ -163,6 +163,25 @@ fn the_banished() {} // ok! ``` "##, +E0551: r##" +An invalid meta-item was used inside an attribute. + +Erroneous code example: + +```compile_fail,E0551 +#[deprecated(note)] // error! +fn i_am_deprecated() {} +``` + +Meta items are the key-value pairs inside of an attribute. To fix this issue, +you need to give a value to the `note` key. Example: + +``` +#[deprecated(note = "because")] // ok! +fn i_am_deprecated() {} +``` +"##, + E0552: r##" A unrecognized representation attribute was used. @@ -454,7 +473,6 @@ features in the `-Z allow_features` flag. // rustc_deprecated attribute must be paired with either stable or unstable // attribute E0549, - E0551, // incorrect meta item E0553, // multiple rustc_const_unstable attributes // E0555, // replaced with a generic attribute input check E0556, // malformed feature, expected just one word From 62f1fb33ec02d59d5984584fd4d04b0443af632b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 30 Sep 2019 13:44:23 +0200 Subject: [PATCH 018/545] Update ui tests --- src/test/ui/deprecation/deprecation-sanity.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/deprecation/deprecation-sanity.stderr b/src/test/ui/deprecation/deprecation-sanity.stderr index 15afa78b140d..57143d681055 100644 --- a/src/test/ui/deprecation/deprecation-sanity.stderr +++ b/src/test/ui/deprecation/deprecation-sanity.stderr @@ -54,5 +54,5 @@ LL | #[deprecated(since = "a", since = "b", note = "c")] error: aborting due to 9 previous errors -Some errors have detailed explanations: E0538, E0541, E0550, E0565. +Some errors have detailed explanations: E0538, E0541, E0550, E0551, E0565. For more information about an error, try `rustc --explain E0538`. From a5d931050e69df1bc07117a2891154a71a06a73e Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Tue, 24 Sep 2019 17:49:25 +0800 Subject: [PATCH 019/545] remove 'as_str' when it's already a str type. fix #62642 --- src/librustc_typeck/check/method/suggest.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 2d4d2e32f23d..e68e3211cade 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -518,7 +518,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if let Some(lev_candidate) = lev_candidate { + fn is_str_ref<'tcx>(ty: Ty<'tcx>) -> bool { + match ty.sty { + ty::Str => true, + ty::Ref(_, ty, _) => is_str_ref(&ty), + _ => false, + } + } + if item_name.as_str() == "as_str" && is_str_ref(&actual) { + err.span_suggestion( + span, + "try to remove `as_str`", + String::new(), + Applicability::MaybeIncorrect, + ); + } else if let Some(lev_candidate) = lev_candidate { let def_kind = lev_candidate.def_kind(); err.span_suggestion( span, From bb3c03049dbef28d18a7ca17b5b9d25f7c276b8e Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Tue, 24 Sep 2019 23:02:21 +0800 Subject: [PATCH 020/545] add test files --- src/librustc_typeck/check/method/suggest.rs | 2 +- src/test/ui/suggestions/remove-as_str.rs | 21 +++++++++++++++ src/test/ui/suggestions/remove-as_str.stderr | 27 ++++++++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/suggestions/remove-as_str.rs create mode 100644 src/test/ui/suggestions/remove-as_str.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index e68e3211cade..6efa30455921 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -518,7 +518,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn is_str_ref<'tcx>(ty: Ty<'tcx>) -> bool { + fn is_str_ref(ty: Ty<'_>) -> bool { match ty.sty { ty::Str => true, ty::Ref(_, ty, _) => is_str_ref(&ty), diff --git a/src/test/ui/suggestions/remove-as_str.rs b/src/test/ui/suggestions/remove-as_str.rs new file mode 100644 index 000000000000..d10300b48ba1 --- /dev/null +++ b/src/test/ui/suggestions/remove-as_str.rs @@ -0,0 +1,21 @@ +fn foo1(s: &str) { + s.as_str(); + //~^ ERROR no method named `as_str` found for type `&str` in the current scope +} + +fn foo2<'a>(s: &'a str) { + s.as_str(); + //~^ ERROR no method named `as_str` found for type `&'a str` in the current scope +} + +fn foo3(s: &mut str) { + s.as_str(); + //~^ ERROR no method named `as_str` found for type `&mut str` in the current scope +} + +fn foo4(s: &&str) { + s.as_str(); + //~^ ERROR no method named `as_str` found for type `&&str` in the current scope +} + +fn main() {} diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr new file mode 100644 index 000000000000..090a359fa68d --- /dev/null +++ b/src/test/ui/suggestions/remove-as_str.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `as_str` found for type `&str` in the current scope + --> $DIR/remove-as_str.rs:2:7 + | +LL | s.as_str(); + | ^^^^^^ help: try to remove `as_str` + +error[E0599]: no method named `as_str` found for type `&'a str` in the current scope + --> $DIR/remove-as_str.rs:7:7 + | +LL | s.as_str(); + | ^^^^^^ help: try to remove `as_str` + +error[E0599]: no method named `as_str` found for type `&mut str` in the current scope + --> $DIR/remove-as_str.rs:12:7 + | +LL | s.as_str(); + | ^^^^^^ help: try to remove `as_str` + +error[E0599]: no method named `as_str` found for type `&&str` in the current scope + --> $DIR/remove-as_str.rs:17:7 + | +LL | s.as_str(); + | ^^^^^^ help: try to remove `as_str` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. From 4cb86c908989087dca7d3ad2b5c9029c62aaf852 Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Wed, 25 Sep 2019 12:31:52 +0800 Subject: [PATCH 021/545] comment fixes --- src/librustc/ty/sty.rs | 4 ++++ src/librustc_typeck/check/method/suggest.rs | 11 ++--------- src/test/ui/suggestions/remove-as_str.stderr | 8 ++++---- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e105c44d09ae..dfd8168985c0 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1776,6 +1776,10 @@ impl<'tcx> TyS<'tcx> { #[inline] pub fn is_bool(&self) -> bool { self.kind == Bool } + /// Returns `true` if this type is a `str`. + #[inline] + pub fn is_str(&self) -> bool { self.sty == Str } + #[inline] pub fn is_param(&self, index: u32) -> bool { match self.kind { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 6efa30455921..89055628342b 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -518,17 +518,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - fn is_str_ref(ty: Ty<'_>) -> bool { - match ty.sty { - ty::Str => true, - ty::Ref(_, ty, _) => is_str_ref(&ty), - _ => false, - } - } - if item_name.as_str() == "as_str" && is_str_ref(&actual) { + if item_name.as_str() == "as_str" && actual.peel_refs().is_str() { err.span_suggestion( span, - "try to remove `as_str`", + "try removing `as_str`", String::new(), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr index 090a359fa68d..47196aa2c8ea 100644 --- a/src/test/ui/suggestions/remove-as_str.stderr +++ b/src/test/ui/suggestions/remove-as_str.stderr @@ -2,25 +2,25 @@ error[E0599]: no method named `as_str` found for type `&str` in the current scop --> $DIR/remove-as_str.rs:2:7 | LL | s.as_str(); - | ^^^^^^ help: try to remove `as_str` + | ^^^^^^ help: try removing `as_str` error[E0599]: no method named `as_str` found for type `&'a str` in the current scope --> $DIR/remove-as_str.rs:7:7 | LL | s.as_str(); - | ^^^^^^ help: try to remove `as_str` + | ^^^^^^ help: try removing `as_str` error[E0599]: no method named `as_str` found for type `&mut str` in the current scope --> $DIR/remove-as_str.rs:12:7 | LL | s.as_str(); - | ^^^^^^ help: try to remove `as_str` + | ^^^^^^ help: try removing `as_str` error[E0599]: no method named `as_str` found for type `&&str` in the current scope --> $DIR/remove-as_str.rs:17:7 | LL | s.as_str(); - | ^^^^^^ help: try to remove `as_str` + | ^^^^^^ help: try removing `as_str` error: aborting due to 4 previous errors From 5abc5e9b3df85ec6fa22e67e0ea624cd225d2007 Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Tue, 1 Oct 2019 15:22:52 +0800 Subject: [PATCH 022/545] add FIXME and use 'span_label' --- src/librustc_typeck/check/method/suggest.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 89055628342b..e9a8a52857ab 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -519,11 +519,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if item_name.as_str() == "as_str" && actual.peel_refs().is_str() { - err.span_suggestion( + // FIXME: the span is not quite correct, it should point to ".as_str()" instead + // of just "as_str". + err.span_label( span, - "try removing `as_str`", - String::new(), - Applicability::MaybeIncorrect, + "try removing `as_str`" ); } else if let Some(lev_candidate) = lev_candidate { let def_kind = lev_candidate.def_kind(); From 51482d0b75de535243032265269562ffa7538c46 Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Tue, 1 Oct 2019 15:29:09 +0800 Subject: [PATCH 023/545] fix unit tests --- src/test/ui/suggestions/remove-as_str.stderr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr index 47196aa2c8ea..2e8b72ebd4f6 100644 --- a/src/test/ui/suggestions/remove-as_str.stderr +++ b/src/test/ui/suggestions/remove-as_str.stderr @@ -2,25 +2,25 @@ error[E0599]: no method named `as_str` found for type `&str` in the current scop --> $DIR/remove-as_str.rs:2:7 | LL | s.as_str(); - | ^^^^^^ help: try removing `as_str` + | ^^^^^^ try removing `as_str` error[E0599]: no method named `as_str` found for type `&'a str` in the current scope --> $DIR/remove-as_str.rs:7:7 | LL | s.as_str(); - | ^^^^^^ help: try removing `as_str` + | ^^^^^^ try removing `as_str` error[E0599]: no method named `as_str` found for type `&mut str` in the current scope --> $DIR/remove-as_str.rs:12:7 | LL | s.as_str(); - | ^^^^^^ help: try removing `as_str` + | ^^^^^^ try removing `as_str` error[E0599]: no method named `as_str` found for type `&&str` in the current scope --> $DIR/remove-as_str.rs:17:7 | LL | s.as_str(); - | ^^^^^^ help: try removing `as_str` + | ^^^^^^ try removing `as_str` error: aborting due to 4 previous errors From 11c2d43485e92a00d86b3a5bc1655165b6b8371b Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Wed, 2 Oct 2019 12:09:30 +0800 Subject: [PATCH 024/545] typo fix in the code --- src/librustc/ty/sty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index dfd8168985c0..ebeb26be23df 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1778,7 +1778,7 @@ impl<'tcx> TyS<'tcx> { /// Returns `true` if this type is a `str`. #[inline] - pub fn is_str(&self) -> bool { self.sty == Str } + pub fn is_str(&self) -> bool { self.kind == Str } #[inline] pub fn is_param(&self, index: u32) -> bool { From 73b50d211b254bf72ce10b5ea4c3e0033e3189f4 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sun, 29 Sep 2019 19:22:18 -0400 Subject: [PATCH 025/545] Add support for 'extern const fn' This works just as you might expect - an 'extern const fn' is a 'const fn' that is callable from foreign code. Currently, panicking is not allowed in consts. When RFC 2345 is stabilized, then panicking in an 'extern const fn' will produce a compile-time error when invoked at compile time, and an abort when invoked at runtime. Since this is extending the language (we're allowing the `const` keyword in a new context), I believe that this will need an FCP. However, it's a very minor change, so I didn't think that filing an RFC was necessary. This will allow libc (and other FFI crates) to make many functions `const`, without having to give up on making them `extern` as well. --- src/libsyntax/feature_gate/active.rs | 3 + src/libsyntax/feature_gate/check.rs | 1 + src/libsyntax/parse/mod.rs | 2 + src/libsyntax/parse/parser.rs | 9 +++ src/libsyntax/parse/parser/item.rs | 52 ++++++++++------- src/libsyntax_pos/symbol.rs | 1 + .../const-extern-fn-call-extern-fn.rs | 23 ++++++++ .../const-extern-fn-call-extern-fn.stderr | 21 +++++++ .../const-extern-fn-min-const-fn.rs | 13 +++++ .../const-extern-fn-min-const-fn.stderr | 39 +++++++++++++ .../const-extern-fn-requires-unsafe.rs | 10 ++++ .../const-extern-fn-requires-unsafe.stderr | 19 +++++++ .../consts/const-extern-fn/const-extern-fn.rs | 35 ++++++++++++ .../feature-gate-const_extern_fn.rs | 12 ++++ .../feature-gate-const_extern_fn.stderr | 57 +++++++++++++++++++ .../ui/parser/no-const-fn-in-extern-block.rs | 8 +++ .../parser/no-const-fn-in-extern-block.stderr | 14 +++++ src/test/ui/reify-intrinsic.stderr | 4 +- 18 files changed, 302 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs create mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr create mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs create mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr create mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs create mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr create mode 100644 src/test/ui/consts/const-extern-fn/const-extern-fn.rs create mode 100644 src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs create mode 100644 src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr create mode 100644 src/test/ui/parser/no-const-fn-in-extern-block.rs create mode 100644 src/test/ui/parser/no-const-fn-in-extern-block.stderr diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 47ee41f0adc1..20a77fa37cf6 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -519,6 +519,9 @@ declare_features! ( /// Allows the use of or-patterns (e.g., `0 | 1`). (active, or_patterns, "1.38.0", Some(54883), None), + /// Allows the definition of `const extern fn` and `const unsafe extern fn`. + (active, const_extern_fn, "1.40.0", Some(64926), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index d7fc74955bbb..9e40b1a26ac1 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -821,6 +821,7 @@ pub fn check_crate(krate: &ast::Crate, gate_all!(async_closure, "async closures are unstable"); gate_all!(yields, generators, "yield syntax is experimental"); gate_all!(or_patterns, "or-patterns syntax is experimental"); + gate_all!(const_extern_fn, "`const extern fn` definitions are unstable"); visit::walk_crate(&mut visitor, krate); } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index fa4c10431228..1518da23b096 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -57,6 +57,8 @@ pub struct GatedSpans { pub yields: Lock>, /// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`. pub or_patterns: Lock>, + /// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`. + pub const_extern_fn: Lock>, } /// Info about a parsing session. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 95f84d5cb331..6b0b60bfe477 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1486,6 +1486,15 @@ impl<'a> Parser<'a> { Ok(()) } + /// Parses `extern` followed by an optional ABI string, or nothing. + fn parse_extern_abi(&mut self) -> PResult<'a, Abi> { + if self.eat_keyword(kw::Extern) { + Ok(self.parse_opt_abi()?.unwrap_or(Abi::C)) + } else { + Ok(Abi::Rust) + } + } + /// Parses a string as an ABI spec on an extern type or module. Consumes /// the `extern` keyword, if one is found. fn parse_opt_abi(&mut self) -> PResult<'a, Option> { diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index c00a5807d52c..d9fec72566cf 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -149,17 +149,23 @@ impl<'a> Parser<'a> { } if self.eat_keyword(kw::Const) { let const_span = self.prev_span; - if self.check_keyword(kw::Fn) - || (self.check_keyword(kw::Unsafe) - && self.is_keyword_ahead(1, &[kw::Fn])) { + if [kw::Fn, kw::Unsafe, kw::Extern].iter().any(|k| self.check_keyword(*k)) { // CONST FUNCTION ITEM + let unsafety = self.parse_unsafety(); - self.bump(); + + if self.check_keyword(kw::Extern) { + self.sess.gated_spans.const_extern_fn.borrow_mut().push( + lo.to(self.token.span) + ); + } + let abi = self.parse_extern_abi()?; + let header = FnHeader { unsafety, asyncness: respan(const_span, IsAsync::NotAsync), constness: respan(const_span, Constness::Const), - abi: Abi::Rust, + abi, }; return self.parse_item_fn(lo, visibility, attrs, header); } @@ -257,11 +263,7 @@ impl<'a> Parser<'a> { self.bump(); // `unsafe` // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic. self.check(&token::OpenDelim(token::Brace)); - let abi = if self.eat_keyword(kw::Extern) { - self.parse_opt_abi()?.unwrap_or(Abi::C) - } else { - Abi::Rust - }; + let abi = self.parse_extern_abi()?; self.expect_keyword(kw::Fn)?; let fn_span = self.prev_span; let header = FnHeader { @@ -834,11 +836,7 @@ impl<'a> Parser<'a> { let (constness, unsafety, abi) = if is_const_fn { (respan(const_span, Constness::Const), unsafety, Abi::Rust) } else { - let abi = if self.eat_keyword(kw::Extern) { - self.parse_opt_abi()?.unwrap_or(Abi::C) - } else { - Abi::Rust - }; + let abi = self.parse_extern_abi()?; (respan(self.prev_span, Constness::NotConst), unsafety, abi) }; if !self.eat_keyword(kw::Fn) { @@ -1278,14 +1276,30 @@ impl<'a> Parser<'a> { // Treat `const` as `static` for error recovery, but don't add it to expected tokens. if self.check_keyword(kw::Static) || self.token.is_keyword(kw::Const) { if self.token.is_keyword(kw::Const) { - self.diagnostic() - .struct_span_err(self.token.span, "extern items cannot be `const`") - .span_suggestion( + let mut err = self + .struct_span_err(self.token.span, "extern items cannot be `const`"); + + + // The user wrote 'const fn' + if self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) { + err.emit(); + // Consume `const` + self.bump(); + // Consume `unsafe` if present, since `extern` blocks + // don't allow it. This will leave behind a plain 'fn' + self.eat_keyword(kw::Unsafe); + // Treat 'const fn` as a plain `fn` for error recovery purposes. + // We've already emitted an error, so compilation is guaranteed + // to fail + return Ok(self.parse_item_foreign_fn(visibility, lo, attrs, extern_sp)?); + } + err.span_suggestion( self.token.span, "try using a static value", "static".to_owned(), Applicability::MachineApplicable - ).emit(); + ); + err.emit(); } self.bump(); // `static` or `const` return Ok(self.parse_item_foreign_static(visibility, lo, attrs)?); diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 1769135e7f21..38e55cb5c5df 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -196,6 +196,7 @@ symbols! { console, const_compare_raw_pointers, const_constructor, + const_extern_fn, const_fn, const_fn_union, const_generics, diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs new file mode 100644 index 000000000000..7c6a574a2110 --- /dev/null +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.rs @@ -0,0 +1,23 @@ +#![feature(const_extern_fn)] + +extern "C" { + fn regular_in_block(); +} + +const extern fn bar() { + unsafe { + regular_in_block(); + //~^ ERROR: cannot call functions with `"C"` abi in `min_const_fn` + } +} + +extern fn regular() {} + +const extern fn foo() { + unsafe { + regular(); + //~^ ERROR: cannot call functions with `"C"` abi in `min_const_fn` + } +} + +fn main() {} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr new file mode 100644 index 000000000000..d8bdf0a57cf6 --- /dev/null +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-call-extern-fn.stderr @@ -0,0 +1,21 @@ +error[E0723]: cannot call functions with `"C"` abi in `min_const_fn` + --> $DIR/const-extern-fn-call-extern-fn.rs:9:9 + | +LL | regular_in_block(); + | ^^^^^^^^^^^^^^^^^^ + | + = 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[E0723]: cannot call functions with `"C"` abi in `min_const_fn` + --> $DIR/const-extern-fn-call-extern-fn.rs:18:9 + | +LL | regular(); + | ^^^^^^^^^ + | + = 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 2 previous errors + +For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs new file mode 100644 index 000000000000..561981176880 --- /dev/null +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.rs @@ -0,0 +1,13 @@ +#![feature(const_extern_fn)] + +const extern fn unsize(x: &[u8; 3]) -> &[u8] { x } +//~^ ERROR unsizing casts are not allowed in const fn +const unsafe extern "C" fn closure() -> fn() { || {} } +//~^ ERROR function pointers in const fn are unstable +const unsafe extern fn use_float() { 1.0 + 1.0; } +//~^ ERROR only int, `bool` and `char` operations are stable in const fn +const extern "C" fn ptr_cast(val: *const u8) { val as usize; } +//~^ ERROR casting pointers to ints is unstable in const fn + + +fn main() {} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr new file mode 100644 index 000000000000..0ab1ddd8d522 --- /dev/null +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-min-const-fn.stderr @@ -0,0 +1,39 @@ +error[E0723]: unsizing casts are not allowed in const fn + --> $DIR/const-extern-fn-min-const-fn.rs:3:48 + | +LL | const extern fn unsize(x: &[u8; 3]) -> &[u8] { x } + | ^ + | + = 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[E0723]: function pointers in const fn are unstable + --> $DIR/const-extern-fn-min-const-fn.rs:5:41 + | +LL | const unsafe extern "C" fn closure() -> fn() { || {} } + | ^^^^ + | + = 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[E0723]: only int, `bool` and `char` operations are stable in const fn + --> $DIR/const-extern-fn-min-const-fn.rs:7:38 + | +LL | const unsafe extern fn use_float() { 1.0 + 1.0; } + | ^^^^^^^^^ + | + = 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[E0723]: casting pointers to ints is unstable in const fn + --> $DIR/const-extern-fn-min-const-fn.rs:9:48 + | +LL | const extern "C" fn ptr_cast(val: *const u8) { val as usize; } + | ^^^^^^^^^^^^ + | + = 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 4 previous errors + +For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs new file mode 100644 index 000000000000..cab175bbfa81 --- /dev/null +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs @@ -0,0 +1,10 @@ +#![feature(const_extern_fn)] + +const unsafe extern fn foo() -> usize { 5 } + +fn main() { + let a: [u8; foo()]; + //~^ ERROR call to unsafe function is unsafe and requires unsafe function or block + foo(); + //~^ ERROR call to unsafe function is unsafe and requires unsafe function or block +} diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr b/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr new file mode 100644 index 000000000000..5196b8ee0a21 --- /dev/null +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/const-extern-fn-requires-unsafe.rs:8:5 + | +LL | foo(); + | ^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/const-extern-fn-requires-unsafe.rs:6:17 + | +LL | let a: [u8; foo()]; + | ^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0133`. diff --git a/src/test/ui/consts/const-extern-fn/const-extern-fn.rs b/src/test/ui/consts/const-extern-fn/const-extern-fn.rs new file mode 100644 index 000000000000..1dc0f83cadf7 --- /dev/null +++ b/src/test/ui/consts/const-extern-fn/const-extern-fn.rs @@ -0,0 +1,35 @@ +// run-pass +#![feature(const_extern_fn)] + +const extern fn foo1(val: u8) -> u8 { + val + 1 +} + +const extern "C" fn foo2(val: u8) -> u8 { + val + 1 +} + +const unsafe extern fn bar1(val: bool) -> bool { + !val +} + +const unsafe extern "C" fn bar2(val: bool) -> bool { + !val +} + + +fn main() { + let a: [u8; foo1(25) as usize] = [0; 26]; + let b: [u8; foo2(25) as usize] = [0; 26]; + assert_eq!(a, b); + + let bar1_res = unsafe { bar1(false) }; + let bar2_res = unsafe { bar2(false) }; + assert!(bar1_res); + assert_eq!(bar1_res, bar2_res); + + let _foo1_cast: extern fn(u8) -> u8 = foo1; + let _foo2_cast: extern fn(u8) -> u8 = foo2; + let _bar1_cast: unsafe extern fn(bool) -> bool = bar1; + let _bar2_cast: unsafe extern fn(bool) -> bool = bar2; +} diff --git a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs new file mode 100644 index 000000000000..d39f2c1fe277 --- /dev/null +++ b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.rs @@ -0,0 +1,12 @@ +// Check that `const extern fn` and `const unsafe extern fn` are feature-gated. + +#[cfg(FALSE)] const extern fn foo1() {} //~ ERROR `const extern fn` definitions are unstable +#[cfg(FALSE)] const extern "C" fn foo2() {} //~ ERROR `const extern fn` definitions are unstable +#[cfg(FALSE)] const extern "Rust" fn foo3() {} //~ ERROR `const extern fn` definitions are unstable +#[cfg(FALSE)] const unsafe extern fn bar1() {} //~ ERROR `const extern fn` definitions are unstable +#[cfg(FALSE)] const unsafe extern "C" fn bar2() {} +//~^ ERROR `const extern fn` definitions are unstable +#[cfg(FALSE)] const unsafe extern "Rust" fn bar3() {} +//~^ ERROR `const extern fn` definitions are unstable + +fn main() {} diff --git a/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr new file mode 100644 index 000000000000..f138620ffefb --- /dev/null +++ b/src/test/ui/consts/const-extern-fn/feature-gate-const_extern_fn.stderr @@ -0,0 +1,57 @@ +error[E0658]: `const extern fn` definitions are unstable + --> $DIR/feature-gate-const_extern_fn.rs:3:15 + | +LL | #[cfg(FALSE)] const extern fn foo1() {} + | ^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/64926 + = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable + +error[E0658]: `const extern fn` definitions are unstable + --> $DIR/feature-gate-const_extern_fn.rs:4:15 + | +LL | #[cfg(FALSE)] const extern "C" fn foo2() {} + | ^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/64926 + = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable + +error[E0658]: `const extern fn` definitions are unstable + --> $DIR/feature-gate-const_extern_fn.rs:5:15 + | +LL | #[cfg(FALSE)] const extern "Rust" fn foo3() {} + | ^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/64926 + = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable + +error[E0658]: `const extern fn` definitions are unstable + --> $DIR/feature-gate-const_extern_fn.rs:6:15 + | +LL | #[cfg(FALSE)] const unsafe extern fn bar1() {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/64926 + = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable + +error[E0658]: `const extern fn` definitions are unstable + --> $DIR/feature-gate-const_extern_fn.rs:7:15 + | +LL | #[cfg(FALSE)] const unsafe extern "C" fn bar2() {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/64926 + = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable + +error[E0658]: `const extern fn` definitions are unstable + --> $DIR/feature-gate-const_extern_fn.rs:9:15 + | +LL | #[cfg(FALSE)] const unsafe extern "Rust" fn bar3() {} + | ^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/64926 + = help: add `#![feature(const_extern_fn)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/parser/no-const-fn-in-extern-block.rs b/src/test/ui/parser/no-const-fn-in-extern-block.rs new file mode 100644 index 000000000000..29f26389ded1 --- /dev/null +++ b/src/test/ui/parser/no-const-fn-in-extern-block.rs @@ -0,0 +1,8 @@ +extern { + const fn foo(); + //~^ ERROR extern items cannot be `const` + const unsafe fn bar(); + //~^ ERROR extern items cannot be `const` +} + +fn main() {} diff --git a/src/test/ui/parser/no-const-fn-in-extern-block.stderr b/src/test/ui/parser/no-const-fn-in-extern-block.stderr new file mode 100644 index 000000000000..5b4663a702f0 --- /dev/null +++ b/src/test/ui/parser/no-const-fn-in-extern-block.stderr @@ -0,0 +1,14 @@ +error: extern items cannot be `const` + --> $DIR/no-const-fn-in-extern-block.rs:2:5 + | +LL | const fn foo(); + | ^^^^^ + +error: extern items cannot be `const` + --> $DIR/no-const-fn-in-extern-block.rs:4:5 + | +LL | const unsafe fn bar(); + | ^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr index 4a1bd77cf7ee..a4fa451e8cba 100644 --- a/src/test/ui/reify-intrinsic.stderr +++ b/src/test/ui/reify-intrinsic.stderr @@ -8,9 +8,9 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr | help: use parentheses to call this function: `std::mem::transmute(...)` | = note: expected type `unsafe extern "rust-intrinsic" fn(isize) -> usize` - found type `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` + found type `unsafe extern "rust-intrinsic" fn(_) -> _ {std::mem::transmute::<_, _>}` -error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid +error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::mem::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid --> $DIR/reify-intrinsic.rs:11:13 | LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; From 4a2ae451e3b4807cd98013a10025ec0d2cdfecbe Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 28 Sep 2019 16:39:07 +0000 Subject: [PATCH 026/545] Stabilize `slice::repeat` (feature `repeat_generic_slice`) --- src/liballoc/slice.rs | 6 +----- src/liballoc/tests/lib.rs | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/liballoc/slice.rs b/src/liballoc/slice.rs index 4e4a285c21da..08243ef7c519 100644 --- a/src/liballoc/slice.rs +++ b/src/liballoc/slice.rs @@ -411,20 +411,16 @@ impl [T] { /// Basic usage: /// /// ``` - /// #![feature(repeat_generic_slice)] /// assert_eq!([1, 2].repeat(3), vec![1, 2, 1, 2, 1, 2]); /// ``` /// /// A panic upon overflow: /// /// ```should_panic - /// #![feature(repeat_generic_slice)] /// // this will panic at runtime /// b"0123456789abcdef".repeat(usize::max_value()); /// ``` - #[unstable(feature = "repeat_generic_slice", - reason = "it's on str, why not on slice?", - issue = "48784")] + #[stable(feature = "repeat_generic_slice", since = "1.40.0")] pub fn repeat(&self, n: usize) -> Vec where T: Copy { if n == 0 { return Vec::new(); diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 5723a30c0f34..f2a2c80f2f7e 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -4,7 +4,6 @@ #![feature(exact_size_is_empty)] #![feature(option_flattening)] #![feature(pattern)] -#![feature(repeat_generic_slice)] #![feature(trusted_len)] #![feature(try_reserve)] #![feature(unboxed_closures)] From 84b680f56fa15e8a9f0bbb16b33d9b94bf89e4d7 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 2 Oct 2019 01:04:22 -0400 Subject: [PATCH 027/545] Add missing 'bump' --- src/libsyntax/parse/parser/item.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index d9fec72566cf..2ac0352764fa 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -160,6 +160,7 @@ impl<'a> Parser<'a> { ); } let abi = self.parse_extern_abi()?; + self.bump(); // 'fn' let header = FnHeader { unsafety, From 4eb5fcb09c76d9aa72340b7eae8d8f0a1cbd024b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 2 Oct 2019 10:39:35 +0200 Subject: [PATCH 028/545] Compute the layout of uninhabited structs --- src/librustc/mir/interpret/error.rs | 6 ------ src/librustc/ty/layout.rs | 16 ++++++++++++---- src/librustc_mir/interpret/place.rs | 13 +++++-------- src/test/ui/issues/issue-64506.rs | 20 ++++++++++++++++++++ 4 files changed, 37 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/issues/issue-64506.rs diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 71967b513a04..ac99ccd45eaf 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -389,10 +389,6 @@ pub enum UnsupportedOpInfo<'tcx> { /// Free-form case. Only for errors that are never caught! Unsupported(String), - /// FIXME(#64506) Error used to work around accessing projections of - /// uninhabited types. - UninhabitedValue, - // -- Everything below is not categorized yet -- FunctionAbiMismatch(Abi, Abi), FunctionArgMismatch(Ty<'tcx>, Ty<'tcx>), @@ -556,8 +552,6 @@ impl fmt::Debug for UnsupportedOpInfo<'tcx> { not a power of two"), Unsupported(ref msg) => write!(f, "{}", msg), - UninhabitedValue => - write!(f, "tried to use an uninhabited value"), } } } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 6b22ded49f3f..2751ce57e3e8 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -825,10 +825,18 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }); (present_variants.next(), present_variants.next()) }; - if present_first.is_none() { - // Uninhabited because it has no variants, or only absent ones. - return tcx.layout_raw(param_env.and(tcx.types.never)); - } + let present_first = if present_first.is_none() { + if def.is_enum() { + // Uninhabited because it has no variants, or only absent ones. + return tcx.layout_raw(param_env.and(tcx.types.never)); + } else { + // if it's a struct, still compute a layout so that we can still compute the + // field offsets + Some(VariantIdx::new(0)) + } + } else { + present_first + }; let is_struct = !def.is_enum() || // Only one variant is present. diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 1166ca9bf244..f57c180191d2 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -9,7 +9,7 @@ use rustc::mir; use rustc::mir::interpret::truncate; use rustc::ty::{self, Ty}; use rustc::ty::layout::{ - self, Size, Abi, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt + self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx, PrimitiveExt }; use rustc::ty::TypeFoldable; @@ -377,20 +377,17 @@ where layout::FieldPlacement::Array { stride, .. } => { let len = base.len(self)?; if field >= len { - // This can be violated because this runs during promotion on code where the - // type system has not yet ensured that such things don't happen. + // This can be violated because the index (field) can be a runtime value + // provided by the user. debug!("tried to access element {} of array/slice with length {}", field, len); throw_panic!(BoundsCheck { len, index: field }); } stride * field } layout::FieldPlacement::Union(count) => { - // FIXME(#64506) `UninhabitedValue` can be removed when this issue is resolved - if base.layout.abi == Abi::Uninhabited { - throw_unsup!(UninhabitedValue); - } assert!(field < count as u64, - "Tried to access field {} of union with {} fields", field, count); + "Tried to access field {} of union {:#?} with {} fields", + field, base.layout, count); // Offset is always 0 Size::from_bytes(0) } diff --git a/src/test/ui/issues/issue-64506.rs b/src/test/ui/issues/issue-64506.rs new file mode 100644 index 000000000000..db3e85a7bdfd --- /dev/null +++ b/src/test/ui/issues/issue-64506.rs @@ -0,0 +1,20 @@ +// check-pass + +#[derive(Copy, Clone)] +pub struct ChildStdin { + inner: AnonPipe, +} + +#[derive(Copy, Clone)] +enum AnonPipe {} + +const FOO: () = { + union Foo { + a: ChildStdin, + b: (), + } + let x = unsafe { Foo { b: () }.a }; + let x = &x.inner; +}; + +fn main() {} From e8796cada9d962e30417a8f4f973f2c99727d0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 2 Oct 2019 10:12:57 -0700 Subject: [PATCH 029/545] Do not ICE when dereferencing non-Copy raw pointer --- src/librustc_mir/borrow_check/mod.rs | 12 +++++++----- src/test/ui/issues/issue-52262.rs | 25 +++++++++++++++++++++++++ src/test/ui/issues/issue-52262.stderr | 9 +++++++++ 3 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issues/issue-52262.rs create mode 100644 src/test/ui/issues/issue-52262.stderr diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index cfa211ad5afd..75d4b56fdb7c 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1944,14 +1944,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.is_mutable(place.as_ref(), is_local_mutation_allowed), self.errors_buffer.is_empty() ) { - // rust-lang/rust#46908: In pure NLL mode this code path should - // be unreachable (and thus we signal an ICE in the else branch here). - span_bug!( - span, + // rust-lang/rust#46908: In pure NLL mode this code path should be + // unreachable, but we use `delay_span_bug` because we can hit this when + // dereferencing a non-Copy raw pointer *and* have `-Ztreat-err-as-bug` + // enabled. We don't want to ICE for that case, as other errors will have + // been emitted (#52262). + self.infcx.tcx.sess.delay_span_bug(span, &format!( "Accessing `{:?}` with the kind `{:?}` shouldn't be possible", place, kind, - ); + )); } return false; } diff --git a/src/test/ui/issues/issue-52262.rs b/src/test/ui/issues/issue-52262.rs new file mode 100644 index 000000000000..2195b8955579 --- /dev/null +++ b/src/test/ui/issues/issue-52262.rs @@ -0,0 +1,25 @@ +// compile-flags:-Ztreat-err-as-bug=5 +#[derive(Debug)] +enum MyError { + NotFound { key: Vec }, + Err41, +} + +impl std::error::Error for MyError {} + +impl std::fmt::Display for MyError { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + MyError::NotFound { key } => write!( + f, + "unknown error with code {}.", + String::from_utf8(*key).unwrap() + //~^ ERROR cannot move out of `*key` which is behind a shared reference + ), + MyError::Err41 => write!(f, "Sit by a lake"), + } + } +} +fn main() { + println!("Hello, world!"); +} diff --git a/src/test/ui/issues/issue-52262.stderr b/src/test/ui/issues/issue-52262.stderr new file mode 100644 index 000000000000..7312976c8015 --- /dev/null +++ b/src/test/ui/issues/issue-52262.stderr @@ -0,0 +1,9 @@ +error[E0507]: cannot move out of `*key` which is behind a shared reference + --> $DIR/issue-52262.rs:16:35 + | +LL | String::from_utf8(*key).unwrap() + | ^^^^ move occurs because `*key` has type `std::vec::Vec`, which does not implement the `Copy` trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`. From a87b44dbea5335c9b5d563b44e0e5f8b074ac9db Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 2 Oct 2019 18:36:06 +0000 Subject: [PATCH 030/545] Always inline `mem::{size_of,align_of}` in debug builds Those two are const fn and do not have any arguments. Inlining helps reducing generated code size in debug builds. --- 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 95ad4272cedd..12942af307b4 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -236,7 +236,7 @@ pub fn forget_unsized(t: T) { /// ``` /// /// [alignment]: ./fn.align_of.html -#[inline] +#[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] pub const fn size_of() -> usize { @@ -328,7 +328,7 @@ pub fn min_align_of_val(val: &T) -> usize { /// /// assert_eq!(4, mem::align_of::()); /// ``` -#[inline] +#[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_promotable] pub const fn align_of() -> usize { From 9fbb2a9b347d44074fff8aab27cd161a9cd54c74 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 2 Oct 2019 21:43:24 +0200 Subject: [PATCH 031/545] Fix missing calls to drop on unwind with lto=fat; issue 64655. --- src/librustc_codegen_llvm/attributes.rs | 51 ++++++++++++++++++------- 1 file changed, 38 insertions(+), 13 deletions(-) diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 33b50401b22f..4189904a8018 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -273,25 +273,50 @@ pub fn from_fn_attrs( } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) { // Special attribute for allocator functions, which can't unwind false - } else if let Some(id) = id { + } else if let Some(_) = id { + // rust-lang/rust#64655, rust-lang/rust#63909: to minimize + // risk associated with changing cases where nounwind + // attribute is attached, this code is deliberately mimicking + // old control flow based on whether `id` is `Some` or `None`. + // + // However, in the long term we should either: + // - fold this into final else (i.e. stop inspecting `id`) + // - or better still: whole-heartedly adopt Rust PR #63909. + // + // see also Rust RFC 2753. + let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - if cx.tcx.is_foreign_item(id) { - // Foreign items like `extern "C" { fn foo(); }` are assumed not to - // unwind - false - } else if sig.abi != Abi::Rust && sig.abi != Abi::RustCall { - // Any items defined in Rust that *don't* have the `extern` ABI are - // defined to not unwind. We insert shims to abort if an unwind - // happens to enforce this. - false - } else { - // Anything else defined in Rust is assumed that it can possibly - // unwind + if sig.abi == Abi::Rust || sig.abi == Abi::RustCall { + // Any Rust method (or `extern "Rust" fn` or `extern + // "rust-call" fn`) is explicitly allowed to unwind + // (unless it has no-unwind attribute, handled above). true + } else { + // Anything else is either: + // + // 1. A foreign item (like `extern "C" { fn foo(); }`), or + // + // 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`). + // + // Foreign items (case 1) are assumed to not unwind; it is + // UB otherwise. (At least for now; see also + // rust-lang/rust#63909 and Rust RFC 2753.) + // + // Items defined in Rust with non-Rust ABIs (case 2) are + // defined to not unwind. We insert shims to abort if an + // unwind happens to enforce this. + // + // In either case, we mark item as explicitly nounwind. + false } } else { // assume this can possibly unwind, avoiding the application of a // `nounwind` attribute below. + // + // (But: See comments in previous branch. Specifically, it is + // unclear whether there is real value in the assumption this + // can unwind. The conservatism here may just be papering over + // a real problem by making some UB a bit harder to hit.) true }); From a3719728325e7a6fa511aee5c8191c248262a9af Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 2 Oct 2019 21:43:40 +0200 Subject: [PATCH 032/545] Regression tests for issue 64655. --- ...llow-unwind-when-calling-panic-directly.rs | 63 ++++++++++++++ ...sue-64655-extern-rust-must-allow-unwind.rs | 82 +++++++++++++++++++ 2 files changed, 145 insertions(+) create mode 100644 src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs create mode 100644 src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs new file mode 100644 index 000000000000..ac715e4328fd --- /dev/null +++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -0,0 +1,63 @@ +// run-pass + +// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine +// should still run desstructors as it unwindws the stack. However, +// bugs with how the nounwind LLVM attribute was applied led to this +// simple case being mishandled *if* you had fat LTO turned on. + +// Unlike issue-64655-extern-rust-must-allow-unwind.rs, the issue +// embodied in this test cropped up regardless of optimization level. +// Therefore it seemed worthy of being enshrined as a dedicated unit +// test. + +// LTO settings cannot be combined with -C prefer-dynamic +// no-prefer-dynamic + +// The revisions just enumerate lto settings (the opt-level appeared irrelevant in practice) + +// revisions: no thin fat +//[no]compile-flags: -C lto=no +//[thin]compile-flags: -C lto=thin +//[fat]compile-flags: -C lto=fat + +#![feature(core_panic)] + +// (For some reason, reproducing the LTO issue requires pulling in std +// explicitly this way.) +#![no_std] +extern crate std; + +fn main() { + use std::sync::atomic::{AtomicUsize, Ordering}; + use std::boxed::Box; + + static SHARED: AtomicUsize = AtomicUsize::new(0); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0); + + let old_hook = std::panic::take_hook(); + + std::panic::set_hook(Box::new(|_| { } )); // no-op on panic. + + let handle = std::thread::spawn(|| { + struct Droppable; + impl Drop for Droppable { + fn drop(&mut self) { + SHARED.fetch_add(1, Ordering::SeqCst); + } + } + + let _guard = Droppable; + let s = "issue-64655-allow-unwind-when-calling-panic-directly.rs"; + core::panicking::panic(&("???", s, 17, 4)); + }); + + let wait = handle.join(); + + // reinstate handler to ease observation of assertion failures. + std::panic::set_hook(old_hook); + + assert!(wait.is_err()); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1); +} diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs new file mode 100644 index 000000000000..4f7e8e3072f6 --- /dev/null +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -0,0 +1,82 @@ +// run-pass + +// rust-lang/rust#64655: with panic=unwind, a panic from a subroutine +// should still run desstructors as it unwindws the stack. However, +// bugs with how the nounwind LLVM attribute was applied led to this +// simple case being mishandled *if* you had optimization *and* fat +// LTO turned on. + +// This test is the closest thing to a "regression test" we can do +// without actually spawning subprocesses and comparing stderr +// results. +// +// This test takes the code from the above issue and adapts it to +// better fit our test infrastructure: +// +// * Instead of relying on println! to observe whether the destructor +// is run, we instead run the code in a spawned thread and +// communicate the destructor's operation via a synchronous atomic +// in static memory. +// +// * To keep the output from confusing a casual user, we override the +// panic hook to be a no-op (rather than printing a message to +// stderr). +// +// (pnkfelix has confirmed by hand that these additions do not mask +// the underlying bug.) + +// LTO settings cannot be combined with -C prefer-dynamic +// no-prefer-dynamic + +// The revisions combine each lto setting with each optimization +// setting; pnkfelix observed three differing behaviors at opt-levels +// 0/1/2+3 for this test, so it seems prudent to be thorough. + +// revisions: no0 no1 no2 no3 thin0 thin1 thin2 thin3 fat0 fat1 fat2 fat3 + +//[no0]compile-flags: -C opt-level=0 -C lto=no +//[no1]compile-flags: -C opt-level=1 -C lto=no +//[no2]compile-flags: -C opt-level=2 -C lto=no +//[no3]compile-flags: -C opt-level=3 -C lto=no +//[thin0]compile-flags: -C opt-level=0 -C lto=thin +//[thin1]compile-flags: -C opt-level=1 -C lto=thin +//[thin2]compile-flags: -C opt-level=2 -C lto=thin +//[thin3]compile-flags: -C opt-level=3 -C lto=thin +//[fat0]compile-flags: -C opt-level=0 -C lto=fat +//[fat1]compile-flags: -C opt-level=1 -C lto=fat +//[fat2]compile-flags: -C opt-level=2 -C lto=fat +//[fat3]compile-flags: -C opt-level=3 -C lto=fat + +fn main() { + use std::sync::atomic::{AtomicUsize, Ordering}; + + static SHARED: AtomicUsize = AtomicUsize::new(0); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 0); + + let old_hook = std::panic::take_hook(); + + std::panic::set_hook(Box::new(|_| { } )); // no-op on panic. + + let handle = std::thread::spawn(|| { + struct Droppable; + impl Drop for Droppable { + fn drop(&mut self) { + SHARED.fetch_add(1, Ordering::SeqCst); + } + } + + let _guard = Droppable; + None::<()>.expect("???"); + }); + + let wait = handle.join(); + + // reinstate handler to ease observation of assertion failures. + std::panic::set_hook(old_hook); + + assert!(wait.is_err()); + + assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1); +} + From 73c09870b5da81c16209844fe8ca650afd4e7ade Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 29 Sep 2019 21:34:22 +0100 Subject: [PATCH 033/545] Do not mark unitinitialized locals as requiring storage --- .../dataflow/impls/storage_liveness.rs | 38 +++++-- src/librustc_mir/transform/generator.rs | 5 +- .../async-await/async-fn-size-moved-locals.rs | 3 +- .../async-fn-size-uninit-locals.rs | 103 ++++++++++++++++++ src/test/ui/async-await/async-fn-size.rs | 8 +- 5 files changed, 140 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/async-await/async-fn-size-uninit-locals.rs diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 0f66b13fdc51..c1695ba66d0d 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -109,15 +109,13 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { assert_eq!(1, self.body.arg_count); } - fn statement_effect(&self, - sets: &mut GenKillSet, - loc: Location) { - self.check_for_move(sets, loc); + 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]; match stmt.kind { - StatementKind::StorageLive(l) => sets.gen(l), StatementKind::StorageDead(l) => sets.kill(l), StatementKind::Assign(box(ref place, _)) | StatementKind::SetDiscriminant { box ref place, .. } => { @@ -136,11 +134,35 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { } } - fn terminator_effect(&self, - sets: &mut GenKillSet, - loc: Location) { + fn statement_effect(&self, sets: &mut GenKillSet, loc: Location) { + // If we move from a place then only stops needing storage *after* + // that statement. self.check_for_move(sets, loc); + } + + fn before_terminator_effect(&self, sets: &mut GenKillSet, loc: Location) { self.check_for_borrow(sets, loc); + + if let TerminatorKind::Call { + destination: Some((Place { base: PlaceBase::Local(local), .. }, _)), + .. + } = self.body[loc.block].terminator().kind { + sets.gen(local); + } + } + + 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((Place { base: PlaceBase::Local(local), projection: box [] }, _)), + .. + } = self.body[loc.block].terminator().kind { + sets.kill(local); + } + self.check_for_move(sets, loc); } fn propagate_call_return( diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 2b66e602370c..f304ac4e9e16 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -508,10 +508,7 @@ fn locals_live_across_suspend_points( storage_liveness_map.insert(block, storage_liveness.clone()); requires_storage_cursor.seek(loc); - let mut storage_required = requires_storage_cursor.get().clone(); - - // Mark locals without storage statements as always requiring storage - storage_required.union(&ignored.0); + let storage_required = requires_storage_cursor.get().clone(); // Locals live are live at this point only if they are used across // suspension points (the `liveness` variable) diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs index 3ffcbb58595e..c266644fd702 100644 --- a/src/test/ui/async-await/async-fn-size-moved-locals.rs +++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs @@ -22,7 +22,8 @@ struct BigFut([u8; BIG_FUT_SIZE]); impl BigFut { fn new() -> Self { BigFut([0; BIG_FUT_SIZE]) - } } + } +} impl Drop for BigFut { fn drop(&mut self) {} diff --git a/src/test/ui/async-await/async-fn-size-uninit-locals.rs b/src/test/ui/async-await/async-fn-size-uninit-locals.rs new file mode 100644 index 000000000000..a489fb11630c --- /dev/null +++ b/src/test/ui/async-await/async-fn-size-uninit-locals.rs @@ -0,0 +1,103 @@ +// Test that we don't store uninitialized locals in futures from `async fn`. +// +// The exact sizes can change by a few bytes (we'd like to know when they do). +// What we don't want to see is the wrong multiple of 1024 (the size of `Big`) +// being reflected in the size. + +// ignore-wasm32-bare (sizes don't match) +// run-pass + +// edition:2018 + +#![allow(unused_variables, unused_assignments)] + +use std::future::Future; +use std::pin::Pin; +use std::task::{Context, Poll}; + +const BIG_FUT_SIZE: usize = 1024; +struct Big([u8; BIG_FUT_SIZE]); + +impl Big { + fn new() -> Self { + Big([0; BIG_FUT_SIZE]) + } +} + +impl Drop for Big { + fn drop(&mut self) {} +} + +#[allow(dead_code)] +struct Joiner { + a: Option, + b: Option, + c: Option, +} + +impl Future for Joiner { + type Output = (); + + fn poll(self: Pin<&mut Self>, _ctx: &mut Context<'_>) -> Poll { + Poll::Ready(()) + } +} + +fn noop() {} +async fn fut() {} + +async fn single() { + let x; + fut().await; + x = Big::new(); +} + +async fn single_with_noop() { + let x; + fut().await; + noop(); + x = Big::new(); + noop(); +} + +async fn joined() { + let joiner; + let a = Big::new(); + let b = Big::new(); + let c = Big::new(); + + fut().await; + noop(); + joiner = Joiner { a: Some(a), b: Some(b), c: Some(c) }; + noop(); +} + +async fn joined_with_noop() { + let joiner; + let a = Big::new(); + let b = Big::new(); + let c = Big::new(); + + fut().await; + noop(); + joiner = Joiner { a: Some(a), b: Some(b), c: Some(c) }; + noop(); +} + +async fn join_retval() -> Joiner { + let a = Big::new(); + let b = Big::new(); + let c = Big::new(); + + fut().await; + noop(); + Joiner { a: Some(a), b: Some(b), c: Some(c) } +} + +fn main() { + assert_eq!(8, std::mem::size_of_val(&single())); + assert_eq!(12, std::mem::size_of_val(&single_with_noop())); + assert_eq!(3084, std::mem::size_of_val(&joined())); + assert_eq!(3084, std::mem::size_of_val(&joined_with_noop())); + assert_eq!(3084, std::mem::size_of_val(&join_retval())); +} diff --git a/src/test/ui/async-await/async-fn-size.rs b/src/test/ui/async-await/async-fn-size.rs index b5c94ecb7169..b313992db4ec 100644 --- a/src/test/ui/async-await/async-fn-size.rs +++ b/src/test/ui/async-await/async-fn-size.rs @@ -89,10 +89,10 @@ fn main() { assert_eq!(8, std::mem::size_of_val(&await1_level1())); assert_eq!(12, std::mem::size_of_val(&await2_level1())); assert_eq!(12, std::mem::size_of_val(&await3_level1())); - assert_eq!(20, std::mem::size_of_val(&await3_level2())); - assert_eq!(28, std::mem::size_of_val(&await3_level3())); - assert_eq!(36, std::mem::size_of_val(&await3_level4())); - assert_eq!(44, std::mem::size_of_val(&await3_level5())); + assert_eq!(24, std::mem::size_of_val(&await3_level2())); + assert_eq!(36, std::mem::size_of_val(&await3_level3())); + assert_eq!(48, std::mem::size_of_val(&await3_level4())); + assert_eq!(60, std::mem::size_of_val(&await3_level5())); assert_eq!(1, wait(base())); assert_eq!(1, wait(await1_level1())); From 3adcc3ed222bdc6fc669281c42ef933aa3f6116b Mon Sep 17 00:00:00 2001 From: Felix S Klock II Date: Wed, 2 Oct 2019 22:04:30 +0200 Subject: [PATCH 034/545] fix typo --- src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs index 4f7e8e3072f6..18e441625ab9 100644 --- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -1,7 +1,7 @@ // run-pass // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine -// should still run desstructors as it unwindws the stack. However, +// should still run desstructors as it unwinds the stack. However, // bugs with how the nounwind LLVM attribute was applied led to this // simple case being mishandled *if* you had optimization *and* fat // LTO turned on. From a4cad414ad42d36adfe27ac4b9271831e8af5125 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 2 Oct 2019 20:38:47 -0400 Subject: [PATCH 035/545] Revert changes to `src/test/ui/reify-intrinsic.stderr` For some reason, I'm getting different output for this locally. --- src/test/ui/reify-intrinsic.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/reify-intrinsic.stderr b/src/test/ui/reify-intrinsic.stderr index a4fa451e8cba..4a1bd77cf7ee 100644 --- a/src/test/ui/reify-intrinsic.stderr +++ b/src/test/ui/reify-intrinsic.stderr @@ -8,9 +8,9 @@ LL | let _: unsafe extern "rust-intrinsic" fn(isize) -> usize = std::mem::tr | help: use parentheses to call this function: `std::mem::transmute(...)` | = note: expected type `unsafe extern "rust-intrinsic" fn(isize) -> usize` - found type `unsafe extern "rust-intrinsic" fn(_) -> _ {std::mem::transmute::<_, _>}` + found type `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` -error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::mem::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid +error[E0606]: casting `unsafe extern "rust-intrinsic" fn(_) -> _ {std::intrinsics::transmute::<_, _>}` as `unsafe extern "rust-intrinsic" fn(isize) -> usize` is invalid --> $DIR/reify-intrinsic.rs:11:13 | LL | let _ = std::mem::transmute as unsafe extern "rust-intrinsic" fn(isize) -> usize; From 334bafebc97c83be357ed1e5f933a3df87b76c3d Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Thu, 3 Oct 2019 04:01:37 +0200 Subject: [PATCH 036/545] Document current deny by default lints --- .../src/lints/listing/deny-by-default.md | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/doc/rustc/src/lints/listing/deny-by-default.md b/src/doc/rustc/src/lints/listing/deny-by-default.md index 6574267f1851..5688e90ada12 100644 --- a/src/doc/rustc/src/lints/listing/deny-by-default.md +++ b/src/doc/rustc/src/lints/listing/deny-by-default.md @@ -222,3 +222,28 @@ error: invalid `crate_type` value | ^^^^^^^^^^^^^^^^^^^^ | ``` + +## const-err + +This lint detects expressions that will always panic at runtime and would be an +error in a `const` context. + +```rust,ignore +let _ = [0; 4][4]; +``` + +This will produce: + +```text +error: index out of bounds: the len is 4 but the index is 4 + --> src/lib.rs:1:9 + | +1 | let _ = [0; 4][4]; + | ^^^^^^^^^ + | +``` + +## order-dependent-trait-objects + +This lint detects a trait coherency violation that would allow creating two +trait impls for the same dynamic trait object involving marker traits. From 375469149c123d72d188bed3fbe468304a1b6004 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Thu, 3 Oct 2019 15:24:00 +0900 Subject: [PATCH 037/545] Reorder methods of Cell To make `new` method appear first in documentation. --- src/libcore/cell.rs | 92 ++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 8579dbf353e8..fda103a52d8b 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -229,52 +229,6 @@ pub struct Cell { value: UnsafeCell, } -impl Cell { - /// Returns a copy of the contained value. - /// - /// # Examples - /// - /// ``` - /// use std::cell::Cell; - /// - /// let c = Cell::new(5); - /// - /// let five = c.get(); - /// ``` - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn get(&self) -> T { - unsafe{ *self.value.get() } - } - - /// Updates the contained value using a function and returns the new value. - /// - /// # Examples - /// - /// ``` - /// #![feature(cell_update)] - /// - /// use std::cell::Cell; - /// - /// let c = Cell::new(5); - /// let new = c.update(|x| x + 1); - /// - /// assert_eq!(new, 6); - /// assert_eq!(c.get(), 6); - /// ``` - #[inline] - #[unstable(feature = "cell_update", issue = "50186")] - pub fn update(&self, f: F) -> T - where - F: FnOnce(T) -> T, - { - let old = self.get(); - let new = f(old); - self.set(new); - new - } -} - #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Cell where T: Send {} @@ -448,6 +402,52 @@ impl Cell { } } +impl Cell { + /// Returns a copy of the contained value. + /// + /// # Examples + /// + /// ``` + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// + /// let five = c.get(); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn get(&self) -> T { + unsafe{ *self.value.get() } + } + + /// Updates the contained value using a function and returns the new value. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_update)] + /// + /// use std::cell::Cell; + /// + /// let c = Cell::new(5); + /// let new = c.update(|x| x + 1); + /// + /// assert_eq!(new, 6); + /// assert_eq!(c.get(), 6); + /// ``` + #[inline] + #[unstable(feature = "cell_update", issue = "50186")] + pub fn update(&self, f: F) -> T + where + F: FnOnce(T) -> T, + { + let old = self.get(); + let new = f(old); + self.set(new); + new + } +} + impl Cell { /// Returns a raw pointer to the underlying data in this cell. /// From 00d9db14f74c6b4d532547f7acf38b3538574958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Habov=C5=A1tiak?= Date: Thu, 3 Oct 2019 10:09:04 +0200 Subject: [PATCH 038/545] Added doc about behavior of extend on HashMap It was unclear what the implementation does when it encounters existing keys. This change makes it clear by documenting the trait impl. --- src/libstd/collections/hash/map.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index ff50051ef504..c9596dc05bbf 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2362,6 +2362,8 @@ where } } +/// Inserts all new key-values from the iterator and replaces values with existing +/// keys with new values returned from the iterator. #[stable(feature = "rust1", since = "1.0.0")] impl Extend<(K, V)> for HashMap where From e7e6dec06a050c5bc4e7a93e6700fad28570779a Mon Sep 17 00:00:00 2001 From: Felix S Klock II Date: Thu, 3 Oct 2019 10:46:01 +0200 Subject: [PATCH 039/545] Apply suggestions from code review Co-Authored-By: Mazdak Farrokhzad Co-Authored-By: Ralf Jung --- src/librustc_codegen_llvm/attributes.rs | 4 ++-- .../issue-64655-allow-unwind-when-calling-panic-directly.rs | 4 ++-- .../ui/extern/issue-64655-extern-rust-must-allow-unwind.rs | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 4189904a8018..73d43289d19c 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -281,7 +281,7 @@ pub fn from_fn_attrs( // // However, in the long term we should either: // - fold this into final else (i.e. stop inspecting `id`) - // - or better still: whole-heartedly adopt Rust PR #63909. + // - adopt Rust PR #63909. // // see also Rust RFC 2753. @@ -294,7 +294,7 @@ pub fn from_fn_attrs( } else { // Anything else is either: // - // 1. A foreign item (like `extern "C" { fn foo(); }`), or + // 1. A foreign item using a non-Rust ABI (like `extern "C" { fn foo(); }`), or // // 2. A Rust item using a non-Rust ABI (like `extern "C" fn foo() { ... }`). // diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs index ac715e4328fd..63e373e5b59b 100644 --- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -1,7 +1,7 @@ // run-pass // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine -// should still run desstructors as it unwindws the stack. However, +// should still run destructors as it unwinds the stack. However, // bugs with how the nounwind LLVM attribute was applied led to this // simple case being mishandled *if* you had fat LTO turned on. @@ -54,7 +54,7 @@ fn main() { let wait = handle.join(); - // reinstate handler to ease observation of assertion failures. + // Reinstate handler to ease observation of assertion failures. std::panic::set_hook(old_hook); assert!(wait.is_err()); diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs index 18e441625ab9..346d176ad3bc 100644 --- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -1,7 +1,7 @@ // run-pass // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine -// should still run desstructors as it unwinds the stack. However, +// should still run destructors as it unwinds the stack. However, // bugs with how the nounwind LLVM attribute was applied led to this // simple case being mishandled *if* you had optimization *and* fat // LTO turned on. @@ -13,7 +13,7 @@ // This test takes the code from the above issue and adapts it to // better fit our test infrastructure: // -// * Instead of relying on println! to observe whether the destructor +// * Instead of relying on `println!` to observe whether the destructor // is run, we instead run the code in a spawned thread and // communicate the destructor's operation via a synchronous atomic // in static memory. From 5e7e8cd41f5591285bf764e3a8fc87ed89db21ba Mon Sep 17 00:00:00 2001 From: Felix S Klock II Date: Thu, 3 Oct 2019 11:08:28 +0200 Subject: [PATCH 040/545] Update attributes.rs Some comment refinements inspired by review feedback. --- src/librustc_codegen_llvm/attributes.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 73d43289d19c..423a2df3523e 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -281,7 +281,7 @@ pub fn from_fn_attrs( // // However, in the long term we should either: // - fold this into final else (i.e. stop inspecting `id`) - // - adopt Rust PR #63909. + // - or, adopt Rust PR #63909. // // see also Rust RFC 2753. @@ -302,9 +302,10 @@ pub fn from_fn_attrs( // UB otherwise. (At least for now; see also // rust-lang/rust#63909 and Rust RFC 2753.) // - // Items defined in Rust with non-Rust ABIs (case 2) are - // defined to not unwind. We insert shims to abort if an - // unwind happens to enforce this. + // Items defined in Rust with non-Rust ABIs (case 2) are also + // not supposed to unwind. Whether this should be enforced + // (versus stating it is UB) and *how* it would be enforced + // is currently under discussion; see rust-lang/rust#58794. // // In either case, we mark item as explicitly nounwind. false From 71e5f7893490d3fa4f9e55ebf5a13cffc2bb1607 Mon Sep 17 00:00:00 2001 From: Felix S Klock II Date: Thu, 3 Oct 2019 11:10:13 +0200 Subject: [PATCH 041/545] Update issue-64655-extern-rust-must-allow-unwind.rs placate tidy --- src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs index 346d176ad3bc..4d521e470396 100644 --- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -79,4 +79,3 @@ fn main() { assert_eq!(SHARED.fetch_add(0, Ordering::SeqCst), 1); } - From 1222cc98ad8e37c69f89b0f411ac5b96416719f9 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 3 Oct 2019 12:31:06 -0400 Subject: [PATCH 042/545] permit asyncawait-ondeck to be added by anyone Still debating if this is the right approach --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index f3509897bdf9..53c0e52136e6 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -4,6 +4,7 @@ allow-unauthenticated = [ "requires-nightly", # I-* without I-nominated "I-compilemem", "I-compiletime", "I-crash", "I-hang", "I-ICE", "I-slow", + "AsyncAwait-OnDeck", ] [assign] From 1fcbd902a1d1145ed91fae1edb7a8c5798f68a14 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 3 Oct 2019 12:37:31 -0400 Subject: [PATCH 043/545] Update triagebot.toml Co-Authored-By: Pietro Albini --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 53c0e52136e6..d87c5b64c21c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -3,7 +3,7 @@ allow-unauthenticated = [ "C-*", "A-*", "E-*", "NLL-*", "O-*", "S-*", "T-*", "WG-*", "F-*", "requires-nightly", # I-* without I-nominated - "I-compilemem", "I-compiletime", "I-crash", "I-hang", "I-ICE", "I-slow", + "I-*", "!I-nominated", "AsyncAwait-OnDeck", ] From ed60cf2475cabd3d9ad1afdc03bd6952d99b744c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 29 Sep 2019 19:07:26 -0700 Subject: [PATCH 044/545] When encountering chained operators use heuristics to recover from bad turbofish --- src/libsyntax/parse/diagnostics.rs | 100 +++++++++++++++--- src/libsyntax/parse/parser/expr.rs | 4 +- src/test/ui/did_you_mean/issue-40396.stderr | 16 +-- .../require-parens-for-chained-comparison.rs | 5 +- ...quire-parens-for-chained-comparison.stderr | 23 ++-- 5 files changed, 121 insertions(+), 27 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index e8d7b7663ed5..0e3d873b252e 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -543,16 +543,25 @@ impl<'a> Parser<'a> { } /// Produces an error if comparison operators are chained (RFC #558). - /// We only need to check the LHS, not the RHS, because all comparison ops - /// have same precedence and are left-associative. - crate fn check_no_chained_comparison(&self, lhs: &Expr, outer_op: &AssocOp) -> PResult<'a, ()> { - debug_assert!(outer_op.is_comparison(), - "check_no_chained_comparison: {:?} is not comparison", - outer_op); + /// We only need to check the LHS, not the RHS, because all comparison ops have same + /// precedence and are left-associative. + /// + /// This can also be hit if someone incorrectly writes `foo()` when they should have used + /// the turbofish syntax. We attempt some heuristic recovery if that is the case. + crate fn check_no_chained_comparison( + &mut self, + lhs: &Expr, + outer_op: &AssocOp, + ) -> PResult<'a, Option>> { + debug_assert!( + outer_op.is_comparison(), + "check_no_chained_comparison: {:?} is not comparison", + outer_op, + ); match lhs.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { // Respan to include both operators. - let op_span = op.span.to(self.token.span); + let op_span = op.span.to(self.prev_span); let mut err = self.struct_span_err( op_span, "chained comparison operators require parentheses", @@ -561,17 +570,84 @@ impl<'a> Parser<'a> { *outer_op == AssocOp::Less || // Include `<` to provide this recommendation *outer_op == AssocOp::Greater // even in a case like the following: { // Foo>> - err.help( - "use `::<...>` instead of `<...>` if you meant to specify type arguments"); - err.help("or use `(...)` if you meant to specify fn arguments"); - // These cases cause too many knock-down errors, bail out (#61329). + let msg = "use `::<...>` instead of `<...>` if you meant to specify type \ + arguments"; + if *outer_op == AssocOp::Less { + // if self.look_ahead(1, |t| t.kind == token::Lt || t.kind == token::ModSep) { + let snapshot = self.clone(); + self.bump(); + // So far we have parsed `foo 0 { + match &self.token.kind { + token::Lt => { + acc += 1; + } + token::Gt => { + acc -= 1; + } + token::BinOp(token::Shr) => { + acc -= 2; + } + token::Eof => { + break; + } + _ => {} + } + self.bump(); + } + if self.token.kind != token::OpenDelim(token::Paren) { + mem::replace(self, snapshot.clone()); + } + } + if self.token.kind == token::OpenDelim(token::Paren) { + err.span_suggestion( + op_span.shrink_to_lo(), + msg, + "::".to_string(), + Applicability::MaybeIncorrect, + ); + let snapshot = self.clone(); + self.bump(); + let mut acc = 1; + while acc > 0 { + match &self.token.kind { + token::OpenDelim(token::Paren) => { + acc += 1; + } + token::CloseDelim(token::Paren) => { + acc -= 1; + } + token::Eof => { + break; + } + _ => {} + } + self.bump(); + } + if self.token.kind == token::Eof { + mem::replace(self, snapshot); + return Err(err); + } else { + err.emit(); + return Ok(Some(self.mk_expr( + lhs.span.to(self.prev_span), + ExprKind::Err, + ThinVec::new(), + ))); + } + } else { + err.help(msg); + err.help("or use `(...)` if you meant to specify fn arguments"); + // These cases cause too many knock-down errors, bail out (#61329). + } return Err(err); } err.emit(); } _ => {} } - Ok(()) + Ok(None) } crate fn maybe_report_ambiguous_plus( diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 23674ad589dc..b459782d237c 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -238,7 +238,9 @@ impl<'a> Parser<'a> { self.bump(); if op.is_comparison() { - self.check_no_chained_comparison(&lhs, &op)?; + if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? { + return Ok(expr); + } } // Special cases: if op == AssocOp::As { diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index 7a08fda27e35..d0448cc265c3 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -2,16 +2,17 @@ error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:2:20 | LL | (0..13).collect>(); - | ^^^^^^^^ + | ^^^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments +LL | (0..13).collect::>(); + | ^^ error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:7:8 | LL | Vec::new(); - | ^^^^^^^ + | ^^^^^ | = help: use `::<...>` instead of `<...>` if you meant to specify type arguments = help: or use `(...)` if you meant to specify fn arguments @@ -20,10 +21,11 @@ error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:12:20 | LL | (0..13).collect(); - | ^^^^^^^^ + | ^^^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments +LL | (0..13).collect::(); + | ^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index 3dcc0c8f3d49..11839938cb02 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -13,5 +13,8 @@ fn main() { f(); //~^ ERROR chained comparison operators require parentheses //~| HELP: use `::<...>` instead of `<...>` - //~| HELP: or use `(...)` + + f, Option>>(1, 2); + //~^ ERROR chained comparison operators require parentheses + //~| HELP: use `::<...>` instead of `<...>` } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index e927f4c32484..02fb56a7f9be 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -2,22 +2,33 @@ error: chained comparison operators require parentheses --> $DIR/require-parens-for-chained-comparison.rs:5:11 | LL | false == false == false; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^ error: chained comparison operators require parentheses --> $DIR/require-parens-for-chained-comparison.rs:8:11 | LL | false == 0 < 2; - | ^^^^^^^^ + | ^^^^^^ error: chained comparison operators require parentheses --> $DIR/require-parens-for-chained-comparison.rs:13:6 | LL | f(); - | ^^^^ + | ^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments +LL | f::(); + | ^^ + +error: chained comparison operators require parentheses + --> $DIR/require-parens-for-chained-comparison.rs:17:6 + | +LL | f, Option>>(1, 2); + | ^^^^^^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments + | +LL | f::, Option>>(1, 2); + | ^^ error[E0308]: mismatched types --> $DIR/require-parens-for-chained-comparison.rs:8:14 @@ -37,6 +48,6 @@ LL | false == 0 < 2; = note: expected type `bool` found type `{integer}` -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0308`. From 6c9f298a8bee9b1716b2e6fcdb8305c3f4874fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Sep 2019 12:19:22 -0700 Subject: [PATCH 045/545] review comments --- src/libsyntax/parse/diagnostics.rs | 87 +++++++++++++++++------------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 0e3d873b252e..584c7c2ded55 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -560,6 +560,7 @@ impl<'a> Parser<'a> { ); match lhs.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { + // Respan to include both operators. let op_span = op.span.to(self.prev_span); let mut err = self.struct_span_err( @@ -573,63 +574,54 @@ impl<'a> Parser<'a> { let msg = "use `::<...>` instead of `<...>` if you meant to specify type \ arguments"; if *outer_op == AssocOp::Less { - // if self.look_ahead(1, |t| t.kind == token::Lt || t.kind == token::ModSep) { let snapshot = self.clone(); self.bump(); - // So far we have parsed `foo 0 { - match &self.token.kind { - token::Lt => { - acc += 1; - } - token::Gt => { - acc -= 1; - } - token::BinOp(token::Shr) => { - acc -= 2; - } - token::Eof => { - break; - } - _ => {} - } - self.bump(); - } + // So far we have parsed `foo(`, so we rewind the parser and bail out. mem::replace(self, snapshot.clone()); } } if self.token.kind == token::OpenDelim(token::Paren) { + // We have high certainty that this was a bad turbofish at this point. + // `foo< bar >(` err.span_suggestion( op_span.shrink_to_lo(), msg, "::".to_string(), Applicability::MaybeIncorrect, ); + let snapshot = self.clone(); - self.bump(); - let mut acc = 1; - while acc > 0 { - match &self.token.kind { - token::OpenDelim(token::Paren) => { - acc += 1; - } - token::CloseDelim(token::Paren) => { - acc -= 1; - } - token::Eof => { - break; - } - _ => {} - } - self.bump(); - } + + // Consume the fn call arguments. + let modifiers = vec![ + (token::OpenDelim(token::Paren), 1), + (token::CloseDelim(token::Paren), -1), + ]; + let early_return = vec![token::Eof]; + self.bump(); // `(` + self.consume_tts(1, &modifiers[..], &early_return[..]); + if self.token.kind == token::Eof { + // Not entirely sure now, but we bubble the error up with the + // suggestion. mem::replace(self, snapshot); return Err(err); } else { + // 99% certain that the suggestion is correct, continue parsing. err.emit(); + // FIXME: actually check that the two expressions in the binop are + // paths and resynthesize new fn call expression instead of using + // `ExprKind::Err` placeholder. return Ok(Some(self.mk_expr( lhs.span.to(self.prev_span), ExprKind::Err, @@ -637,6 +629,8 @@ impl<'a> Parser<'a> { ))); } } else { + // All we know is that this is `foo < bar >` and *nothing* else. Try to + // be helpful, but don't attempt to recover. err.help(msg); err.help("or use `(...)` if you meant to specify fn arguments"); // These cases cause too many knock-down errors, bail out (#61329). @@ -1424,6 +1418,23 @@ impl<'a> Parser<'a> { err } + fn consume_tts( + &mut self, + mut acc: i64, + modifier: &[(token::TokenKind, i64)], // Not using FxHasMap and FxHashSet due to + early_return: &[token::TokenKind], // `token::TokenKind: !Eq + !Hash`. + ) { + while acc > 0 { + if let Some((_, val)) = modifier.iter().filter(|(t, _)| *t == self.token.kind).next() { + acc += *val; + } + if early_return.contains(&self.token.kind) { + break; + } + self.bump(); + } + } + /// Replace duplicated recovered parameters with `_` pattern to avoid unecessary errors. /// /// This is necessary because at this point we don't know whether we parsed a function with From d7dceaa0c57759d37a48b5a0aa1064b7c89f957b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Sep 2019 12:36:44 -0700 Subject: [PATCH 046/545] Account for missing turbofish in paths too --- src/libsyntax/parse/diagnostics.rs | 47 +++++++++++++++++++-- src/test/ui/did_you_mean/issue-40396.stderr | 5 ++- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 584c7c2ded55..4fbd36cfefc8 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -585,12 +585,51 @@ impl<'a> Parser<'a> { let early_return = vec![token::Eof]; self.consume_tts(1, &modifiers[..], &early_return[..]); - if self.token.kind != token::OpenDelim(token::Paren) { - // We don't have `foo< bar >(`, so we rewind the parser and bail out. + if !&[ + token::OpenDelim(token::Paren), + token::ModSep, + ].contains(&self.token.kind) { + // We don't have `foo< bar >(` or `foo< bar >::`, so we rewind the + // parser and bail out. mem::replace(self, snapshot.clone()); } } - if self.token.kind == token::OpenDelim(token::Paren) { + if token::ModSep == self.token.kind { + // We have some certainty that this was a bad turbofish at this point. + // `foo< bar >::` + err.span_suggestion( + op_span.shrink_to_lo(), + msg, + "::".to_string(), + Applicability::MaybeIncorrect, + ); + + let snapshot = self.clone(); + + self.bump(); // `::` + // Consume the rest of the likely `foo::new()` or return at `foo`. + match self.parse_expr() { + Ok(_) => { + // 99% certain that the suggestion is correct, continue parsing. + err.emit(); + // FIXME: actually check that the two expressions in the binop are + // paths and resynthesize new fn call expression instead of using + // `ExprKind::Err` placeholder. + return Ok(Some(self.mk_expr( + lhs.span.to(self.prev_span), + ExprKind::Err, + ThinVec::new(), + ))); + } + Err(mut err) => { + err.cancel(); + // Not entirely sure now, but we bubble the error up with the + // suggestion. + mem::replace(self, snapshot); + return Err(err); + } + } + } else if token::OpenDelim(token::Paren) == self.token.kind { // We have high certainty that this was a bad turbofish at this point. // `foo< bar >(` err.span_suggestion( @@ -601,6 +640,7 @@ impl<'a> Parser<'a> { ); let snapshot = self.clone(); + self.bump(); // `(` // Consume the fn call arguments. let modifiers = vec![ @@ -608,7 +648,6 @@ impl<'a> Parser<'a> { (token::CloseDelim(token::Paren), -1), ]; let early_return = vec![token::Eof]; - self.bump(); // `(` self.consume_tts(1, &modifiers[..], &early_return[..]); if self.token.kind == token::Eof { diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index d0448cc265c3..5e3771002b68 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -13,9 +13,10 @@ error: chained comparison operators require parentheses | LL | Vec::new(); | ^^^^^ +help: use `::<...>` instead of `<...>` if you meant to specify type arguments | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments +LL | Vec::::new(); + | ^^ error: chained comparison operators require parentheses --> $DIR/issue-40396.rs:12:20 From d27683a39f5924205d73e0015b8c25c97aadaa63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Sep 2019 13:22:58 -0700 Subject: [PATCH 047/545] Prove bad turbofish parser recovery in test --- src/test/ui/did_you_mean/issue-40396.rs | 10 +--------- src/test/ui/did_you_mean/issue-40396.stderr | 4 ++-- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs index 6902779f33d2..189335520543 100644 --- a/src/test/ui/did_you_mean/issue-40396.rs +++ b/src/test/ui/did_you_mean/issue-40396.rs @@ -1,16 +1,8 @@ -fn foo() { +fn main() { (0..13).collect>(); //~^ ERROR chained comparison -} - -fn bar() { Vec::new(); //~^ ERROR chained comparison -} - -fn qux() { (0..13).collect(); //~^ ERROR chained comparison } - -fn main() {} diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index 5e3771002b68..dd19bc137e30 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -9,7 +9,7 @@ LL | (0..13).collect::>(); | ^^ error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:7:8 + --> $DIR/issue-40396.rs:4:8 | LL | Vec::new(); | ^^^^^ @@ -19,7 +19,7 @@ LL | Vec::::new(); | ^^ error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:12:20 + --> $DIR/issue-40396.rs:6:20 | LL | (0..13).collect(); | ^^^^^ From dfdc369b40da72eb9ff466fab89584c7815d7a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 1 Oct 2019 11:24:05 -0700 Subject: [PATCH 048/545] review comments --- src/libsyntax/parse/diagnostics.rs | 79 ++++++++++--------- src/test/ui/did_you_mean/issue-40396.stderr | 6 +- .../require-parens-for-chained-comparison.rs | 18 +++-- ...quire-parens-for-chained-comparison.stderr | 15 +++- 4 files changed, 70 insertions(+), 48 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 4fbd36cfefc8..14c5dc6132cf 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -17,6 +17,8 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError}; use log::{debug, trace}; use std::mem; +const TURBOFISH: &'static str = "use the \"turbofish\" `::<...>` instead of `<...>` to specify \ + type arguments"; /// Creates a placeholder argument. crate fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { @@ -544,10 +546,20 @@ impl<'a> Parser<'a> { /// Produces an error if comparison operators are chained (RFC #558). /// We only need to check the LHS, not the RHS, because all comparison ops have same - /// precedence and are left-associative. + /// precedence (see `fn precedence`) and are left-associative (see `fn fixity`). /// /// This can also be hit if someone incorrectly writes `foo()` when they should have used - /// the turbofish syntax. We attempt some heuristic recovery if that is the case. + /// the turbofish (`foo::()`) syntax. We attempt some heuristic recovery if that is the + /// case. + /// + /// Keep in mind that given that `outer_op.is_comparison()` holds and comparison ops are left + /// associative we can infer that we have: + /// + /// outer_op + /// / \ + /// inner_op r2 + /// / \ + /// l1 r1 crate fn check_no_chained_comparison( &mut self, lhs: &Expr, @@ -560,30 +572,36 @@ impl<'a> Parser<'a> { ); match lhs.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { - // Respan to include both operators. let op_span = op.span.to(self.prev_span); let mut err = self.struct_span_err( op_span, "chained comparison operators require parentheses", ); + + let suggest = |err: &mut DiagnosticBuilder<'_>| { + err.span_suggestion( + op_span.shrink_to_lo(), + TURBOFISH, + "::".to_string(), + Applicability::MaybeIncorrect, + ); + }; + if op.node == BinOpKind::Lt && *outer_op == AssocOp::Less || // Include `<` to provide this recommendation *outer_op == AssocOp::Greater // even in a case like the following: { // Foo>> - let msg = "use `::<...>` instead of `<...>` if you meant to specify type \ - arguments"; if *outer_op == AssocOp::Less { let snapshot = self.clone(); self.bump(); - // So far we have parsed `foo Parser<'a> { if token::ModSep == self.token.kind { // We have some certainty that this was a bad turbofish at this point. // `foo< bar >::` - err.span_suggestion( - op_span.shrink_to_lo(), - msg, - "::".to_string(), - Applicability::MaybeIncorrect, - ); + suggest(&mut err); let snapshot = self.clone(); - self.bump(); // `::` + // Consume the rest of the likely `foo::new()` or return at `foo`. match self.parse_expr() { Ok(_) => { @@ -621,8 +634,8 @@ impl<'a> Parser<'a> { ThinVec::new(), ))); } - Err(mut err) => { - err.cancel(); + Err(mut expr_err) => { + expr_err.cancel(); // Not entirely sure now, but we bubble the error up with the // suggestion. mem::replace(self, snapshot); @@ -632,45 +645,39 @@ impl<'a> Parser<'a> { } else if token::OpenDelim(token::Paren) == self.token.kind { // We have high certainty that this was a bad turbofish at this point. // `foo< bar >(` - err.span_suggestion( - op_span.shrink_to_lo(), - msg, - "::".to_string(), - Applicability::MaybeIncorrect, - ); + suggest(&mut err); let snapshot = self.clone(); self.bump(); // `(` // Consume the fn call arguments. - let modifiers = vec![ + let modifiers = [ (token::OpenDelim(token::Paren), 1), (token::CloseDelim(token::Paren), -1), ]; - let early_return = vec![token::Eof]; - self.consume_tts(1, &modifiers[..], &early_return[..]); + self.consume_tts(1, &modifiers[..], &[]); - if self.token.kind == token::Eof { + return if self.token.kind == token::Eof { // Not entirely sure now, but we bubble the error up with the // suggestion. mem::replace(self, snapshot); - return Err(err); + Err(err) } else { // 99% certain that the suggestion is correct, continue parsing. err.emit(); // FIXME: actually check that the two expressions in the binop are // paths and resynthesize new fn call expression instead of using // `ExprKind::Err` placeholder. - return Ok(Some(self.mk_expr( + Ok(Some(self.mk_expr( lhs.span.to(self.prev_span), ExprKind::Err, ThinVec::new(), - ))); + ))) } } else { // All we know is that this is `foo < bar >` and *nothing* else. Try to // be helpful, but don't attempt to recover. - err.help(msg); + err.help(TURBOFISH); err.help("or use `(...)` if you meant to specify fn arguments"); // These cases cause too many knock-down errors, bail out (#61329). } @@ -1459,15 +1466,15 @@ impl<'a> Parser<'a> { fn consume_tts( &mut self, - mut acc: i64, - modifier: &[(token::TokenKind, i64)], // Not using FxHasMap and FxHashSet due to + mut acc: i64, // `i64` because malformed code can have more closing delims than opening. + modifier: &[(token::TokenKind, i64)], // Not using `FxHashMap` and `FxHashSet` due to early_return: &[token::TokenKind], // `token::TokenKind: !Eq + !Hash`. ) { while acc > 0 { - if let Some((_, val)) = modifier.iter().filter(|(t, _)| *t == self.token.kind).next() { + if let Some((_, val)) = modifier.iter().find(|(t, _)| *t == self.token.kind) { acc += *val; } - if early_return.contains(&self.token.kind) { + if self.token.kind == token::Eof || early_return.contains(&self.token.kind) { break; } self.bump(); diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index dd19bc137e30..9757f8258c13 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -3,7 +3,7 @@ error: chained comparison operators require parentheses | LL | (0..13).collect>(); | ^^^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::>(); | ^^ @@ -13,7 +13,7 @@ error: chained comparison operators require parentheses | LL | Vec::new(); | ^^^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | Vec::::new(); | ^^ @@ -23,7 +23,7 @@ error: chained comparison operators require parentheses | LL | (0..13).collect(); | ^^^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::(); | ^^ diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index 11839938cb02..f3bfe2d482f5 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -3,18 +3,24 @@ struct X; fn main() { false == false == false; - //~^ ERROR: chained comparison operators require parentheses + //~^ ERROR chained comparison operators require parentheses false == 0 < 2; - //~^ ERROR: chained comparison operators require parentheses - //~| ERROR: mismatched types - //~| ERROR: mismatched types + //~^ ERROR chained comparison operators require parentheses + //~| ERROR mismatched types + //~| ERROR mismatched types f(); //~^ ERROR chained comparison operators require parentheses - //~| HELP: use `::<...>` instead of `<...>` + //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments f, Option>>(1, 2); //~^ ERROR chained comparison operators require parentheses - //~| HELP: use `::<...>` instead of `<...>` + //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + + use std::convert::identity; + let _ = identity; + //~^ ERROR chained comparison operators require parentheses + //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + //~| HELP or use `(...)` if you meant to specify fn arguments } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 02fb56a7f9be..4b108e1db87b 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -15,7 +15,7 @@ error: chained comparison operators require parentheses | LL | f(); | ^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | f::(); | ^^ @@ -25,11 +25,20 @@ error: chained comparison operators require parentheses | LL | f, Option>>(1, 2); | ^^^^^^^^ -help: use `::<...>` instead of `<...>` if you meant to specify type arguments +help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments | LL | f::, Option>>(1, 2); | ^^ +error: chained comparison operators require parentheses + --> $DIR/require-parens-for-chained-comparison.rs:22:21 + | +LL | let _ = identity; + | ^^^^ + | + = help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + = help: or use `(...)` if you meant to specify fn arguments + error[E0308]: mismatched types --> $DIR/require-parens-for-chained-comparison.rs:8:14 | @@ -48,6 +57,6 @@ LL | false == 0 < 2; = note: expected type `bool` found type `{integer}` -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0308`. From f1499a864688a484c04c4e53962dc8ec44f79a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 1 Oct 2019 15:51:50 -0700 Subject: [PATCH 049/545] review comments --- src/libsyntax/parse/diagnostics.rs | 37 ++++++++++++++---------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 14c5dc6132cf..72206ffb28df 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -570,6 +570,11 @@ impl<'a> Parser<'a> { "check_no_chained_comparison: {:?} is not comparison", outer_op, ); + + let mk_err_expr = |this: &Self, span| { + Ok(Some(this.mk_expr(span, ExprKind::Err, ThinVec::new()))) + }; + match lhs.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { // Respan to include both operators. @@ -601,7 +606,7 @@ impl<'a> Parser<'a> { (token::Gt, -1), (token::BinOp(token::Shr), -2), ]; - self.consume_tts(1, &modifiers[..], &[]); + self.consume_tts(1, &modifiers[..]); if !&[ token::OpenDelim(token::Paren), @@ -612,7 +617,7 @@ impl<'a> Parser<'a> { mem::replace(self, snapshot.clone()); } } - if token::ModSep == self.token.kind { + return if token::ModSep == self.token.kind { // We have some certainty that this was a bad turbofish at this point. // `foo< bar >::` suggest(&mut err); @@ -628,18 +633,14 @@ 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. - return Ok(Some(self.mk_expr( - lhs.span.to(self.prev_span), - ExprKind::Err, - ThinVec::new(), - ))); + mk_err_expr(self, lhs.span.to(self.prev_span)) } Err(mut expr_err) => { expr_err.cancel(); // Not entirely sure now, but we bubble the error up with the // suggestion. mem::replace(self, snapshot); - return Err(err); + Err(err) } } } else if token::OpenDelim(token::Paren) == self.token.kind { @@ -655,9 +656,9 @@ impl<'a> Parser<'a> { (token::OpenDelim(token::Paren), 1), (token::CloseDelim(token::Paren), -1), ]; - self.consume_tts(1, &modifiers[..], &[]); + self.consume_tts(1, &modifiers[..]); - return if self.token.kind == token::Eof { + if self.token.kind == token::Eof { // Not entirely sure now, but we bubble the error up with the // suggestion. mem::replace(self, snapshot); @@ -668,11 +669,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. - Ok(Some(self.mk_expr( - lhs.span.to(self.prev_span), - ExprKind::Err, - ThinVec::new(), - ))) + mk_err_expr(self, lhs.span.to(self.prev_span)) } } else { // All we know is that this is `foo < bar >` and *nothing* else. Try to @@ -680,8 +677,8 @@ impl<'a> Parser<'a> { err.help(TURBOFISH); err.help("or use `(...)` if you meant to specify fn arguments"); // These cases cause too many knock-down errors, bail out (#61329). - } - return Err(err); + Err(err) + }; } err.emit(); } @@ -1467,14 +1464,14 @@ impl<'a> Parser<'a> { fn consume_tts( &mut self, mut acc: i64, // `i64` because malformed code can have more closing delims than opening. - modifier: &[(token::TokenKind, i64)], // Not using `FxHashMap` and `FxHashSet` due to - early_return: &[token::TokenKind], // `token::TokenKind: !Eq + !Hash`. + // Not using `FxHashMap` due to `token::TokenKind: !Eq + !Hash`. + modifier: &[(token::TokenKind, i64)], ) { while acc > 0 { if let Some((_, val)) = modifier.iter().find(|(t, _)| *t == self.token.kind) { acc += *val; } - if self.token.kind == token::Eof || early_return.contains(&self.token.kind) { + if self.token.kind == token::Eof { break; } self.bump(); From 02f57f83a9ea5903cb02bdc304800661c8f4296f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 13:22:18 -0700 Subject: [PATCH 050/545] review comments --- src/librustc_errors/diagnostic.rs | 41 +++++++++++-- src/librustc_errors/emitter.rs | 4 +- src/librustc_errors/lib.rs | 2 + src/libsyntax/parse/diagnostics.rs | 57 +++++++++++-------- src/test/ui/did_you_mean/issue-40396.stderr | 6 +- .../require-parens-for-chained-comparison.rs | 6 +- ...quire-parens-for-chained-comparison.stderr | 6 +- 7 files changed, 81 insertions(+), 41 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 3f1b91256c46..811a48a39f0d 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -298,9 +298,13 @@ impl Diagnostic { /// * may contain a name of a function, variable, or type, but not whole expressions /// /// See `CodeSuggestion` for more information. - pub fn span_suggestion(&mut self, sp: Span, msg: &str, - suggestion: String, - applicability: Applicability) -> &mut Self { + pub fn span_suggestion( + &mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability, + ) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { parts: vec![SubstitutionPart { @@ -315,10 +319,35 @@ impl Diagnostic { self } + pub fn span_suggestion_verbose( + &mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability, + ) -> &mut Self { + self.suggestions.push(CodeSuggestion { + substitutions: vec![Substitution { + parts: vec![SubstitutionPart { + snippet: suggestion, + span: sp, + }], + }], + msg: msg.to_owned(), + style: SuggestionStyle::ShowAlways, + applicability, + }); + self + } + /// Prints out a message with multiple suggested edits of the code. - pub fn span_suggestions(&mut self, sp: Span, msg: &str, - suggestions: impl Iterator, applicability: Applicability) -> &mut Self - { + pub fn span_suggestions( + &mut self, + sp: Span, + msg: &str, + suggestions: impl Iterator, + applicability: Applicability, + ) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: suggestions.map(|snippet| Substitution { parts: vec![SubstitutionPart { diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 0c7aa3582ac2..bd8191065eec 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -221,7 +221,9 @@ pub trait Emitter { // when this style is set we want the suggestion to be a message, not inline sugg.style != SuggestionStyle::HideCodeAlways && // trivial suggestion for tooling's sake, never shown - sugg.style != SuggestionStyle::CompletelyHidden + sugg.style != SuggestionStyle::CompletelyHidden && + // subtle suggestion, never shown inline + sugg.style != SuggestionStyle::ShowAlways { let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); let msg = if substitution.len() == 0 || sugg.style.hide_inline() { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index f9dc13ce97ee..2fae584c1536 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -81,6 +81,8 @@ pub enum SuggestionStyle { /// This will *not* show the code if the suggestion is inline *and* the suggested code is /// empty. ShowCode, + /// Always show the suggested code independently. + ShowAlways, } impl SuggestionStyle { diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 72206ffb28df..e3abf8ffc6c8 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -17,8 +17,7 @@ use syntax_pos::{Span, DUMMY_SP, MultiSpan, SpanSnippetError}; use log::{debug, trace}; use std::mem; -const TURBOFISH: &'static str = "use the \"turbofish\" `::<...>` instead of `<...>` to specify \ - type arguments"; +const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify type arguments"; /// Creates a placeholder argument. crate fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { @@ -585,7 +584,7 @@ impl<'a> Parser<'a> { ); let suggest = |err: &mut DiagnosticBuilder<'_>| { - err.span_suggestion( + err.span_suggestion_verbose( op_span.shrink_to_lo(), TURBOFISH, "::".to_string(), @@ -647,29 +646,16 @@ impl<'a> Parser<'a> { // We have high certainty that this was a bad turbofish at this point. // `foo< bar >(` suggest(&mut err); - - let snapshot = self.clone(); - self.bump(); // `(` - // Consume the fn call arguments. - let modifiers = [ - (token::OpenDelim(token::Paren), 1), - (token::CloseDelim(token::Paren), -1), - ]; - self.consume_tts(1, &modifiers[..]); - - if self.token.kind == token::Eof { - // Not entirely sure now, but we bubble the error up with the - // suggestion. - mem::replace(self, snapshot); - Err(err) - } else { - // 99% certain that the suggestion is correct, continue parsing. - err.emit(); - // 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, lhs.span.to(self.prev_span)) + match self.consume_fn_args() { + Err(()) => Err(err), + Ok(()) => { + err.emit(); + // 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, lhs.span.to(self.prev_span)) + } } } else { // All we know is that this is `foo < bar >` and *nothing* else. Try to @@ -687,6 +673,27 @@ impl<'a> Parser<'a> { Ok(None) } + fn consume_fn_args(&mut self) -> Result<(), ()> { + let snapshot = self.clone(); + self.bump(); // `(` + + // Consume the fn call arguments. + let modifiers = [ + (token::OpenDelim(token::Paren), 1), + (token::CloseDelim(token::Paren), -1), + ]; + self.consume_tts(1, &modifiers[..]); + + if self.token.kind == token::Eof { + // Not entirely sure that what we consumed were fn arguments, rollback. + mem::replace(self, snapshot); + Err(()) + } else { + // 99% certain that the suggestion is correct, continue parsing. + Ok(()) + } + } + crate fn maybe_report_ambiguous_plus( &mut self, allow_plus: bool, diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index 9757f8258c13..7fc7c2628c47 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -3,7 +3,7 @@ error: chained comparison operators require parentheses | LL | (0..13).collect>(); | ^^^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::>(); | ^^ @@ -13,7 +13,7 @@ error: chained comparison operators require parentheses | LL | Vec::new(); | ^^^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | Vec::::new(); | ^^ @@ -23,7 +23,7 @@ error: chained comparison operators require parentheses | LL | (0..13).collect(); | ^^^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | (0..13).collect::(); | ^^ diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index f3bfe2d482f5..9c7a25d589a1 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -12,15 +12,15 @@ fn main() { f(); //~^ ERROR chained comparison operators require parentheses - //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + //~| HELP use `::<...>` instead of `<...>` to specify type arguments f, Option>>(1, 2); //~^ ERROR chained comparison operators require parentheses - //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + //~| HELP use `::<...>` instead of `<...>` to specify type arguments use std::convert::identity; let _ = identity; //~^ ERROR chained comparison operators require parentheses - //~| HELP use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + //~| HELP use `::<...>` instead of `<...>` to specify type arguments //~| HELP or use `(...)` if you meant to specify fn arguments } diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 4b108e1db87b..5aa37a40cbd3 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -15,7 +15,7 @@ error: chained comparison operators require parentheses | LL | f(); | ^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | f::(); | ^^ @@ -25,7 +25,7 @@ error: chained comparison operators require parentheses | LL | f, Option>>(1, 2); | ^^^^^^^^ -help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments +help: use `::<...>` instead of `<...>` to specify type arguments | LL | f::, Option>>(1, 2); | ^^ @@ -36,7 +36,7 @@ error: chained comparison operators require parentheses LL | let _ = identity; | ^^^^ | - = help: use the "turbofish" `::<...>` instead of `<...>` to specify type arguments + = help: use `::<...>` instead of `<...>` to specify type arguments = help: or use `(...)` if you meant to specify fn arguments error[E0308]: mismatched types From e85089b63a2b67f4048da207b39cc265887e018f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 3 Oct 2019 21:29:25 -0400 Subject: [PATCH 051/545] Remove -Zprofile-queries --- src/librustc/dep_graph/graph.rs | 9 - src/librustc/session/config.rs | 4 - src/librustc/session/mod.rs | 14 +- src/librustc/ty/query/on_disk_cache.rs | 2 +- src/librustc/ty/query/plumbing.rs | 49 ---- src/librustc/util/common.rs | 75 +----- src/librustc_codegen_llvm/back/lto.rs | 6 +- src/librustc_codegen_llvm/back/write.rs | 4 +- src/librustc_codegen_ssa/back/link.rs | 2 +- src/librustc_incremental/persist/load.rs | 2 +- src/librustc_interface/interface.rs | 13 +- src/librustc_interface/lib.rs | 1 - src/librustc_interface/profile/mod.rs | 297 ---------------------- src/librustc_interface/profile/trace.rs | 304 ----------------------- 14 files changed, 11 insertions(+), 771 deletions(-) delete mode 100644 src/librustc_interface/profile/mod.rs delete mode 100644 src/librustc_interface/profile/trace.rs diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 0c56fc7914b4..b08c710534a9 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -9,7 +9,6 @@ use std::hash::Hash; use std::collections::hash_map::Entry; use std::mem; use crate::ty::{self, TyCtxt}; -use crate::util::common::{ProfileQueriesMsg, profq_msg}; use parking_lot::{Mutex, Condvar}; use crate::ich::{StableHashingContext, StableHashingContextProvider, Fingerprint}; @@ -260,10 +259,6 @@ impl DepGraph { // - we can get an idea of the runtime cost. let mut hcx = cx.get_stable_hashing_context(); - if cfg!(debug_assertions) { - profq_msg(hcx.sess(), ProfileQueriesMsg::TaskBegin(key.clone())) - }; - let result = if no_tcx { task(cx, arg) } else { @@ -279,10 +274,6 @@ impl DepGraph { }) }; - if cfg!(debug_assertions) { - profq_msg(hcx.sess(), ProfileQueriesMsg::TaskEnd) - }; - let current_fingerprint = hash_result(&mut hcx, &result); let dep_node_index = finish_task_and_alloc_depnode( diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2771ce69b9e0..ed8aafa25caa 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1316,10 +1316,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"), query_dep_graph: bool = (false, parse_bool, [UNTRACKED], "enable queries of the dependency graph for regression testing"), - profile_queries: bool = (false, parse_bool, [UNTRACKED], - "trace and profile the queries of the incremental compilation framework"), - profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED], - "trace and profile the queries and keys of the incremental compilation framework"), no_analysis: bool = (false, parse_bool, [UNTRACKED], "parse and expand the source, but run no analysis"), extra_plugins: Vec = (Vec::new(), parse_list, [TRACKED], diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index f22445f5d474..9d60221fa3d7 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -11,7 +11,6 @@ use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath}; use crate::session::search_paths::{PathKind, SearchPath}; use crate::util::nodemap::{FxHashMap, FxHashSet}; use crate::util::common::{duration_to_secs_str, ErrorReported}; -use crate::util::common::ProfileQueriesMsg; use rustc_data_structures::base_n; use rustc_data_structures::sync::{ @@ -46,7 +45,7 @@ use std::fmt; use std::io::Write; use std::path::PathBuf; use std::time::Duration; -use std::sync::{Arc, mpsc}; +use std::sync::Arc; mod code_stats; pub mod config; @@ -125,9 +124,6 @@ pub struct Session { /// `-Zquery-dep-graph` is specified. pub cgu_reuse_tracker: CguReuseTracker, - /// Used by `-Z profile-queries` in `util::common`. - pub profile_channel: Lock>>, - /// Used by `-Z self-profile`. pub prof: SelfProfilerRef, @@ -509,13 +505,6 @@ impl Session { pub fn time_extended(&self) -> bool { self.opts.debugging_opts.time_passes } - pub fn profile_queries(&self) -> bool { - self.opts.debugging_opts.profile_queries - || self.opts.debugging_opts.profile_queries_and_keys - } - pub fn profile_queries_and_keys(&self) -> bool { - self.opts.debugging_opts.profile_queries_and_keys - } pub fn instrument_mcount(&self) -> bool { self.opts.debugging_opts.instrument_mcount } @@ -1234,7 +1223,6 @@ fn build_session_( incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, prof: SelfProfilerRef::new(self_profiler), - profile_channel: Lock::new(None), perf_stats: PerfStats { symbol_hash_time: Lock::new(Duration::from_secs(0)), decode_def_path_tables_time: Lock::new(Duration::from_secs(0)), diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 97fafe341a31..1bba7fdd863e 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -1075,7 +1075,7 @@ where let desc = &format!("encode_query_results for {}", ::std::any::type_name::()); - time_ext(tcx.sess.time_extended(), Some(tcx.sess), desc, || { + time_ext(tcx.sess.time_extended(), desc, || { 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()) { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 955f1447c55b..f7046c4ab26f 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -9,8 +9,6 @@ use crate::ty::query::Query; use crate::ty::query::config::{QueryConfig, QueryDescription}; use crate::ty::query::job::{QueryJob, QueryResult, QueryInfo}; -use crate::util::common::{profq_msg, ProfileQueriesMsg, QueryMsg}; - use errors::DiagnosticBuilder; use errors::Level; use errors::Diagnostic; @@ -62,33 +60,6 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { } } -// If enabled, sends a message to the profile-queries thread. -macro_rules! profq_msg { - ($tcx:expr, $msg:expr) => { - if cfg!(debug_assertions) { - if $tcx.sess.profile_queries() { - profq_msg($tcx.sess, $msg) - } - } - } -} - -// If enabled, formats a key using its debug string, which can be -// expensive to compute (in terms of time). -macro_rules! profq_query_msg { - ($query:expr, $tcx:expr, $key:expr) => {{ - let msg = if cfg!(debug_assertions) { - if $tcx.sess.profile_queries_and_keys() { - Some(format!("{:?}", $key)) - } else { None } - } else { None }; - QueryMsg { - query: $query, - msg, - } - }} -} - /// 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>> { @@ -111,7 +82,6 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { loop { let mut lock = cache.get_shard_by_value(key).lock(); if let Some(value) = lock.results.get(key) { - profq_msg!(tcx, ProfileQueriesMsg::CacheHit); tcx.prof.query_cache_hit(Q::NAME); let result = (value.value.clone(), value.index); #[cfg(debug_assertions)] @@ -358,13 +328,6 @@ impl<'tcx> TyCtxt<'tcx> { key, span); - profq_msg!(self, - ProfileQueriesMsg::QueryBegin( - span.data(), - profq_query_msg!(Q::NAME.as_str(), self, key), - ) - ); - let job = match JobOwner::try_get(self, span, &key) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(result) => return result, @@ -383,7 +346,6 @@ impl<'tcx> TyCtxt<'tcx> { if Q::ANON { - profq_msg!(self, ProfileQueriesMsg::ProviderBegin); let prof_timer = self.prof.query_provider(Q::NAME); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { @@ -395,7 +357,6 @@ impl<'tcx> TyCtxt<'tcx> { }); drop(prof_timer); - profq_msg!(self, ProfileQueriesMsg::ProviderEnd); self.dep_graph.read_index(dep_node_index); @@ -468,7 +429,6 @@ impl<'tcx> TyCtxt<'tcx> { }; let result = if let Some(result) = result { - profq_msg!(self, ProfileQueriesMsg::CacheHit); result } else { // We could not load a result from the on-disk cache, so @@ -546,7 +506,6 @@ impl<'tcx> TyCtxt<'tcx> { - dep-node: {:?}", key, dep_node); - profq_msg!(self, ProfileQueriesMsg::ProviderBegin); let prof_timer = self.prof.query_provider(Q::NAME); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { @@ -568,7 +527,6 @@ impl<'tcx> TyCtxt<'tcx> { }); drop(prof_timer); - profq_msg!(self, ProfileQueriesMsg::ProviderEnd); if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) { self.dep_graph.mark_loaded_from_cache(dep_node_index, false); @@ -614,19 +572,12 @@ impl<'tcx> TyCtxt<'tcx> { let _ = self.get_query::(DUMMY_SP, key); } else { - profq_msg!(self, ProfileQueriesMsg::CacheHit); self.prof.query_cache_hit(Q::NAME); } } #[allow(dead_code)] fn force_query>(self, key: Q::Key, span: Span, dep_node: DepNode) { - profq_msg!( - self, - ProfileQueriesMsg::QueryBegin(span.data(), - profq_query_msg!(Q::NAME.as_str(), self, 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) { diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index 0f472126695e..3e52a6aa5085 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -6,11 +6,8 @@ use std::cell::Cell; use std::fmt::Debug; use std::time::{Duration, Instant}; -use std::sync::mpsc::{Sender}; -use syntax_pos::{SpanData}; use syntax::symbol::{Symbol, sym}; use rustc_macros::HashStable; -use crate::dep_graph::{DepNode}; use crate::session::Session; #[cfg(test)] @@ -26,17 +23,6 @@ pub struct ErrorReported; thread_local!(static TIME_DEPTH: Cell = Cell::new(0)); -/// Parameters to the `Dump` variant of type `ProfileQueriesMsg`. -#[derive(Clone,Debug)] -pub struct ProfQDumpParams { - /// A base path for the files we will dump. - pub path:String, - /// To ensure that the compiler waits for us to finish our dumps. - pub ack:Sender<()>, - /// Toggle dumping a log file with every `ProfileQueriesMsg`. - pub dump_profq_msg_log:bool, -} - #[allow(nonstandard_style)] #[derive(Clone, Debug, PartialEq, Eq)] pub struct QueryMsg { @@ -44,53 +30,6 @@ pub struct QueryMsg { pub msg: Option, } -/// A sequence of these messages induce a trace of query-based incremental compilation. -// FIXME(matthewhammer): Determine whether we should include cycle detection here or not. -#[derive(Clone,Debug)] -pub enum ProfileQueriesMsg { - /// Begin a timed pass. - TimeBegin(String), - /// End a timed pass. - TimeEnd, - /// Begin a task (see `dep_graph::graph::with_task`). - TaskBegin(DepNode), - /// End a task. - TaskEnd, - /// Begin a new query. - /// Cannot use `Span` because queries are sent to other thread. - QueryBegin(SpanData, QueryMsg), - /// Query is satisfied by using an already-known value for the given key. - CacheHit, - /// Query requires running a provider; providers may nest, permitting queries to nest. - ProviderBegin, - /// Query is satisfied by a provider terminating with a value. - ProviderEnd, - /// Dump a record of the queries to the given path. - Dump(ProfQDumpParams), - /// Halt the profiling/monitoring background thread. - Halt -} - -/// If enabled, send a message to the profile-queries thread. -pub fn profq_msg(sess: &Session, msg: ProfileQueriesMsg) { - if let Some(s) = sess.profile_channel.borrow().as_ref() { - s.send(msg).unwrap() - } else { - // Do nothing. - } -} - -/// Set channel for profile queries channel. -pub fn profq_set_chan(sess: &Session, s: Sender) -> bool { - let mut channel = sess.profile_channel.borrow_mut(); - if channel.is_none() { - *channel = Some(s); - true - } else { - false - } -} - /// Read the current depth of `time()` calls. This is used to /// encourage indentation across threads. pub fn time_depth() -> usize { @@ -107,10 +46,10 @@ pub fn set_time_depth(depth: usize) { pub fn time(sess: &Session, what: &str, f: F) -> T where F: FnOnce() -> T, { - time_ext(sess.time_passes(), Some(sess), what, f) + time_ext(sess.time_passes(), what, f) } -pub fn time_ext(do_it: bool, sess: Option<&Session>, what: &str, f: F) -> T where +pub fn time_ext(do_it: bool, what: &str, f: F) -> T where F: FnOnce() -> T, { if !do_it { return f(); } @@ -121,19 +60,9 @@ pub fn time_ext(do_it: bool, sess: Option<&Session>, what: &str, f: F) -> r }); - if let Some(sess) = sess { - if cfg!(debug_assertions) { - profq_msg(sess, ProfileQueriesMsg::TimeBegin(what.to_string())) - } - } let start = Instant::now(); let rv = f(); let dur = start.elapsed(); - if let Some(sess) = sess { - if cfg!(debug_assertions) { - profq_msg(sess, ProfileQueriesMsg::TimeEnd) - } - } print_time_passes_entry(true, what, dur); diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index c4368d2cb8b4..da74c69d7d70 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -116,7 +116,7 @@ fn prepare_lto(cgcx: &CodegenContext, info!("adding bytecode {}", name); let bc_encoded = data.data(); - let (bc, id) = time_ext(cgcx.time_passes, None, &format!("decode {}", name), || { + let (bc, id) = time_ext(cgcx.time_passes, &format!("decode {}", name), || { match DecodedBytecode::new(bc_encoded) { Ok(b) => Ok((b.bytecode(), b.identifier().to_string())), Err(e) => Err(diag_handler.fatal(&e)), @@ -295,7 +295,7 @@ fn fat_lto(cgcx: &CodegenContext, for (bc_decoded, name) in serialized_modules { let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_link_module"); info!("linking {:?}", name); - time_ext(cgcx.time_passes, None, &format!("ll link {:?}", name), || { + time_ext(cgcx.time_passes, &format!("ll link {:?}", name), || { let data = bc_decoded.data(); linker.add(&data).map_err(|()| { let msg = format!("failed to load bc of {:?}", name); @@ -590,7 +590,7 @@ pub(crate) fn run_pass_manager(cgcx: &CodegenContext, llvm::LLVMRustAddPass(pm, pass.unwrap()); } - time_ext(cgcx.time_passes, None, "LTO passes", || + time_ext(cgcx.time_passes, "LTO passes", || llvm::LLVMRunPassManager(pm, module.module_llvm.llmod())); llvm::LLVMDisposePassManager(pm); diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 78db90b57b53..17cf9ed5ba76 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -427,7 +427,6 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext, { let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_function_passes"); time_ext(config.time_passes, - None, &format!("llvm function passes [{}]", module_name.unwrap()), || { llvm::LLVMRustRunFunctionPassManager(fpm, llmod) @@ -436,7 +435,6 @@ pub(crate) unsafe fn optimize(cgcx: &CodegenContext, { let _timer = cgcx.prof.generic_activity("LLVM_module_optimize_module_passes"); time_ext(config.time_passes, - None, &format!("llvm module passes [{}]", module_name.unwrap()), || { llvm::LLVMRunPassManager(mpm, llmod) @@ -538,7 +536,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, embed_bitcode(cgcx, llcx, llmod, None); } - time_ext(config.time_passes, None, &format!("codegen passes [{}]", module_name.unwrap()), + time_ext(config.time_passes, &format!("codegen passes [{}]", module_name.unwrap()), || -> Result<(), FatalError> { if config.emit_ir { let _timer = cgcx.prof.generic_activity("LLVM_module_codegen_emit_ir"); diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 3b7ae5e33d5e..1ce008e4d74d 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1527,7 +1527,7 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( let name = cratepath.file_name().unwrap().to_str().unwrap(); let name = &name[3..name.len() - 5]; // chop off lib/.rlib - time_ext(sess.time_extended(), Some(sess), &format!("altering {}.rlib", name), || { + time_ext(sess.time_extended(), &format!("altering {}.rlib", name), || { let mut archive = ::new(sess, &dst, Some(cratepath)); archive.update_symbols(); diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 90aefb0f3241..b7f4df62b494 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -160,7 +160,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { } MaybeAsync::Async(std::thread::spawn(move || { - time_ext(time_passes, None, "background load prev dep-graph", move || { + time_ext(time_passes, "background load prev dep-graph", move || { match load_data(report_incremental_info, &path) { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, LoadResult::Error { message } => LoadResult::Error { message }, diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index dae8fb242d58..b26bd75c974c 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -1,6 +1,5 @@ use crate::queries::Queries; use crate::util; -use crate::profile; pub use crate::passes::BoxedResolver; use rustc::lint; @@ -115,17 +114,7 @@ where compiler.sess.diagnostic().print_error_count(&util::diagnostics_registry()); }); - if compiler.sess.profile_queries() { - profile::begin(&compiler.sess); - } - - let r = f(&compiler); - - if compiler.sess.profile_queries() { - profile::dump(&compiler.sess, "profile_queries".to_string()) - } - - r + f(&compiler) } pub fn run_compiler(mut config: Config, f: F) -> R diff --git a/src/librustc_interface/lib.rs b/src/librustc_interface/lib.rs index 2e593d441553..6be36e9b9001 100644 --- a/src/librustc_interface/lib.rs +++ b/src/librustc_interface/lib.rs @@ -16,6 +16,5 @@ mod passes; mod queries; pub mod util; mod proc_macro_decls; -mod profile; pub use interface::{run_compiler, Config}; diff --git a/src/librustc_interface/profile/mod.rs b/src/librustc_interface/profile/mod.rs deleted file mode 100644 index 2e71d46f4154..000000000000 --- a/src/librustc_interface/profile/mod.rs +++ /dev/null @@ -1,297 +0,0 @@ -use log::debug; -use rustc::dep_graph::DepNode; -use rustc::session::Session; -use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan}; -use std::sync::mpsc::{Receiver}; -use std::io::{Write}; -use std::time::{Duration, Instant}; - -pub mod trace; - -/// begin a profile thread, if not already running -pub fn begin(sess: &Session) { - use std::thread; - use std::sync::mpsc::{channel}; - let (tx, rx) = channel(); - if profq_set_chan(sess, tx) { - thread::spawn(move || profile_queries_thread(rx)); - } -} - -/// dump files with profiling information to the given base path, and -/// wait for this dump to complete. -/// -/// wraps the RPC (send/recv channel logic) of requesting a dump. -pub fn dump(sess: &Session, path: String) { - use std::sync::mpsc::{channel}; - let (tx, rx) = channel(); - let params = ProfQDumpParams { - path, - ack: tx, - // FIXME: Add another compiler flag to toggle whether this log - // is written; false for now - dump_profq_msg_log: true, - }; - profq_msg(sess, ProfileQueriesMsg::Dump(params)); - let _ = rx.recv().unwrap(); -} - -// State for parsing recursive trace structure in separate thread, via messages -#[derive(Clone, Eq, PartialEq)] -enum ParseState { - // No (local) parse state; may be parsing a tree, focused on a - // sub-tree that could be anything. - Clear, - // Have Query information from the last message - HaveQuery(trace::Query, Instant), - // Have "time-begin" information from the last message (doit flag, and message) - HaveTimeBegin(String, Instant), - // Have "task-begin" information from the last message - HaveTaskBegin(DepNode, Instant), -} -struct StackFrame { - pub parse_st: ParseState, - pub traces: Vec, -} - -fn total_duration(traces: &[trace::Rec]) -> Duration { - Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum() -} - -// profiling thread; retains state (in local variables) and dump traces, upon request. -fn profile_queries_thread(r: Receiver) { - use self::trace::*; - use std::fs::File; - - let mut profq_msgs: Vec = vec![]; - let mut frame: StackFrame = StackFrame { parse_st: ParseState::Clear, traces: vec![] }; - let mut stack: Vec = vec![]; - loop { - let msg = r.recv(); - if let Err(_recv_err) = msg { - // FIXME: Perhaps do something smarter than simply quitting? - break - }; - let msg = msg.unwrap(); - debug!("profile_queries_thread: {:?}", msg); - - // Meta-level versus _actual_ queries messages - match msg { - ProfileQueriesMsg::Halt => return, - ProfileQueriesMsg::Dump(params) => { - assert!(stack.is_empty()); - assert!(frame.parse_st == ParseState::Clear); - - // write log of all messages - if params.dump_profq_msg_log { - let mut log_file = - File::create(format!("{}.log.txt", params.path)).unwrap(); - for m in profq_msgs.iter() { - writeln!(&mut log_file, "{:?}", m).unwrap() - }; - } - - // write HTML file, and counts file - let html_path = format!("{}.html", params.path); - let mut html_file = File::create(&html_path).unwrap(); - - let counts_path = format!("{}.counts.txt", params.path); - let mut counts_file = File::create(&counts_path).unwrap(); - - writeln!(html_file, - "\n\n", - "profile_queries.css").unwrap(); - writeln!(html_file, "\n\n").unwrap(); - trace::write_traces(&mut html_file, &mut counts_file, &frame.traces); - writeln!(html_file, "\n").unwrap(); - - let ack_path = format!("{}.ack", params.path); - let ack_file = File::create(&ack_path).unwrap(); - drop(ack_file); - - // Tell main thread that we are done, e.g., so it can exit - params.ack.send(()).unwrap(); - } - // Actual query message: - msg => { - // Record msg in our log - profq_msgs.push(msg.clone()); - // Respond to the message, knowing that we've already handled Halt and Dump, above. - match (frame.parse_st.clone(), msg) { - (_, ProfileQueriesMsg::Halt) | (_, ProfileQueriesMsg::Dump(_)) => { - unreachable!(); - }, - // Parse State: Clear - (ParseState::Clear, - ProfileQueriesMsg::QueryBegin(span, querymsg)) => { - let start = Instant::now(); - frame.parse_st = ParseState::HaveQuery - (Query { span, msg: querymsg }, start) - }, - (ParseState::Clear, - ProfileQueriesMsg::CacheHit) => { - panic!("parse error: unexpected CacheHit; expected QueryBegin") - }, - (ParseState::Clear, - ProfileQueriesMsg::ProviderBegin) => { - panic!("parse error: expected QueryBegin before beginning a provider") - }, - (ParseState::Clear, - ProfileQueriesMsg::ProviderEnd) => { - let provider_extent = frame.traces; - match stack.pop() { - None => - panic!("parse error: expected a stack frame; found an empty stack"), - Some(old_frame) => { - match old_frame.parse_st { - ParseState::HaveQuery(q, start) => { - let duration = start.elapsed(); - frame = StackFrame{ - parse_st: ParseState::Clear, - traces: old_frame.traces - }; - let dur_extent = total_duration(&provider_extent); - let trace = Rec { - effect: Effect::QueryBegin(q, CacheCase::Miss), - extent: Box::new(provider_extent), - start: start, - dur_self: duration - dur_extent, - dur_total: duration, - }; - frame.traces.push( trace ); - }, - _ => panic!("internal parse error: malformed parse stack") - } - } - } - }, - (ParseState::Clear, - ProfileQueriesMsg::TimeBegin(msg)) => { - let start = Instant::now(); - frame.parse_st = ParseState::HaveTimeBegin(msg, start); - stack.push(frame); - frame = StackFrame{parse_st: ParseState::Clear, traces: vec![]}; - }, - (_, ProfileQueriesMsg::TimeBegin(_)) => { - panic!("parse error; did not expect time begin here"); - }, - (ParseState::Clear, - ProfileQueriesMsg::TimeEnd) => { - let provider_extent = frame.traces; - match stack.pop() { - None => - panic!("parse error: expected a stack frame; found an empty stack"), - Some(old_frame) => { - match old_frame.parse_st { - ParseState::HaveTimeBegin(msg, start) => { - let duration = start.elapsed(); - frame = StackFrame{ - parse_st: ParseState::Clear, - traces: old_frame.traces - }; - let dur_extent = total_duration(&provider_extent); - let trace = Rec { - effect: Effect::TimeBegin(msg), - extent: Box::new(provider_extent), - start: start, - dur_total: duration, - dur_self: duration - dur_extent, - }; - frame.traces.push( trace ); - }, - _ => panic!("internal parse error: malformed parse stack") - } - } - } - }, - (_, ProfileQueriesMsg::TimeEnd) => { - panic!("parse error") - }, - (ParseState::Clear, - ProfileQueriesMsg::TaskBegin(key)) => { - let start = Instant::now(); - frame.parse_st = ParseState::HaveTaskBegin(key, start); - stack.push(frame); - frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] }; - }, - (_, ProfileQueriesMsg::TaskBegin(_)) => { - panic!("parse error; did not expect time begin here"); - }, - (ParseState::Clear, - ProfileQueriesMsg::TaskEnd) => { - let provider_extent = frame.traces; - match stack.pop() { - None => - panic!("parse error: expected a stack frame; found an empty stack"), - Some(old_frame) => { - match old_frame.parse_st { - ParseState::HaveTaskBegin(key, start) => { - let duration = start.elapsed(); - frame = StackFrame{ - parse_st: ParseState::Clear, - traces: old_frame.traces - }; - let dur_extent = total_duration(&provider_extent); - let trace = Rec { - effect: Effect::TaskBegin(key), - extent: Box::new(provider_extent), - start: start, - dur_total: duration, - dur_self: duration - dur_extent, - }; - frame.traces.push( trace ); - }, - _ => panic!("internal parse error: malformed parse stack") - } - } - } - }, - (_, ProfileQueriesMsg::TaskEnd) => { - panic!("parse error") - }, - // Parse State: HaveQuery - (ParseState::HaveQuery(q,start), - ProfileQueriesMsg::CacheHit) => { - let duration = start.elapsed(); - let trace : Rec = Rec{ - effect: Effect::QueryBegin(q, CacheCase::Hit), - extent: Box::new(vec![]), - start: start, - dur_self: duration, - dur_total: duration, - }; - frame.traces.push( trace ); - frame.parse_st = ParseState::Clear; - }, - (ParseState::HaveQuery(_, _), - ProfileQueriesMsg::ProviderBegin) => { - stack.push(frame); - frame = StackFrame{ parse_st: ParseState::Clear, traces: vec![] }; - }, - - // Parse errors: - - (ParseState::HaveQuery(q, _), - ProfileQueriesMsg::ProviderEnd) => { - panic!("parse error: unexpected ProviderEnd; \ - expected something else to follow BeginQuery for {:?}", q) - }, - (ParseState::HaveQuery(q1, _), - ProfileQueriesMsg::QueryBegin(span2, querymsg2)) => { - panic!("parse error: unexpected QueryBegin; \ - earlier query is unfinished: {:?} and now {:?}", - q1, Query{span:span2, msg: querymsg2}) - }, - (ParseState::HaveTimeBegin(_, _), _) => { - unreachable!() - }, - (ParseState::HaveTaskBegin(_, _), _) => { - unreachable!() - }, - } - } - } - } -} diff --git a/src/librustc_interface/profile/trace.rs b/src/librustc_interface/profile/trace.rs deleted file mode 100644 index 95c4ea6ff234..000000000000 --- a/src/librustc_interface/profile/trace.rs +++ /dev/null @@ -1,304 +0,0 @@ -use super::*; -use syntax_pos::SpanData; -use rustc_data_structures::fx::FxHashMap; -use rustc::util::common::QueryMsg; -use std::fs::File; -use std::time::{Duration, Instant}; -use rustc::dep_graph::{DepNode}; - -#[derive(Debug, Clone, Eq, PartialEq)] -pub struct Query { - pub span: SpanData, - pub msg: QueryMsg, -} -pub enum Effect { - QueryBegin(Query, CacheCase), - TimeBegin(String), - TaskBegin(DepNode), -} -pub enum CacheCase { - Hit, Miss -} -/// Recursive trace structure -pub struct Rec { - pub effect: Effect, - pub start: Instant, - pub dur_self: Duration, - pub dur_total: Duration, - pub extent: Box>, -} -pub struct QueryMetric { - pub count: usize, - pub dur_self: Duration, - pub dur_total: Duration, -} - -fn cons(s: &str) -> String { - let first = s.split(|d| d == '(' || d == '{').next(); - assert!(first.is_some() && first != Some("")); - first.unwrap().to_owned() -} - -pub fn cons_of_query_msg(q: &trace::Query) -> String { - cons(&format!("{:?}", q.msg)) -} - -pub fn cons_of_key(k: &DepNode) -> String { - cons(&format!("{:?}", k)) -} - -// First return value is text; second return value is a CSS class -pub fn html_of_effect(eff: &Effect) -> (String, String) { - match *eff { - Effect::TimeBegin(ref msg) => { - (msg.clone(), - "time-begin".to_string()) - }, - Effect::TaskBegin(ref key) => { - let cons = cons_of_key(key); - (cons.clone(), format!("{} task-begin", cons)) - }, - Effect::QueryBegin(ref qmsg, ref cc) => { - let cons = cons_of_query_msg(qmsg); - (cons.clone(), - format!("{} {}", - cons, - match *cc { - CacheCase::Hit => "hit", - CacheCase::Miss => "miss", - })) - } - } -} - -// First return value is text; second return value is a CSS class -fn html_of_duration(_start: &Instant, dur: &Duration) -> (String, String) { - use rustc::util::common::duration_to_secs_str; - (duration_to_secs_str(dur.clone()), String::new()) -} - -fn html_of_fraction(frac: f64) -> (String, &'static str) { - let css = { - if frac > 0.50 { "frac-50" } - else if frac > 0.40 { "frac-40" } - else if frac > 0.30 { "frac-30" } - else if frac > 0.20 { "frac-20" } - else if frac > 0.10 { "frac-10" } - else if frac > 0.05 { "frac-05" } - else if frac > 0.02 { "frac-02" } - else if frac > 0.01 { "frac-01" } - else if frac > 0.001 { "frac-001" } - else { "frac-0" } - }; - let percent = frac * 100.0; - - if percent > 0.1 { - (format!("{:.1}%", percent), css) - } else { - ("< 0.1%".to_string(), css) - } -} - -fn total_duration(traces: &[Rec]) -> Duration { - Duration::new(0, 0) + traces.iter().map(|t| t.dur_total).sum() -} - -fn duration_div(nom: Duration, den: Duration) -> f64 { - fn to_nanos(d: Duration) -> u64 { - d.as_secs() * 1_000_000_000 + d.subsec_nanos() as u64 - } - - to_nanos(nom) as f64 / to_nanos(den) as f64 -} - -fn write_traces_rec(file: &mut File, traces: &[Rec], total: Duration, depth: usize) { - for t in traces { - let (eff_text, eff_css_classes) = html_of_effect(&t.effect); - let (dur_text, dur_css_classes) = html_of_duration(&t.start, &t.dur_total); - let fraction = duration_div(t.dur_total, total); - let percent = fraction * 100.0; - let (frc_text, frc_css_classes) = html_of_fraction(fraction); - writeln!(file, "
", - depth, - t.extent.len(), - /* Heuristic for 'important' CSS class: */ - if t.extent.len() > 5 || percent >= 1.0 { " important" } else { "" }, - eff_css_classes, - dur_css_classes, - frc_css_classes, - ).unwrap(); - writeln!(file, "
{}
", eff_text).unwrap(); - writeln!(file, "
{}
", dur_text).unwrap(); - writeln!(file, "
{}
", frc_text).unwrap(); - write_traces_rec(file, &t.extent, total, depth + 1); - writeln!(file, "
").unwrap(); - } -} - -fn compute_counts_rec(counts: &mut FxHashMap, traces: &[Rec]) { - counts.reserve(traces.len()); - for t in traces.iter() { - match t.effect { - Effect::TimeBegin(ref msg) => { - let qm = match counts.get(msg) { - Some(_qm) => panic!("TimeBegin with non-unique, repeat message"), - None => QueryMetric { - count: 1, - dur_self: t.dur_self, - dur_total: t.dur_total, - } - }; - counts.insert(msg.clone(), qm); - }, - Effect::TaskBegin(ref key) => { - let cons = cons_of_key(key); - let qm = match counts.get(&cons) { - Some(qm) => - QueryMetric { - count: qm.count + 1, - dur_self: qm.dur_self + t.dur_self, - dur_total: qm.dur_total + t.dur_total, - }, - None => QueryMetric { - count: 1, - dur_self: t.dur_self, - dur_total: t.dur_total, - } - }; - counts.insert(cons, qm); - }, - Effect::QueryBegin(ref qmsg, ref _cc) => { - let qcons = cons_of_query_msg(qmsg); - let qm = match counts.get(&qcons) { - Some(qm) => - QueryMetric { - count: qm.count + 1, - dur_total: qm.dur_total + t.dur_total, - dur_self: qm.dur_self + t.dur_self - }, - None => QueryMetric { - count: 1, - dur_total: t.dur_total, - dur_self: t.dur_self, - } - }; - counts.insert(qcons, qm); - } - } - compute_counts_rec(counts, &t.extent) - } -} - -pub fn write_counts(count_file: &mut File, counts: &mut FxHashMap) { - use rustc::util::common::duration_to_secs_str; - use std::cmp::Reverse; - - let mut data = counts.iter().map(|(ref cons, ref qm)| - (cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone()) - ).collect::>(); - - data.sort_by_key(|k| Reverse(k.3)); - for (cons, count, dur_total, dur_self) in data { - writeln!(count_file, "{}, {}, {}, {}", - cons, count, - duration_to_secs_str(dur_total), - duration_to_secs_str(dur_self) - ).unwrap(); - } -} - -pub fn write_traces(html_file: &mut File, counts_file: &mut File, traces: &[Rec]) { - let capacity = traces.iter().fold(0, |acc, t| acc + 1 + t.extent.len()); - let mut counts = FxHashMap::with_capacity_and_hasher(capacity, Default::default()); - compute_counts_rec(&mut counts, traces); - write_counts(counts_file, &mut counts); - - let total: Duration = total_duration(traces); - write_traces_rec(html_file, traces, total, 0) -} - -pub fn write_style(html_file: &mut File) { - write!(html_file, "{}", " -body { - font-family: sans-serif; - background: black; -} -.trace { - color: black; - display: inline-block; - border-style: solid; - border-color: red; - border-width: 1px; - border-radius: 5px; - padding: 0px; - margin: 1px; - font-size: 0px; -} -.task-begin { - border-width: 1px; - color: white; - border-color: #ff8; - font-size: 0px; -} -.miss { - border-color: red; - border-width: 1px; -} -.extent-0 { - padding: 2px; -} -.time-begin { - border-width: 4px; - font-size: 12px; - color: white; - border-color: #afa; -} -.important { - border-width: 3px; - font-size: 12px; - color: white; - border-color: #f77; -} -.hit { - padding: 0px; - border-color: blue; - border-width: 3px; -} -.eff { - color: #fff; - display: inline-block; -} -.frc { - color: #7f7; - display: inline-block; -} -.dur { - display: none -} -.frac-50 { - padding: 10px; - border-width: 10px; - font-size: 32px; -} -.frac-40 { - padding: 8px; - border-width: 8px; - font-size: 24px; -} -.frac-30 { - padding: 6px; - border-width: 6px; - font-size: 18px; -} -.frac-20 { - padding: 4px; - border-width: 6px; - font-size: 16px; -} -.frac-10 { - padding: 2px; - border-width: 6px; - font-size: 14px; -} -").unwrap(); -} From 76456e74066d7594f23757ebade169c33276ea4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 19:32:56 -0700 Subject: [PATCH 052/545] review comments --- src/librustc_errors/diagnostic.rs | 84 ++++++++++++++++--------------- src/librustc_errors/emitter.rs | 14 +++--- 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 811a48a39f0d..fd74d8673da4 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -304,6 +304,24 @@ impl Diagnostic { msg: &str, suggestion: String, applicability: Applicability, + ) -> &mut Self { + self.span_suggestion_with_style( + sp, + msg, + suggestion, + applicability, + SuggestionStyle::ShowCode, + ); + self + } + + pub fn span_suggestion_with_style( + &mut self, + sp: Span, + msg: &str, + suggestion: String, + applicability: Applicability, + style: SuggestionStyle, ) -> &mut Self { self.suggestions.push(CodeSuggestion { substitutions: vec![Substitution { @@ -313,7 +331,7 @@ impl Diagnostic { }], }], msg: msg.to_owned(), - style: SuggestionStyle::ShowCode, + style, applicability, }); self @@ -326,17 +344,13 @@ impl Diagnostic { suggestion: String, applicability: Applicability, ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: vec![SubstitutionPart { - snippet: suggestion, - span: sp, - }], - }], - msg: msg.to_owned(), - style: SuggestionStyle::ShowAlways, + self.span_suggestion_with_style( + sp, + msg, + suggestion, applicability, - }); + SuggestionStyle::ShowAlways, + ); self } @@ -369,17 +383,13 @@ impl Diagnostic { pub fn span_suggestion_short( &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: vec![SubstitutionPart { - snippet: suggestion, - span: sp, - }], - }], - msg: msg.to_owned(), - style: SuggestionStyle::HideCodeInline, + self.span_suggestion_with_style( + sp, + msg, + suggestion, applicability, - }); + SuggestionStyle::HideCodeInline, + ); self } @@ -392,17 +402,13 @@ impl Diagnostic { pub fn span_suggestion_hidden( &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: vec![SubstitutionPart { - snippet: suggestion, - span: sp, - }], - }], - msg: msg.to_owned(), - style: SuggestionStyle::HideCodeAlways, + self.span_suggestion_with_style( + sp, + msg, + suggestion, applicability, - }); + SuggestionStyle::HideCodeAlways, + ); self } @@ -413,17 +419,13 @@ impl Diagnostic { pub fn tool_only_span_suggestion( &mut self, sp: Span, msg: &str, suggestion: String, applicability: Applicability ) -> &mut Self { - self.suggestions.push(CodeSuggestion { - substitutions: vec![Substitution { - parts: vec![SubstitutionPart { - snippet: suggestion, - span: sp, - }], - }], - msg: msg.to_owned(), - style: SuggestionStyle::CompletelyHidden, + self.span_suggestion_with_style( + sp, + msg, + suggestion, applicability, - }); + SuggestionStyle::CompletelyHidden, + ); self } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index bd8191065eec..54b0353d992f 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -218,12 +218,14 @@ pub trait Emitter { sugg.msg.split_whitespace().count() < 10 && // don't display multiline suggestions as labels !sugg.substitutions[0].parts[0].snippet.contains('\n') && - // when this style is set we want the suggestion to be a message, not inline - sugg.style != SuggestionStyle::HideCodeAlways && - // trivial suggestion for tooling's sake, never shown - sugg.style != SuggestionStyle::CompletelyHidden && - // subtle suggestion, never shown inline - sugg.style != SuggestionStyle::ShowAlways + ![ + // when this style is set we want the suggestion to be a message, not inline + SuggestionStyle::HideCodeAlways, + // trivial suggestion for tooling's sake, never shown + SuggestionStyle::CompletelyHidden, + // subtle suggestion, never shown inline + SuggestionStyle::ShowAlways, + ].contains(&sugg.style) { let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); let msg = if substitution.len() == 0 || sugg.style.hide_inline() { From 9a1a3b9013221b90a9b02ecd23614b6e2fcf6a2d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Oct 2019 11:02:04 +1000 Subject: [PATCH 053/545] Combine two `match` arms in `specialize()`. This reduces the number of call sites for `constructor_intersects_pattern()` from two to one, which the next commit will take advantage of. --- src/librustc_mir/hair/pattern/_match.rs | 138 ++++++++++++------------ 1 file changed, 68 insertions(+), 70 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index d3bc61a4dde5..cf8ef8c76998 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -434,6 +434,13 @@ enum Constructor<'tcx> { } impl<'tcx> Constructor<'tcx> { + fn is_slice(&self) -> bool { + match self { + Slice { .. } => true, + _ => false, + } + } + fn variant_index_for_adt<'a>( &self, cx: &MatchCheckCtxt<'a, 'tcx>, @@ -1766,85 +1773,76 @@ fn specialize<'p, 'a: 'p, 'tcx>( Some(smallvec![subpattern]) } - PatKind::Constant { value } => { - match *constructor { - Slice(..) => { - // we extract an `Option` for the pointer because slices of zero elements don't - // necessarily point to memory, they are usually just integers. The only time - // they should be pointing to memory is when they are subslices of nonzero - // slices - let (alloc, offset, n, ty) = match value.ty.kind { - ty::Array(t, n) => { - match value.val { - ConstValue::ByRef { offset, alloc, .. } => ( - alloc, - offset, - n.eval_usize(cx.tcx, cx.param_env), - t, - ), - _ => span_bug!( - pat.span, - "array pattern is {:?}", value, - ), - } - }, - ty::Slice(t) => { - match value.val { - ConstValue::Slice { data, start, end } => ( - data, - Size::from_bytes(start as u64), - (end - start) as u64, - t, - ), - ConstValue::ByRef { .. } => { - // FIXME(oli-obk): implement `deref` for `ConstValue` - return None; - }, - _ => span_bug!( - pat.span, - "slice pattern constant must be scalar pair but is {:?}", - value, - ), - } + PatKind::Constant { value } if constructor.is_slice() => { + // We extract an `Option` for the pointer because slices of zero + // elements don't necessarily point to memory, they are usually + // just integers. The only time they should be pointing to memory + // is when they are subslices of nonzero slices. + let (alloc, offset, n, ty) = match value.ty.kind { + ty::Array(t, n) => { + match value.val { + ConstValue::ByRef { offset, alloc, .. } => ( + alloc, + offset, + n.eval_usize(cx.tcx, cx.param_env), + t, + ), + _ => span_bug!( + pat.span, + "array pattern is {:?}", value, + ), + } + }, + ty::Slice(t) => { + match value.val { + ConstValue::Slice { data, start, end } => ( + data, + Size::from_bytes(start as u64), + (end - start) as u64, + t, + ), + ConstValue::ByRef { .. } => { + // FIXME(oli-obk): implement `deref` for `ConstValue` + return None; }, _ => span_bug!( pat.span, - "unexpected const-val {:?} with ctor {:?}", + "slice pattern constant must be scalar pair but is {:?}", value, - constructor, ), - }; - if wild_patterns.len() as u64 == n { - // convert a constant slice/array pattern to a list of patterns. - let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; - let ptr = Pointer::new(AllocId(0), offset); - (0..n).map(|i| { - let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; - let scalar = alloc.read_scalar( - &cx.tcx, ptr, layout.size, - ).ok()?; - let scalar = scalar.not_undef().ok()?; - let value = ty::Const::from_scalar(cx.tcx, scalar, ty); - let pattern = Pat { - ty, - span: pat.span, - kind: box PatKind::Constant { value }, - }; - Some(&*cx.pattern_arena.alloc(pattern)) - }).collect() - } else { - None } - } - _ => { - // If the constructor is a: - // Single value: add a row if the constructor equals the pattern. - // Range: add a row if the constructor contains the pattern. - constructor_intersects_pattern(cx.tcx, cx.param_env, constructor, pat) - } + }, + _ => span_bug!( + pat.span, + "unexpected const-val {:?} with ctor {:?}", + value, + constructor, + ), + }; + if wild_patterns.len() as u64 == n { + // convert a constant slice/array pattern to a list of patterns. + let layout = cx.tcx.layout_of(cx.param_env.and(ty)).ok()?; + let ptr = Pointer::new(AllocId(0), offset); + (0..n).map(|i| { + let ptr = ptr.offset(layout.size * i, &cx.tcx).ok()?; + let scalar = alloc.read_scalar( + &cx.tcx, ptr, layout.size, + ).ok()?; + let scalar = scalar.not_undef().ok()?; + let value = ty::Const::from_scalar(cx.tcx, scalar, ty); + let pattern = Pat { + ty, + span: pat.span, + kind: box PatKind::Constant { value }, + }; + Some(&*cx.pattern_arena.alloc(pattern)) + }).collect() + } else { + None } } + PatKind::Constant { .. } | PatKind::Range { .. } => { // If the constructor is a: // Single value: add a row if the pattern contains the constructor. From 62ea39a1c95037dbdbfb49dc1b89d1b67562fddf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Oct 2019 11:04:14 +1000 Subject: [PATCH 054/545] Inline and remove `constructor_intersects_pattern()`. This is a 2% instruction count win on `unicode_normalization-check-clean`. --- src/librustc_mir/hair/pattern/_match.rs | 59 +++++++++++-------------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index cf8ef8c76998..6d33c23dfdeb 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1625,36 +1625,6 @@ fn split_grouped_constructors<'p, 'tcx>( split_ctors } -/// Checks whether there exists any shared value in either `ctor` or `pat` by intersecting them. -fn constructor_intersects_pattern<'p, 'tcx>( - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ctor: &Constructor<'tcx>, - pat: &'p Pat<'tcx>, -) -> Option; 2]>> { - if should_treat_range_exhaustively(tcx, ctor) { - match (IntRange::from_ctor(tcx, param_env, ctor), IntRange::from_pat(tcx, param_env, pat)) { - (Some(ctor), Some(pat)) => { - ctor.intersection(&pat).map(|_| { - let (pat_lo, pat_hi) = pat.range.into_inner(); - let (ctor_lo, ctor_hi) = ctor.range.into_inner(); - assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi); - smallvec![] - }) - } - _ => None, - } - } else { - // Fallback for non-ranges and ranges that involve floating-point numbers, which are not - // conveniently handled by `IntRange`. For these cases, the constructor may not be a range - // so intersection actually devolves into being covered by the pattern. - match constructor_covered_by_range(tcx, param_env, ctor, pat) { - Ok(true) => Some(smallvec![]), - Ok(false) | Err(ErrorReported) => None, - } - } -} - fn constructor_covered_by_range<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -1845,9 +1815,32 @@ fn specialize<'p, 'a: 'p, 'tcx>( PatKind::Constant { .. } | PatKind::Range { .. } => { // If the constructor is a: - // Single value: add a row if the pattern contains the constructor. - // Range: add a row if the constructor intersects the pattern. - constructor_intersects_pattern(cx.tcx, cx.param_env, constructor, pat) + // - Single value: add a row if the pattern contains the constructor. + // - Range: add a row if the constructor intersects the pattern. + if should_treat_range_exhaustively(cx.tcx, constructor) { + match (IntRange::from_ctor(cx.tcx, cx.param_env, constructor), + IntRange::from_pat(cx.tcx, cx.param_env, pat)) { + (Some(ctor), Some(pat)) => { + ctor.intersection(&pat).map(|_| { + let (pat_lo, pat_hi) = pat.range.into_inner(); + let (ctor_lo, ctor_hi) = ctor.range.into_inner(); + assert!(pat_lo <= ctor_lo && ctor_hi <= pat_hi); + smallvec![] + }) + } + _ => None, + } + } else { + // Fallback for non-ranges and ranges that involve + // floating-point numbers, which are not conveniently handled + // by `IntRange`. For these cases, the constructor may not be a + // range so intersection actually devolves into being covered + // by the pattern. + match constructor_covered_by_range(cx.tcx, cx.param_env, constructor, pat) { + Ok(true) => Some(smallvec![]), + Ok(false) | Err(ErrorReported) => None, + } + } } PatKind::Array { ref prefix, ref slice, ref suffix } | From a69e0e0ab402591e9e42c596054ea45df702f3e0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Oct 2019 13:16:37 +1000 Subject: [PATCH 055/545] Rearrange `IntRange::from_{ctor,pat}()`. This commit moves a lot of code around but doesn't change functionality at all. The main goal was for `from_pat()` to no longer call `from_ctor()`. The increase in inlining resulted in less function call overhead, for a 3% instruction count win on `unicode_normalization-check-clean`. --- src/librustc_mir/hair/pattern/_match.rs | 109 +++++++++++++++--------- 1 file changed, 69 insertions(+), 40 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 6d33c23dfdeb..2a7be75650f2 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -834,6 +834,59 @@ struct IntRange<'tcx> { } impl<'tcx> IntRange<'tcx> { + #[inline] + fn is_integral(ty: Ty<'_>) -> bool { + match ty.kind { + ty::Char | ty::Int(_) | ty::Uint(_) => true, + _ => false, + } + } + + #[inline] + fn from_const( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + value: &Const<'tcx>, + ) -> Option> { + if Self::is_integral(value.ty) { + let ty = value.ty; + if let Some(val) = value.try_eval_bits(tcx, param_env, ty) { + let bias = IntRange::signed_bias(tcx, ty); + let val = val ^ bias; + Some(IntRange { range: val..=val, ty }) + } else { + None + } + } else { + None + } + } + + #[inline] + fn from_range( + tcx: TyCtxt<'tcx>, + lo: u128, + hi: u128, + ty: Ty<'tcx>, + end: &RangeEnd, + ) -> Option> { + if Self::is_integral(ty) { + // Perform a shift if the underlying types are signed, + // which makes the interval arithmetic simpler. + let bias = IntRange::signed_bias(tcx, ty); + let (lo, hi) = (lo ^ bias, hi ^ bias); + // Make sure the interval is well-formed. + if lo > hi || lo == hi && *end == RangeEnd::Excluded { + None + } else { + let offset = (*end == RangeEnd::Excluded) as u128; + Some(IntRange { range: lo..=(hi - offset), ty }) + } + } else { + None + } + } + fn from_ctor( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -841,37 +894,9 @@ impl<'tcx> IntRange<'tcx> { ) -> Option> { // Floating-point ranges are permitted and we don't want // to consider them when constructing integer ranges. - fn is_integral(ty: Ty<'_>) -> bool { - match ty.kind { - ty::Char | ty::Int(_) | ty::Uint(_) => true, - _ => false, - } - } - match ctor { - ConstantRange(lo, hi, ty, end) if is_integral(ty) => { - // Perform a shift if the underlying types are signed, - // which makes the interval arithmetic simpler. - let bias = IntRange::signed_bias(tcx, ty); - let (lo, hi) = (lo ^ bias, hi ^ bias); - // Make sure the interval is well-formed. - if lo > hi || lo == hi && *end == RangeEnd::Excluded { - None - } else { - let offset = (*end == RangeEnd::Excluded) as u128; - Some(IntRange { range: lo..=(hi - offset), ty }) - } - } - ConstantValue(val) if is_integral(val.ty) => { - let ty = val.ty; - if let Some(val) = val.try_eval_bits(tcx, param_env, ty) { - let bias = IntRange::signed_bias(tcx, ty); - let val = val ^ bias; - Some(IntRange { range: val..=val, ty }) - } else { - None - } - } + ConstantRange(lo, hi, ty, end) => Self::from_range(tcx, *lo, *hi, ty, end), + ConstantValue(val) => Self::from_const(tcx, param_env, val), _ => None, } } @@ -881,22 +906,26 @@ impl<'tcx> IntRange<'tcx> { param_env: ty::ParamEnv<'tcx>, mut pat: &Pat<'tcx>, ) -> Option> { - let range = loop { + loop { match pat.kind { - box PatKind::Constant { value } => break ConstantValue(value), - box PatKind::Range(PatRange { lo, hi, end }) => break ConstantRange( - lo.eval_bits(tcx, param_env, lo.ty), - hi.eval_bits(tcx, param_env, hi.ty), - lo.ty, - end, - ), + box PatKind::Constant { value } => { + return Self::from_const(tcx, param_env, value); + } + box PatKind::Range(PatRange { lo, hi, end }) => { + return Self::from_range( + tcx, + lo.eval_bits(tcx, param_env, lo.ty), + hi.eval_bits(tcx, param_env, hi.ty), + &lo.ty, + &end, + ); + } box PatKind::AscribeUserType { ref subpattern, .. } => { pat = subpattern; }, _ => return None, } - }; - Self::from_ctor(tcx, param_env, &range) + } } // The return value of `signed_bias` should be XORed with an endpoint to encode/decode it. From 5515a976464e488949a6a7324ac41ecaf3246a19 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Oct 2019 14:29:20 +1000 Subject: [PATCH 056/545] Introduce a special case in `IntRange::from_const`. The `if let Some(val) = value.try_eval_bits(...)` branch in `from_const()` is very hot for the `unicode_normalization` benchmark. This commit introduces a special-case alternative for scalars that avoids `try_eval_bits()` and all the functions it calls (`Const::eval()`, `ConstValue::try_to_bits()`, `ConstValue::try_to_scalar()`, and `Scalar::to_bits()`), instead extracting the result immediately. The type and value checking done by `Scalar::to_bits()` is replicated by moving it into a new function `Scalar::check_raw()` and using that new function in the special case. PR #64673 introduced some special-case handling of scalar types in `Const::try_eval_bits()`. This handling is now moved out of that function into the new `IntRange::integral_size_and_signed_bias` function. This commit reduces the instruction count for `unicode_normalization-check-clean` by about 10%. --- src/librustc/mir/interpret/value.rs | 11 +++++--- src/librustc/ty/sty.rs | 18 ++----------- src/librustc_mir/hair/pattern/_match.rs | 35 ++++++++++++++++++++----- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 32f45cd9d472..bbf00cc23ae8 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -343,14 +343,19 @@ 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 } => { - 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); + Self::check_raw(data, size, target_size); Ok(data) } Scalar::Ptr(_) => throw_unsup!(ReadPointerAsBytes), diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e105c44d09ae..d5bb18a2e3e2 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -13,7 +13,7 @@ use rustc_macros::HashStable; use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, GenericArg, GenericArgKind}; use crate::ty::{self, AdtDef, Discr, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable}; use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv}; -use crate::ty::layout::{Size, Integer, IntegerExt, VariantIdx}; +use crate::ty::layout::VariantIdx; use crate::util::captures::Captures; use crate::mir::interpret::{Scalar, GlobalId}; @@ -24,7 +24,6 @@ use std::marker::PhantomData; use std::ops::Range; use rustc_target::spec::abi; use syntax::ast::{self, Ident}; -use syntax::attr::{SignedInt, UnsignedInt}; use syntax::symbol::{kw, InternedString}; use self::InferTy::*; @@ -2299,20 +2298,7 @@ impl<'tcx> Const<'tcx> { ty: Ty<'tcx>, ) -> Option { assert_eq!(self.ty, ty); - // This is purely an optimization -- layout_of is a pretty expensive operation, - // but if we can determine the size without calling it, we don't need all that complexity - // (hashing, caching, etc.). As such, try to skip it. - let size = match ty.kind { - ty::Bool => Size::from_bytes(1), - ty::Char => Size::from_bytes(4), - ty::Int(ity) => { - Integer::from_attr(&tcx, SignedInt(ity)).size() - } - ty::Uint(uty) => { - Integer::from_attr(&tcx, UnsignedInt(uty)).size() - } - _ => tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size, - }; + let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env self.eval(tcx, param_env).val.try_to_bits(size) } diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 2a7be75650f2..c4f59e649b3a 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -842,21 +842,42 @@ impl<'tcx> IntRange<'tcx> { } } + #[inline] + fn integral_size_and_signed_bias(tcx: TyCtxt<'tcx>, ty: Ty<'_>) -> Option<(Size, u128)> { + match ty.kind { + ty::Char => Some((Size::from_bytes(4), 0)), + ty::Int(ity) => { + let size = Integer::from_attr(&tcx, SignedInt(ity)).size(); + Some((size, 1u128 << (size.bits() as u128 - 1))) + } + ty::Uint(uty) => Some((Integer::from_attr(&tcx, UnsignedInt(uty)).size(), 0)), + _ => None, + } + } + #[inline] fn from_const( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, value: &Const<'tcx>, ) -> Option> { - if Self::is_integral(value.ty) { + if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, value.ty) { let ty = value.ty; - if let Some(val) = value.try_eval_bits(tcx, param_env, ty) { - let bias = IntRange::signed_bias(tcx, ty); - let val = val ^ bias; - Some(IntRange { range: val..=val, ty }) + let val = if let 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 { - None - } + return None + }; + let val = val ^ bias; + Some(IntRange { range: val..=val, ty }) } else { None } From 2a3a5447418cc8e7a8b36ae4c9bdf8798a20b873 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 4 Oct 2019 16:22:13 +1000 Subject: [PATCH 057/545] Replace `flat_map()` with `filter_map()` in `is_useful_specialized()`. `filter_map()` is less general, but more efficient, and has the same effect in this case. This commit reduces the instruction count for `unicode_normalization-check-clean` by about 2%. --- src/librustc_mir/hair/pattern/_match.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index c4f59e649b3a..3ea580528772 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1355,9 +1355,11 @@ fn is_useful_specialized<'p, 'a, 'tcx>( } }).collect(); let wild_patterns: Vec<_> = wild_patterns_owned.iter().collect(); - let matrix = Matrix(m.iter().flat_map(|r| { - specialize(cx, &r, &ctor, &wild_patterns) - }).collect()); + let matrix = Matrix( + m.iter() + .filter_map(|r| specialize(cx, &r, &ctor, &wild_patterns)) + .collect() + ); match specialize(cx, v, &ctor, &wild_patterns) { Some(v) => match is_useful(cx, &matrix, &v, witness) { UsefulWithWitness(witnesses) => UsefulWithWitness( From c59d33a063c34cf2b5da440947acb158b3755b99 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 4 Oct 2019 14:20:57 +0200 Subject: [PATCH 058/545] Add some missing normalization calls to fix #63154 --- src/librustc_mir/borrow_check/nll/type_check/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index b24ba596d7e9..60dfc43def79 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1378,7 +1378,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }; let place_ty = place.ty(body, tcx).ty; + let place_ty = self.normalize(place_ty, location); let rv_ty = rv.ty(body, tcx); + let rv_ty = self.normalize(rv_ty, location); if let Err(terr) = self.sub_types_or_anon(rv_ty, place_ty, location.to_locations(), category) { @@ -1654,6 +1656,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { match *destination { Some((ref dest, _target_block)) => { let dest_ty = dest.ty(body, tcx).ty; + let dest_ty = self.normalize(dest_ty, term_location); let category = match *dest { Place { base: PlaceBase::Local(RETURN_PLACE), From 6dd86b411f08b3287ea565b41582641d496b66bf Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 4 Oct 2019 14:21:12 +0200 Subject: [PATCH 059/545] Regression test for #63154. --- src/test/ui/nll/issue-63154-normalize.rs | 34 ++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/ui/nll/issue-63154-normalize.rs diff --git a/src/test/ui/nll/issue-63154-normalize.rs b/src/test/ui/nll/issue-63154-normalize.rs new file mode 100644 index 000000000000..2c18dc5d8e09 --- /dev/null +++ b/src/test/ui/nll/issue-63154-normalize.rs @@ -0,0 +1,34 @@ +// Regression test for rust-lang/rust#63154 +// +// Before, we would ICE after faiing to normalize the destination type +// when checking call destinations and also when checking MIR +// assignment statements. + +// check-pass + +trait HasAssocType { + type Inner; +} + +impl HasAssocType for () { + type Inner = (); +} + +trait Tr: Fn(I) -> Option {} +impl Option> Tr for Q {} + +fn f() -> impl Tr { + |_| None +} + +fn g(f: impl Tr) -> impl Tr { + f +} + +fn h() { + g(f())(()); +} + +fn main() { + h(); +} From d89608829c6778199b61a5b1632db2ae7389febc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 4 Oct 2019 14:43:23 +0200 Subject: [PATCH 060/545] Upgrade librustc_macros dependencies --- Cargo.lock | 24 ++++++++++++++++++------ src/librustc_macros/Cargo.toml | 8 ++++---- src/librustc_macros/src/hash_stable.rs | 8 ++++---- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 80364515a7cc..542f5b3dfaf3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -993,7 +993,7 @@ dependencies = [ "proc-macro2 0.4.30", "quote 0.6.12", "syn 0.15.35", - "synstructure", + "synstructure 0.10.2", ] [[package]] @@ -3165,7 +3165,7 @@ dependencies = [ "proc-macro2 0.4.30", "quote 0.6.12", "syn 0.15.35", - "synstructure", + "synstructure 0.10.2", ] [[package]] @@ -3546,10 +3546,10 @@ name = "rustc_macros" version = "0.1.0" dependencies = [ "itertools 0.8.0", - "proc-macro2 0.4.30", - "quote 0.6.12", - "syn 0.15.35", - "synstructure", + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.5", + "synstructure 0.12.1", ] [[package]] @@ -4242,6 +4242,18 @@ dependencies = [ "unicode-xid 0.1.0", ] +[[package]] +name = "synstructure" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f085a5855930c0441ca1288cf044ea4aecf4f43a91668abdb870b4ba546a203" +dependencies = [ + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.5", + "unicode-xid 0.2.0", +] + [[package]] name = "syntax" version = "0.0.0" diff --git a/src/librustc_macros/Cargo.toml b/src/librustc_macros/Cargo.toml index f989ebc6dfd8..c28fcb1a395f 100644 --- a/src/librustc_macros/Cargo.toml +++ b/src/librustc_macros/Cargo.toml @@ -8,8 +8,8 @@ edition = "2018" proc-macro = true [dependencies] -synstructure = "0.10.2" -syn = { version = "0.15.22", features = ["full"] } -proc-macro2 = "0.4.24" -quote = "0.6.10" +synstructure = "0.12.1" +syn = { version = "1", features = ["full"] } +proc-macro2 = "1" +quote = "1" itertools = "0.8" diff --git a/src/librustc_macros/src/hash_stable.rs b/src/librustc_macros/src/hash_stable.rs index a708f3191dcf..735cfb11b365 100644 --- a/src/librustc_macros/src/hash_stable.rs +++ b/src/librustc_macros/src/hash_stable.rs @@ -15,22 +15,22 @@ fn parse_attributes(field: &syn::Field) -> Attributes { }; for attr in &field.attrs { if let Ok(meta) = attr.parse_meta() { - if &meta.name().to_string() != "stable_hasher" { + if !meta.path().is_ident("stable_hasher") { continue; } let mut any_attr = false; if let Meta::List(list) = meta { for nested in list.nested.iter() { if let NestedMeta::Meta(meta) = nested { - if &meta.name().to_string() == "ignore" { + if meta.path().is_ident("ignore") { attrs.ignore = true; any_attr = true; } - if &meta.name().to_string() == "project" { + if meta.path().is_ident("project") { if let Meta::List(list) = meta { if let Some(nested) = list.nested.iter().next() { if let NestedMeta::Meta(meta) = nested { - attrs.project = Some(meta.name()); + attrs.project = meta.path().get_ident().cloned(); any_attr = true; } } From 2d87bace9687957f37e641ced1613c8b7cca3579 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:02:06 +0800 Subject: [PATCH 061/545] replace GeneratorSubsts with SubstsRef --- src/librustc/ty/sty.rs | 2 +- src/librustc/ty/subst.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3f09bf749edc..c1589b31de78 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -163,7 +163,7 @@ pub enum TyKind<'tcx> { /// The anonymous type of a generator. Used to represent the type of /// `|a| yield a`. - Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), + Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), /// A type representin the types stored inside a generator. /// This should only appear in GeneratorInteriors. diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 537192b0a2e5..de98c098ea53 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -5,7 +5,7 @@ use crate::infer::canonical::Canonical; use crate::ty::{self, Lift, List, Ty, TyCtxt, InferConst, ParamConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::mir::interpret::ConstValue; -use crate::ty::sty::ClosureSubsts; +use crate::ty::sty::{ClosureSubsts, GeneratorSubsts}; use rustc_serialize::{self, Encodable, Encoder, Decodable, Decoder}; use syntax_pos::{Span, DUMMY_SP}; @@ -194,6 +194,14 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { } } + /// Interpret these substitutions as the substitutions of a generator type. + /// Closure substitutions have a particular structure controlled by the + /// compiler that encodes information like the signature and generator kind; + /// see `ty::GeneratorSubsts` struct for more comments. + pub fn as_generator(&'a self) -> GeneratorSubsts<'a> { + GeneratorSubsts { substs: self } + } + /// Creates a `InternalSubsts` that maps each generic parameter to itself. pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { Self::for_item(tcx, def_id, |param, _| { From fa7a87be638e4bcf0403f56413e6dbf9892e5582 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:21:28 +0800 Subject: [PATCH 062/545] generate GeneratorSubsts from SubstsRef --- src/librustc/infer/opaque_types/mod.rs | 8 ++++---- src/librustc/mir/tcx.rs | 2 +- src/librustc/traits/select.rs | 11 ++++++----- src/librustc/ty/context.rs | 2 +- src/librustc/ty/flags.rs | 2 +- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/layout.rs | 15 +++++++-------- src/librustc/ty/outlives.rs | 2 +- src/librustc/ty/print/obsolete.rs | 2 +- src/librustc/ty/print/pretty.rs | 4 ++-- src/librustc/ty/sty.rs | 7 ++++--- src/librustc/ty/walk.rs | 6 ++---- 12 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index e7205dd47a61..d45869ed160c 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -733,12 +733,12 @@ where // Skip lifetime parameters of the enclosing item(s) // Also skip the witness type, because that has no free regions. - for upvar_ty in substs.upvar_tys(def_id, self.tcx) { + for upvar_ty in substs.as_generator().upvar_tys(def_id, self.tcx) { upvar_ty.visit_with(self); } - substs.return_ty(def_id, self.tcx).visit_with(self); - substs.yield_ty(def_id, self.tcx).visit_with(self); + substs.as_generator().return_ty(def_id, self.tcx).visit_with(self); + substs.as_generator().yield_ty(def_id, self.tcx).visit_with(self); } _ => { ty.super_visit_with(self); @@ -902,7 +902,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ty::Generator(def_id, substs, movability) => { let generics = self.tcx.generics_of(def_id); let substs = - self.tcx.mk_substs(substs.substs.iter().enumerate().map(|(index, &kind)| { + self.tcx.mk_substs(substs.iter().enumerate().map(|(index, &kind)| { if index < generics.parent_count { // Accommodate missing regions in the parent kinds... self.fold_kind_mapping_missing_regions_to_empty(kind) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index 26f718e858da..e87aabf9a056 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -197,7 +197,7 @@ impl<'tcx> Rvalue<'tcx> { let ty = place.ty(local_decls, tcx).ty; match ty.kind { ty::Adt(adt_def, _) => adt_def.repr.discr_type().to_ty(tcx), - ty::Generator(_, substs, _) => substs.discr_ty(tcx), + ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx), _ => { // This can only be `0`, for now, so `u8` will suffice. tcx.types.u8 diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 1fae2a2fe8db..4ee5700f43fe 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2761,8 +2761,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { .collect(), ty::Generator(def_id, ref substs, _) => { - let witness = substs.witness(def_id, self.tcx()); + let witness = substs.as_generator().witness(def_id, self.tcx()); substs + .as_generator() .upvar_tys(def_id, self.tcx()) .chain(iter::once(witness)) .collect() @@ -3324,8 +3325,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { )?); Ok(VtableGeneratorData { - generator_def_id: generator_def_id, - substs: substs.clone(), + generator_def_id, + substs, nested: obligations, }) } @@ -3911,9 +3912,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, obligation: &TraitObligation<'tcx>, closure_def_id: DefId, - substs: ty::GeneratorSubsts<'tcx>, + substs: SubstsRef<'tcx>, ) -> ty::PolyTraitRef<'tcx> { - let gen_sig = substs.poly_sig(closure_def_id, self.tcx()); + let gen_sig = substs.as_generator().poly_sig(closure_def_id, self.tcx()); // (1) Feels icky to skip the binder here, but OTOH we know // that the self-type is an generator type and hence is diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 5aad6c1dc183..48820540ebeb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2510,7 +2510,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_generator(self, id: DefId, - generator_substs: GeneratorSubsts<'tcx>, + generator_substs: SubstsRef<'tcx>, movability: hir::GeneratorMovability) -> Ty<'tcx> { self.mk_ty(Generator(id, generator_substs, movability)) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index b513ef5a9667..4ff5e1a7b8de 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -94,7 +94,7 @@ impl FlagComputation { &ty::Generator(_, ref substs, _) => { self.add_flags(TypeFlags::HAS_TY_CLOSURE); self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); - self.add_substs(&substs.substs); + self.add_substs(substs); } &ty::GeneratorWitness(ref ts) => { diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 34f806b15c0c..241b00a2dc40 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -71,7 +71,7 @@ impl<'tcx> Instance<'tcx> { )) } ty::Generator(def_id, substs, _) => { - let sig = substs.poly_sig(def_id, tcx); + let sig = substs.as_generator().poly_sig(def_id, tcx); let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 6e01e1bf26a5..2e6e2f012de9 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1,5 +1,5 @@ use crate::session::{self, DataTypeKind}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions}; +use crate::ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, subst::SubstsRef}; use syntax::ast::{self, Ident, IntTy, UintTy}; use syntax::attr; @@ -15,7 +15,6 @@ use std::ops::Bound; use crate::hir; use crate::ich::StableHashingContext; use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; -use crate::ty::GeneratorSubsts; use crate::ty::subst::Subst; use rustc_index::bit_set::BitSet; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -671,7 +670,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { tcx.intern_layout(unit) } - ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, &substs)?, + ty::Generator(def_id, substs, _) => self.generator_layout(ty, def_id, substs)?, ty::Closure(def_id, ref substs) => { let tys = substs.as_closure().upvar_tys(def_id, tcx); @@ -1406,7 +1405,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { &self, ty: Ty<'tcx>, def_id: hir::def_id::DefId, - substs: &GeneratorSubsts<'tcx>, + substs: SubstsRef<'tcx>, ) -> Result<&'tcx LayoutDetails, LayoutError<'tcx>> { use SavedLocalEligibility::*; let tcx = self.tcx; @@ -1419,9 +1418,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Build a prefix layout, including "promoting" all ineligible // locals as part of the prefix. We compute the layout of all of // these fields at once to get optimal packing. - let discr_index = substs.prefix_tys(def_id, tcx).count(); + let discr_index = substs.as_generator().prefix_tys(def_id, tcx).count(); // FIXME(eddyb) set the correct vaidity range for the discriminant. - let discr_layout = self.layout_of(substs.discr_ty(tcx))?; + let discr_layout = self.layout_of(substs.as_generator().discr_ty(tcx))?; let discr = match &discr_layout.abi { Abi::Scalar(s) => s.clone(), _ => bug!(), @@ -2153,7 +2152,7 @@ where ty::Generator(def_id, ref substs, _) => { match this.variants { Variants::Single { index } => { - substs.state_tys(def_id, tcx) + substs.as_generator().state_tys(def_id, tcx) .nth(index.as_usize()).unwrap() .nth(i).unwrap() } @@ -2161,7 +2160,7 @@ where if i == discr_index { return discr_layout(discr); } - substs.prefix_tys(def_id, tcx).nth(i).unwrap() + substs.as_generator().prefix_tys(def_id, tcx).nth(i).unwrap() } } } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 3ea767d51159..80e77cdfad0b 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -69,7 +69,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::Generator(def_id, ref substs, _) => { // Same as the closure case - for upvar_ty in substs.upvar_tys(def_id, *self) { + for upvar_ty in substs.as_generator().upvar_tys(def_id, *self) { self.compute_components(upvar_ty, out); } diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index 21c018d9ee6d..3855e9e9b8a5 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -154,7 +154,7 @@ impl DefPathBasedNames<'tcx> { self.push_type_name(sig.output(), output, debug); } } - ty::Generator(def_id, GeneratorSubsts { substs }, _) + ty::Generator(def_id, substs, _) | ty::Closure(def_id, substs) => { self.push_def_path(def_id, output); let generics = self.tcx.generics_of(self.tcx.closure_base_def_id(def_id)); diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index ad4be788dae4..732638929963 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -605,8 +605,8 @@ pub trait PrettyPrinter<'tcx>: } ty::Str => p!(write("str")), ty::Generator(did, substs, movability) => { - let upvar_tys = substs.upvar_tys(did, self.tcx()); - let witness = substs.witness(did, self.tcx()); + let upvar_tys = substs.as_generator().upvar_tys(did, self.tcx()); + let witness = substs.as_generator().witness(did, self.tcx()); if movability == hir::GeneratorMovability::Movable { p!(write("[generator")); } else { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index c1589b31de78..ff20996df56f 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2109,7 +2109,8 @@ impl<'tcx> TyS<'tcx> { pub fn variant_range(&self, tcx: TyCtxt<'tcx>) -> Option> { match self.kind { TyKind::Adt(adt, _) => Some(adt.variant_range()), - TyKind::Generator(def_id, substs, _) => Some(substs.variant_range(def_id, tcx)), + TyKind::Generator(def_id, substs, _) => + Some(substs.assert_generator().variant_range(def_id, tcx)), _ => None, } } @@ -2126,7 +2127,7 @@ impl<'tcx> TyS<'tcx> { match self.kind { TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)), TyKind::Generator(def_id, substs, _) => - Some(substs.discriminant_for_variant(def_id, tcx, variant_index)), + Some(substs.as_generator().discriminant_for_variant(def_id, tcx, variant_index)), _ => None, } } @@ -2149,7 +2150,7 @@ impl<'tcx> TyS<'tcx> { out.extend(substs.regions()) } Closure(_, ref substs ) | - Generator(_, GeneratorSubsts { ref substs }, _) => { + Generator(_, ref substs, _) => { out.extend(substs.regions()) } Projection(ref data) | UnnormalizedProjection(ref data) => { diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 1895ab83674e..f5b1902e3cc8 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -110,12 +110,10 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::Adt(_, substs) | ty::Opaque(_, substs) => { stack.extend(substs.types().rev()); } - ty::Closure(_, ref substs) => { + ty::Closure(_, ref substs) + | ty::Generator(_, ref substs, _) => { stack.extend(substs.types().rev()); } - ty::Generator(_, ref substs, _) => { - stack.extend(substs.substs.types().rev()); - } ty::GeneratorWitness(ts) => { stack.extend(ts.skip_binder().iter().cloned().rev()); } From 774ea808be4bcab4e605635b383ce4c5c9d7742f Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:28:04 +0800 Subject: [PATCH 063/545] replace GeneratorSubsts inside related types --- src/librustc/infer/opaque_types/mod.rs | 2 +- src/librustc/mir/mod.rs | 4 ++-- src/librustc/traits/mod.rs | 2 +- src/librustc/ty/context.rs | 2 +- src/librustc/ty/layout.rs | 4 ++-- src/librustc/ty/print/obsolete.rs | 2 +- src/librustc/ty/sty.rs | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index d45869ed160c..bd19a002fe8b 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -912,7 +912,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { } })); - self.tcx.mk_generator(def_id, ty::GeneratorSubsts { substs }, movability) + self.tcx.mk_generator(def_id, substs, movability) } ty::Param(..) => { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 59b4f2407339..2b5212cb7efa 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -15,7 +15,7 @@ use crate::ty::layout::VariantIdx; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{Subst, SubstsRef}; use crate::ty::{ - self, AdtDef, CanonicalUserTypeAnnotations, GeneratorSubsts, Region, Ty, TyCtxt, + self, AdtDef, CanonicalUserTypeAnnotations, Region, Ty, TyCtxt, UserTypeAnnotationIndex, }; @@ -2189,7 +2189,7 @@ pub enum AggregateKind<'tcx> { Adt(&'tcx AdtDef, VariantIdx, SubstsRef<'tcx>, Option, Option), Closure(DefId, SubstsRef<'tcx>), - Generator(DefId, GeneratorSubsts<'tcx>, hir::GeneratorMovability), + Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), } #[derive(Copy, Clone, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 7f194c2fbbc0..d96330bf0a9b 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -610,7 +610,7 @@ pub struct VtableImplData<'tcx, N> { #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] pub struct VtableGeneratorData<'tcx, N> { pub generator_def_id: DefId, - pub substs: ty::GeneratorSubsts<'tcx>, + pub substs: SubstsRef<'tcx>, /// Nested obligations. This can be non-empty if the generator /// signature contains associated types. pub nested: Vec diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 48820540ebeb..eb380eb12d8e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -29,7 +29,7 @@ use crate::traits; use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals}; use crate::ty::{self, DefIdTree, Ty, TypeAndMut}; use crate::ty::{TyS, TyKind, List}; -use crate::ty::{AdtKind, AdtDef, GeneratorSubsts, Region, Const}; +use crate::ty::{AdtKind, AdtDef, Region, Const}; use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; use crate::ty::RegionKind; use crate::ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid, ConstVid}; diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 2e6e2f012de9..ce7e1822d9ab 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1410,7 +1410,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { use SavedLocalEligibility::*; let tcx = self.tcx; - let subst_field = |ty: Ty<'tcx>| { ty.subst(tcx, substs.substs) }; + let subst_field = |ty: Ty<'tcx>| { ty.subst(tcx, substs) }; let info = tcx.generator_layout(def_id); let (ineligible_locals, assignments) = self.generator_saved_local_eligibility(&info); @@ -1429,7 +1429,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { .map(|local| subst_field(info.field_tys[local])) .map(|ty| tcx.mk_maybe_uninit(ty)) .map(|ty| self.layout_of(ty)); - let prefix_layouts = substs.prefix_tys(def_id, tcx) + let prefix_layouts = substs.as_generator().prefix_tys(def_id, tcx) .map(|ty| self.layout_of(ty)) .chain(iter::once(Ok(discr_layout))) .chain(promoted_layouts) diff --git a/src/librustc/ty/print/obsolete.rs b/src/librustc/ty/print/obsolete.rs index 3855e9e9b8a5..df39d0ccc9ee 100644 --- a/src/librustc/ty/print/obsolete.rs +++ b/src/librustc/ty/print/obsolete.rs @@ -8,7 +8,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::interpret::ConstValue; use rustc::ty::subst::SubstsRef; -use rustc::ty::{self, Const, GeneratorSubsts, Instance, Ty, TyCtxt}; +use rustc::ty::{self, Const, Instance, Ty, TyCtxt}; use rustc::{bug, hir}; use std::fmt::Write; use std::iter; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index ff20996df56f..54b6fbe7c218 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2110,7 +2110,7 @@ impl<'tcx> TyS<'tcx> { match self.kind { TyKind::Adt(adt, _) => Some(adt.variant_range()), TyKind::Generator(def_id, substs, _) => - Some(substs.assert_generator().variant_range(def_id, tcx)), + Some(substs.as_generator().variant_range(def_id, tcx)), _ => None, } } From ef9fe102800406ff5132344b43fcf6472cab7d2d Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:30:26 +0800 Subject: [PATCH 064/545] remove GeneratorSubsts visitors --- src/librustc/mir/visit.rs | 14 ++------------ src/librustc/traits/project.rs | 2 +- src/librustc/ty/instance.rs | 2 +- 3 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index ed8086b8fafe..edc7922f46ee 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -1,5 +1,5 @@ use crate::ty::subst::SubstsRef; -use crate::ty::{CanonicalUserTypeAnnotation, GeneratorSubsts, Ty}; +use crate::ty::{CanonicalUserTypeAnnotation, Ty}; use crate::mir::*; use syntax_pos::Span; @@ -230,12 +230,6 @@ macro_rules! make_mir_visitor { self.super_substs(substs); } - fn visit_generator_substs(&mut self, - substs: & $($mutability)? GeneratorSubsts<'tcx>, - _: Location) { - self.super_generator_substs(substs); - } - fn visit_local_decl(&mut self, local: Local, local_decl: & $($mutability)? LocalDecl<'tcx>) { @@ -628,7 +622,7 @@ macro_rules! make_mir_visitor { generator_substs, _movability, ) => { - self.visit_generator_substs(generator_substs, location); + self.visit_substs(generator_substs, location); } } @@ -846,10 +840,6 @@ macro_rules! make_mir_visitor { fn super_substs(&mut self, _substs: & $($mutability)? SubstsRef<'tcx>) { } - fn super_generator_substs(&mut self, - _substs: & $($mutability)? GeneratorSubsts<'tcx>) { - } - // Convenience methods fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Location) { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index a7bb29c699e0..5b4ec885d778 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1259,7 +1259,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( obligation: &ProjectionTyObligation<'tcx>, vtable: VtableGeneratorData<'tcx, PredicateObligation<'tcx>>, ) -> Progress<'tcx> { - let gen_sig = vtable.substs.poly_sig(vtable.generator_def_id, selcx.tcx()); + let gen_sig = vtable.substs.as_generator().poly_sig(vtable.generator_def_id, selcx.tcx()); let Normalized { value: gen_sig, obligations diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 241b00a2dc40..93a8341e7462 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -395,7 +395,7 @@ fn resolve_associated_item<'tcx>( traits::VtableGenerator(generator_data) => { Some(Instance { def: ty::InstanceDef::Item(generator_data.generator_def_id), - substs: generator_data.substs.substs + substs: generator_data.substs }) } traits::VtableClosure(closure_data) => { From afc0bb9794bfcbc9864a1d195ac34b892727f9e4 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 3 Oct 2019 21:51:30 +0800 Subject: [PATCH 065/545] clean up GeneratorSubsts --- src/librustc/ty/sty.rs | 8 ++++---- src/librustc/ty/subst.rs | 2 +- .../debuginfo/metadata.rs | 18 ++++++++++-------- src/librustc_codegen_llvm/type_of.rs | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 2 +- .../symbol_names/legacy.rs | 2 +- src/librustc_codegen_utils/symbol_names/v0.rs | 2 +- .../borrow_check/nll/constraint_generation.rs | 9 +-------- src/librustc_mir/borrow_check/nll/renumber.rs | 16 +--------------- .../borrow_check/nll/type_check/mod.rs | 14 +++++++------- .../borrow_check/nll/universal_regions.rs | 14 +++++++------- src/librustc_mir/build/mod.rs | 2 +- .../interpret/intrinsics/type_name.rs | 3 +-- src/librustc_mir/interpret/operand.rs | 12 ++++++++---- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/transform/generator.rs | 1 + src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_traits/dropck_outlives.rs | 2 +- src/librustc_traits/generic_types.rs | 8 +++++--- src/librustc_typeck/check/closure.rs | 8 ++++---- 20 files changed, 58 insertions(+), 71 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 54b6fbe7c218..e27236b47e07 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -512,7 +512,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// variant indices. #[inline] pub fn discriminants( - &'tcx self, + self, def_id: DefId, tcx: TyCtxt<'tcx>, ) -> impl Iterator)> + Captures<'tcx> { @@ -524,7 +524,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { /// Calls `f` with a reference to the name of the enumerator for the given /// variant `v`. #[inline] - pub fn variant_name(&self, v: VariantIdx) -> Cow<'static, str> { + pub fn variant_name(self, v: VariantIdx) -> Cow<'static, str> { match v.as_usize() { Self::UNRESUMED => Cow::from(Self::UNRESUMED_NAME), Self::RETURNED => Cow::from(Self::RETURNED_NAME), @@ -570,7 +570,7 @@ impl<'tcx> GeneratorSubsts<'tcx> { #[derive(Debug, Copy, Clone)] pub enum UpvarSubsts<'tcx> { Closure(SubstsRef<'tcx>), - Generator(GeneratorSubsts<'tcx>), + Generator(SubstsRef<'tcx>), } impl<'tcx> UpvarSubsts<'tcx> { @@ -582,7 +582,7 @@ impl<'tcx> UpvarSubsts<'tcx> { ) -> impl Iterator> + 'tcx { let upvar_kinds = match self { UpvarSubsts::Closure(substs) => substs.as_closure().split(def_id, tcx).upvar_kinds, - UpvarSubsts::Generator(substs) => substs.split(def_id, tcx).upvar_kinds, + UpvarSubsts::Generator(substs) => substs.as_generator().split(def_id, tcx).upvar_kinds, }; upvar_kinds.iter().map(|t| { if let GenericArgKind::Type(ty) = t.unpack() { diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index de98c098ea53..7c5daaf14d78 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -198,7 +198,7 @@ impl<'a, 'tcx> InternalSubsts<'tcx> { /// Closure substitutions have a particular structure controlled by the /// compiler that encodes information like the signature and generator kind; /// see `ty::GeneratorSubsts` struct for more comments. - pub fn as_generator(&'a self) -> GeneratorSubsts<'a> { + pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> { GeneratorSubsts { substs: self } } diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index e69f4b6aca19..14e4c4adfaa9 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -30,7 +30,7 @@ use rustc::ty::Instance; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; use rustc::ty::layout::{self, Align, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx}; -use rustc::ty::subst::GenericArgKind; +use rustc::ty::subst::{GenericArgKind, SubstsRef}; use rustc::session::config::{self, DebugInfo}; use rustc::util::nodemap::FxHashMap; use rustc_fs_util::path_to_c_string; @@ -692,9 +692,10 @@ pub fn type_metadata( Some(containing_scope)).finalize(cx) } ty::Generator(def_id, substs, _) => { - let upvar_tys : Vec<_> = substs.prefix_tys(def_id, cx.tcx).map(|t| { - cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t) - }).collect(); + let upvar_tys : Vec<_> = substs + .as_generator().prefix_tys(def_id, cx.tcx).map(|t| { + cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t) + }).collect(); prepare_enum_metadata(cx, t, def_id, @@ -1338,7 +1339,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { ty::Adt(adt, _) => VariantInfo::Adt(&adt.variants[index]), ty::Generator(def_id, substs, _) => { let generator_layout = cx.tcx.generator_layout(*def_id); - VariantInfo::Generator(*substs, generator_layout, index) + VariantInfo::Generator(substs, generator_layout, index) } _ => bug!(), } @@ -1611,7 +1612,7 @@ enum EnumDiscriminantInfo<'ll> { #[derive(Copy, Clone)] enum VariantInfo<'tcx> { Adt(&'tcx ty::VariantDef), - Generator(ty::GeneratorSubsts<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx), + Generator(SubstsRef<'tcx>, &'tcx GeneratorLayout<'tcx>, VariantIdx), } impl<'tcx> VariantInfo<'tcx> { @@ -1619,7 +1620,7 @@ impl<'tcx> VariantInfo<'tcx> { match self { VariantInfo::Adt(variant) => f(&variant.ident.as_str()), VariantInfo::Generator(substs, _, variant_index) => - f(&substs.variant_name(*variant_index)), + f(&substs.as_generator().variant_name(*variant_index)), } } @@ -1763,9 +1764,10 @@ fn prepare_enum_metadata( }) .collect(), ty::Generator(_, substs, _) => substs + .as_generator() .variant_range(enum_def_id, cx.tcx) .map(|variant_index| { - let name = SmallCStr::new(&substs.variant_name(variant_index)); + let name = SmallCStr::new(&substs.as_generator().variant_name(variant_index)); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), diff --git a/src/librustc_codegen_llvm/type_of.rs b/src/librustc_codegen_llvm/type_of.rs index 81a99bc5019b..d921bbc96ade 100644 --- a/src/librustc_codegen_llvm/type_of.rs +++ b/src/librustc_codegen_llvm/type_of.rs @@ -65,7 +65,7 @@ fn uncached_llvm_type<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, if let (&ty::Generator(_, substs, _), &layout::Variants::Single { index }) = (&layout.ty.kind, &layout.variants) { - write!(&mut name, "::{}", substs.variant_name(index)).unwrap(); + write!(&mut name, "::{}", substs.as_generator().variant_name(index)).unwrap(); } Some(name) } diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 5787447d6230..9d2f8b42c704 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -636,7 +636,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ty::Generator(def_id, substs, _) => (def_id, substs), _ => bug!("generator layout without generator substs"), }; - let state_tys = gen_substs.state_tys(def_id, tcx); + let state_tys = gen_substs.as_generator().state_tys(def_id, tcx); generator_layout.variant_fields.iter() .zip(state_tys) diff --git a/src/librustc_codegen_utils/symbol_names/legacy.rs b/src/librustc_codegen_utils/symbol_names/legacy.rs index 5bcb3b4ceb3b..cf575c54293c 100644 --- a/src/librustc_codegen_utils/symbol_names/legacy.rs +++ b/src/librustc_codegen_utils/symbol_names/legacy.rs @@ -225,7 +225,7 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, substs) | - ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + ty::Generator(def_id, substs, _) => { self.print_def_path(def_id, substs) } _ => self.pretty_print_type(ty), diff --git a/src/librustc_codegen_utils/symbol_names/v0.rs b/src/librustc_codegen_utils/symbol_names/v0.rs index 2ad699d7c6f0..55b148fceb21 100644 --- a/src/librustc_codegen_utils/symbol_names/v0.rs +++ b/src/librustc_codegen_utils/symbol_names/v0.rs @@ -415,7 +415,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, substs) | - ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + ty::Generator(def_id, substs, _) => { self = self.print_def_path(def_id, substs)?; } ty::Foreign(def_id) => { diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 0e22ead62d1c..b105664399a5 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -12,7 +12,7 @@ use rustc::mir::{ SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection, }; use rustc::ty::fold::TypeFoldable; -use rustc::ty::{self, GeneratorSubsts, RegionVid, Ty}; +use rustc::ty::{self, RegionVid, Ty}; use rustc::ty::subst::SubstsRef; pub(super) fn generate_constraints<'cx, 'tcx>( @@ -91,13 +91,6 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> { self.super_ty(ty); } - /// We sometimes have `generator_substs` within an rvalue, or within a - /// call. Make them live at the location where they appear. - fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) { - self.add_regular_live_constraint(*substs, location); - self.super_generator_substs(substs); - } - fn visit_statement( &mut self, statement: &Statement<'tcx>, diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 014335711a51..88ad1fb12950 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,5 +1,5 @@ use rustc::ty::subst::SubstsRef; -use rustc::ty::{self, GeneratorSubsts, Ty, TypeFoldable}; +use rustc::ty::{self, Ty, TypeFoldable}; use rustc::mir::{Location, Body, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; @@ -82,18 +82,4 @@ impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _location: Location) { *constant = self.renumber_regions(&*constant); } - - fn visit_generator_substs(&mut self, - substs: &mut GeneratorSubsts<'tcx>, - location: Location) { - debug!( - "visit_generator_substs(substs={:?}, location={:?})", - substs, - location, - ); - - *substs = self.renumber_regions(substs); - - debug!("visit_generator_substs: substs={:?}", substs); - } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index f55889794c24..1563a27250eb 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -759,13 +759,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { PlaceTy { ty, variant_index: Some(variant_index) } => match ty.kind { ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs), ty::Generator(def_id, substs, _) => { - let mut variants = substs.state_tys(def_id, tcx); + let mut variants = substs.as_generator().state_tys(def_id, tcx); let mut variant = match variants.nth(variant_index.into()) { Some(v) => v, None => { bug!("variant_index of generator out of range: {:?}/{:?}", variant_index, - substs.state_tys(def_id, tcx).count()) + substs.as_generator().state_tys(def_id, tcx).count()) } }; return match variant.nth(field.index()) { @@ -791,10 +791,10 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ty::Generator(def_id, substs, _) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. - return match substs.prefix_tys(def_id, tcx).nth(field.index()) { + return match substs.as_generator().prefix_tys(def_id, tcx).nth(field.index()) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.prefix_tys(def_id, tcx).count(), + field_count: substs.as_generator().prefix_tys(def_id, tcx).count(), }), } } @@ -1963,10 +1963,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // It doesn't make sense to look at a field beyond the prefix; // these require a variant index, and are not initialized in // aggregate rvalues. - match substs.prefix_tys(def_id, tcx).nth(field_index) { + match substs.as_generator().prefix_tys(def_id, tcx).nth(field_index) { Some(ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.prefix_tys(def_id, tcx).count(), + field_count: substs.as_generator().prefix_tys(def_id, tcx).count(), }), } } @@ -2541,7 +2541,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // these extra requirements are basically like where // clauses on the struct. AggregateKind::Closure(def_id, substs) - | AggregateKind::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + | AggregateKind::Generator(def_id, substs, _) => { self.prove_closure_bounds(tcx, *def_id, substs, location) } diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index e3efacff66a2..5f6951856434 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -19,7 +19,7 @@ use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc::middle::lang_items; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{InternalSubsts, SubstsRef, Subst}; -use rustc::ty::{self, GeneratorSubsts, RegionVid, Ty, TyCtxt}; +use rustc::ty::{self, RegionVid, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_index::vec::{Idx, IndexVec}; use rustc_errors::DiagnosticBuilder; @@ -90,7 +90,7 @@ pub enum DefiningTy<'tcx> { /// The MIR is a generator. The signature is that generators take /// no parameters and return the result of /// `ClosureSubsts::generator_return_ty`. - Generator(DefId, ty::GeneratorSubsts<'tcx>, hir::GeneratorMovability), + Generator(DefId, SubstsRef<'tcx>, hir::GeneratorMovability), /// The MIR is a fn item with the given `DefId` and substs. The signature /// of the function can be bound then with the `fn_sig` query. @@ -113,7 +113,7 @@ impl<'tcx> DefiningTy<'tcx> { substs.as_closure().upvar_tys(def_id, tcx) ), DefiningTy::Generator(def_id, substs, _) => { - Either::Right(Either::Left(substs.upvar_tys(def_id, tcx))) + Either::Right(Either::Left(substs.as_generator().upvar_tys(def_id, tcx))) } DefiningTy::FnDef(..) | DefiningTy::Const(..) => { Either::Right(Either::Right(iter::empty())) @@ -334,7 +334,7 @@ impl<'tcx> UniversalRegions<'tcx> { err.note(&format!( "defining type: {:?} with generator substs {:#?}", def_id, - &substs.substs[..] + &substs[..] )); // FIXME: As above, we'd like to print out the region @@ -470,7 +470,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let yield_ty = match defining_ty { DefiningTy::Generator(def_id, substs, _) => { - Some(substs.yield_ty(def_id, self.infcx.tcx)) + Some(substs.as_generator().yield_ty(def_id, self.infcx.tcx)) } _ => None, }; @@ -549,7 +549,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let identity_substs = InternalSubsts::identity_for_item(tcx, closure_base_def_id); let fr_substs = match defining_ty { DefiningTy::Closure(_, ref substs) - | DefiningTy::Generator(_, GeneratorSubsts { ref substs }, _) => { + | DefiningTy::Generator(_, ref substs, _) => { // In the case of closures, we rely on the fact that // the first N elements in the ClosureSubsts are // inherited from the `closure_base_def_id`. @@ -612,7 +612,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { DefiningTy::Generator(def_id, substs, movability) => { assert_eq!(self.mir_def_id, def_id); - let output = substs.return_ty(def_id, tcx); + let output = substs.as_generator().return_ty(def_id, tcx); let generator_ty = tcx.mk_generator(def_id, substs, movability); let inputs_and_output = self.infcx.tcx.intern_type_list(&[generator_ty, output]); ty::Binder::dummy(inputs_and_output) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 9c30d9509908..6b6eac5add2f 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -146,7 +146,7 @@ pub fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> Body<'_> { let (yield_ty, return_ty) = if body.generator_kind.is_some() { let gen_sig = match ty.kind { ty::Generator(gen_def_id, gen_substs, ..) => - gen_substs.sig(gen_def_id, tcx), + gen_substs.as_generator().sig(gen_def_id, tcx), _ => span_bug!(tcx.hir().span(id), "generator w/o generator type: {:?}", ty), diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index dc3b7694c35c..f9200f8c1c04 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -68,8 +68,7 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, substs) - | ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) - => self.print_def_path(def_id, substs), + | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), ty::GeneratorWitness(_) => { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 861e5ebef877..4bdd71f9602a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -664,14 +664,18 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { bits_discr }; // Make sure we catch invalid discriminants - let index = match &rval.layout.ty.kind { + let index = match rval.layout.ty.kind { ty::Adt(adt, _) => adt .discriminants(self.tcx.tcx) .find(|(_, var)| var.val == real_discr), - ty::Generator(def_id, substs, _) => substs - .discriminants(*def_id, self.tcx.tcx) - .find(|(_, var)| var.val == real_discr), + ty::Generator(def_id, substs, _) => { + let substs = substs.as_generator(); + substs + .discriminants(def_id, self.tcx.tcx) + .find(|(_, var)| var.val == real_discr) + } _ => bug!("tagged layout for non-adt non-generator"), + }.ok_or_else( || err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())) )?; diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index d089eafbb079..78008e2fcd36 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -169,7 +169,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) // Check if this is a generator, if so, return the drop glue for it if let Some(&ty::TyS { kind: ty::Generator(gen_def_id, substs, _), .. }) = ty { let body = &**tcx.optimized_mir(gen_def_id).generator_drop.as_ref().unwrap(); - return body.subst(tcx, substs.substs); + return body.subst(tcx, substs); } let substs = if let Some(ty) = ty { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index bfc5eb5a94ef..a648fadde43b 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1126,6 +1126,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // Get the interior types and substs which typeck computed let (upvars, interior, discr_ty, movable) = match gen_ty.kind { ty::Generator(_, substs, movability) => { + let substs = substs.as_generator(); (substs.upvar_tys(def_id, tcx).collect(), substs.witness(def_id, tcx), substs.discr_ty(tcx), diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index bdbf040276d2..f7ba6f1ec699 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -798,7 +798,7 @@ where // It effetively only contains upvars until the generator transformation runs. // See librustc_body/transform/generator.rs for more details. ty::Generator(def_id, substs, _) => { - let tys : Vec<_> = substs.upvar_tys(def_id, self.tcx()).collect(); + let tys : Vec<_> = substs.as_generator().upvar_tys(def_id, self.tcx()).collect(); self.open_drop_for_tuple(&tys) } ty::Tuple(..) => { diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 7db1a7413c7b..88e62db9a10d 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -223,7 +223,7 @@ fn dtorck_constraint_for_ty<'tcx>( // *do* incorporate the upvars here. let constraint = DtorckConstraint { - outlives: substs.upvar_tys(def_id, tcx).map(|t| t.into()).collect(), + outlives: substs.as_generator().upvar_tys(def_id, tcx).map(|t| t.into()).collect(), dtorck_types: vec![], overflows: vec![], }; diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs index 91ca6415bdcb..cc5348623fab 100644 --- a/src/librustc_traits/generic_types.rs +++ b/src/librustc_traits/generic_types.rs @@ -73,7 +73,9 @@ crate fn closure(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { } crate fn generator(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_generator(def_id, ty::GeneratorSubsts { - substs: InternalSubsts::bound_vars_for_item(tcx, def_id), - }, hir::GeneratorMovability::Movable) + tcx.mk_generator( + def_id, + InternalSubsts::bound_vars_for_item(tcx, def_id), + hir::GeneratorMovability::Movable + ) } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 03f0860c6605..8b97bf643e9b 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -113,21 +113,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }); if let Some(GeneratorTypes { yield_ty, interior, movability }) = generator_types { - let substs = ty::GeneratorSubsts { substs }; + let generator_substs = substs.as_generator(); self.demand_eqtype( expr.span, yield_ty, - substs.yield_ty(expr_def_id, self.tcx), + generator_substs.yield_ty(expr_def_id, self.tcx), ); self.demand_eqtype( expr.span, liberated_sig.output(), - substs.return_ty(expr_def_id, self.tcx), + generator_substs.return_ty(expr_def_id, self.tcx), ); self.demand_eqtype( expr.span, interior, - substs.witness(expr_def_id, self.tcx), + generator_substs.witness(expr_def_id, self.tcx), ); return self.tcx.mk_generator(expr_def_id, substs, movability); } From c97f5f0045f8ba959dc3b72cd705043ac7b4d9eb Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Fri, 4 Oct 2019 22:55:10 +0900 Subject: [PATCH 066/545] Remove dead module --- src/librustc_mir/monomorphize/item.rs | 204 -------------------------- 1 file changed, 204 deletions(-) delete mode 100644 src/librustc_mir/monomorphize/item.rs diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs deleted file mode 100644 index e63426281bf2..000000000000 --- a/src/librustc_mir/monomorphize/item.rs +++ /dev/null @@ -1,204 +0,0 @@ -use rustc::hir::def_id::LOCAL_CRATE; -use rustc::mir::mono::MonoItem; -use rustc::session::config::OptLevel; -use rustc::ty::{self, TyCtxt, Instance}; -use rustc::ty::subst::InternalSubsts; -use rustc::ty::print::obsolete::DefPathBasedNames; -use syntax::attr::InlineAttr; -use std::fmt; -use rustc::mir::mono::Linkage; -use syntax_pos::symbol::InternedString; -use syntax::source_map::Span; - -/// Describes how a monomorphization will be instantiated in object files. -#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] -pub enum InstantiationMode { - /// There will be exactly one instance of the given MonoItem. It will have - /// external linkage so that it can be linked to from other codegen units. - GloballyShared { - /// In some compilation scenarios we may decide to take functions that - /// are typically `LocalCopy` and instead move them to `GloballyShared` - /// to avoid codegenning them a bunch of times. In this situation, - /// however, our local copy may conflict with other crates also - /// inlining the same function. - /// - /// This flag indicates that this situation is occurring, and informs - /// symbol name calculation that some extra mangling is needed to - /// avoid conflicts. Note that this may eventually go away entirely if - /// ThinLTO enables us to *always* have a globally shared instance of a - /// function within one crate's compilation. - may_conflict: bool, - }, - - /// Each codegen unit containing a reference to the given MonoItem will - /// have its own private copy of the function (with internal linkage). - LocalCopy, -} - -pub trait MonoItemExt<'tcx>: fmt::Debug { - fn as_mono_item(&self) -> &MonoItem<'tcx>; - - fn is_generic_fn(&self) -> bool { - match *self.as_mono_item() { - MonoItem::Fn(ref instance) => { - instance.substs.non_erasable_generics().next().is_some() - } - MonoItem::Static(..) | - MonoItem::GlobalAsm(..) => false, - } - } - - fn symbol_name(&self, tcx: TyCtxt<'tcx>) -> ty::SymbolName { - match *self.as_mono_item() { - MonoItem::Fn(instance) => tcx.symbol_name(instance), - MonoItem::Static(def_id) => { - tcx.symbol_name(Instance::mono(tcx, def_id)) - } - MonoItem::GlobalAsm(hir_id) => { - let def_id = tcx.hir().local_def_id(hir_id); - ty::SymbolName { - name: InternedString::intern(&format!("global_asm_{:?}", def_id)) - } - } - } - } - fn instantiation_mode(&self, tcx: TyCtxt<'tcx>) -> InstantiationMode { - let inline_in_all_cgus = - tcx.sess.opts.debugging_opts.inline_in_all_cgus.unwrap_or_else(|| { - tcx.sess.opts.optimize != OptLevel::No - }) && !tcx.sess.opts.cg.link_dead_code; - - match *self.as_mono_item() { - MonoItem::Fn(ref instance) => { - let entry_def_id = tcx.entry_fn(LOCAL_CRATE).map(|(id, _)| id); - // If this function isn't inlined or otherwise has explicit - // linkage, then we'll be creating a globally shared version. - if self.explicit_linkage(tcx).is_some() || - !instance.def.requires_local(tcx) || - Some(instance.def_id()) == entry_def_id - { - return InstantiationMode::GloballyShared { may_conflict: false } - } - - // At this point we don't have explicit linkage and we're an - // inlined function. If we're inlining into all CGUs then we'll - // be creating a local copy per CGU - if inline_in_all_cgus { - return InstantiationMode::LocalCopy - } - - // Finally, if this is `#[inline(always)]` we're sure to respect - // that with an inline copy per CGU, but otherwise we'll be - // creating one copy of this `#[inline]` function which may - // conflict with upstream crates as it could be an exported - // symbol. - match tcx.codegen_fn_attrs(instance.def_id()).inline { - InlineAttr::Always => InstantiationMode::LocalCopy, - _ => { - InstantiationMode::GloballyShared { may_conflict: true } - } - } - } - MonoItem::Static(..) | - MonoItem::GlobalAsm(..) => { - InstantiationMode::GloballyShared { may_conflict: false } - } - } - } - - fn explicit_linkage(&self, tcx: TyCtxt<'tcx>) -> Option { - let def_id = match *self.as_mono_item() { - MonoItem::Fn(ref instance) => instance.def_id(), - MonoItem::Static(def_id) => def_id, - MonoItem::GlobalAsm(..) => return None, - }; - - let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id); - codegen_fn_attrs.linkage - } - - /// Returns `true` if this instance is instantiable - whether it has no unsatisfied - /// predicates. - /// - /// In order to codegen an item, all of its predicates must hold, because - /// otherwise the item does not make sense. Type-checking ensures that - /// the predicates of every item that is *used by* a valid item *do* - /// hold, so we can rely on that. - /// - /// However, we codegen collector roots (reachable items) and functions - /// in vtables when they are seen, even if they are not used, and so they - /// might not be instantiable. For example, a programmer can define this - /// public function: - /// - /// pub fn foo<'a>(s: &'a mut ()) where &'a mut (): Clone { - /// <&mut () as Clone>::clone(&s); - /// } - /// - /// That function can't be codegened, because the method `<&mut () as Clone>::clone` - /// does not exist. Luckily for us, that function can't ever be used, - /// because that would require for `&'a mut (): Clone` to hold, so we - /// can just not emit any code, or even a linker reference for it. - /// - /// Similarly, if a vtable method has such a signature, and therefore can't - /// be used, we can just not emit it and have a placeholder (a null pointer, - /// which will never be accessed) in its place. - fn is_instantiable(&self, tcx: TyCtxt<'tcx>) -> bool { - debug!("is_instantiable({:?})", self); - let (def_id, substs) = match *self.as_mono_item() { - MonoItem::Fn(ref instance) => (instance.def_id(), instance.substs), - MonoItem::Static(def_id) => (def_id, InternalSubsts::empty()), - // global asm never has predicates - MonoItem::GlobalAsm(..) => return true - }; - - tcx.substitute_normalize_and_test_predicates((def_id, &substs)) - } - - fn to_string(&self, tcx: TyCtxt<'tcx>, debug: bool) -> String { - return match *self.as_mono_item() { - MonoItem::Fn(instance) => { - to_string_internal(tcx, "fn ", instance, debug) - }, - MonoItem::Static(def_id) => { - let instance = Instance::new(def_id, tcx.intern_substs(&[])); - to_string_internal(tcx, "static ", instance, debug) - }, - MonoItem::GlobalAsm(..) => { - "global_asm".to_string() - } - }; - - fn to_string_internal<'a, 'tcx>( - tcx: TyCtxt<'tcx>, - prefix: &str, - instance: Instance<'tcx>, - debug: bool, - ) -> String { - let mut result = String::with_capacity(32); - result.push_str(prefix); - let printer = DefPathBasedNames::new(tcx, false, false); - printer.push_instance_as_string(instance, &mut result, debug); - result - } - } - - fn local_span(&self, tcx: TyCtxt<'tcx>) -> Option { - match *self.as_mono_item() { - MonoItem::Fn(Instance { def, .. }) => { - tcx.hir().as_local_hir_id(def.def_id()) - } - MonoItem::Static(def_id) => { - tcx.hir().as_local_hir_id(def_id) - } - MonoItem::GlobalAsm(hir_id) => { - Some(hir_id) - } - }.map(|hir_id| tcx.hir().span(hir_id)) - } -} - -impl MonoItemExt<'tcx> for MonoItem<'tcx> { - fn as_mono_item(&self) -> &MonoItem<'tcx> { - self - } -} From 6c9f218f3e1f2bb9a6bc0cdf5a0aa16c220f1ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Fri, 4 Oct 2019 00:00:00 +0000 Subject: [PATCH 067/545] Disable stack probe when thread sanitizer is enabled When thread sanitizer instrumentation is enabled during compilation of stack probe function, the function will be miscompiled and trigger segmentation fault at runtime. Disable stack probes when tsan is enabled. --- src/librustc_codegen_llvm/attributes.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 33b50401b22f..a0bef5b78156 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -96,10 +96,12 @@ pub fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) { } // Currently stack probes seem somewhat incompatible with the address - // sanitizer. With asan we're already protected from stack overflow anyway - // so we don't really need stack probes regardless. - if let Some(Sanitizer::Address) = cx.sess().opts.debugging_opts.sanitizer { - return + // sanitizer and thread sanitizer. With asan we're already protected from + // stack overflow anyway so we don't really need stack probes regardless. + match cx.sess().opts.debugging_opts.sanitizer { + Some(Sanitizer::Address) | + Some(Sanitizer::Thread) => return, + _ => {}, } // probestack doesn't play nice either with `-C profile-generate`. From e9009c86d2ed877e21011478f1083e3950507428 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 3 Oct 2019 13:43:07 -0400 Subject: [PATCH 068/545] [const-prop] Fix ICE when trying to eval polymorphic promoted MIR --- src/librustc_mir/interpret/place.rs | 7 +++++++ src/test/ui/consts/const-eval/issue-50814.rs | 1 - .../ui/consts/const-eval/issue-50814.stderr | 12 ++--------- src/test/ui/consts/const-eval/issue-64908.rs | 20 +++++++++++++++++++ 4 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/consts/const-eval/issue-64908.rs diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 1166ca9bf244..3ba989529f18 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -594,6 +594,13 @@ where StaticKind::Promoted(promoted, promoted_substs) => { let substs = self.subst_from_frame_and_normalize_erasing_regions(promoted_substs); let instance = ty::Instance::new(place_static.def_id, substs); + + // Even after getting `substs` from the frame, this instance may still be + // polymorphic because `ConstProp` will try to promote polymorphic MIR. + if instance.needs_subst() { + throw_inval!(TooGeneric); + } + self.const_eval_raw(GlobalId { instance, promoted: Some(promoted), diff --git a/src/test/ui/consts/const-eval/issue-50814.rs b/src/test/ui/consts/const-eval/issue-50814.rs index 274967ef60de..b85cecda16e9 100644 --- a/src/test/ui/consts/const-eval/issue-50814.rs +++ b/src/test/ui/consts/const-eval/issue-50814.rs @@ -11,7 +11,6 @@ struct Sum(A,B); impl Unsigned for Sum { const MAX: u8 = A::MAX + B::MAX; //~ ERROR any use of this value will cause an error - //~| ERROR any use of this value will cause an error } fn foo(_: T) -> &'static u8 { diff --git a/src/test/ui/consts/const-eval/issue-50814.stderr b/src/test/ui/consts/const-eval/issue-50814.stderr index de3459c72dd2..707dfee7cd5b 100644 --- a/src/test/ui/consts/const-eval/issue-50814.stderr +++ b/src/test/ui/consts/const-eval/issue-50814.stderr @@ -9,21 +9,13 @@ LL | const MAX: u8 = A::MAX + B::MAX; = note: `#[deny(const_err)]` on by default error[E0080]: evaluation of constant expression failed - --> $DIR/issue-50814.rs:18:5 + --> $DIR/issue-50814.rs:17:5 | LL | &Sum::::MAX | ^----------------- | | | referenced constant has errors -error: any use of this value will cause an error - --> $DIR/issue-50814.rs:13:21 - | -LL | const MAX: u8 = A::MAX + B::MAX; - | ----------------^^^^^^^^^^^^^^^- - | | - | attempt to add with overflow - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-eval/issue-64908.rs b/src/test/ui/consts/const-eval/issue-64908.rs new file mode 100644 index 000000000000..d2e095072844 --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-64908.rs @@ -0,0 +1,20 @@ +// run-pass + +// This test verifies that the `ConstProp` pass doesn't cause an ICE when evaluating polymorphic +// promoted MIR. + +pub trait ArrowPrimitiveType { + type Native; +} + +pub fn new() { + assert_eq!(0, std::mem::size_of::()); +} + +impl ArrowPrimitiveType for () { + type Native = (); +} + +fn main() { + new::<()>(); +} From 08ec3fef571d3dcfbec2f8b7de1cee78ee05554d Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 4 Oct 2019 16:43:32 +0200 Subject: [PATCH 069/545] dont run these tests on targets that default to panic=abort. --- .../issue-64655-allow-unwind-when-calling-panic-directly.rs | 1 + src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs index 63e373e5b59b..c941d36479e5 100644 --- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-wasm32-bare compiled with panic=abort by default // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine // should still run destructors as it unwinds the stack. However, diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs index 4d521e470396..a6666d66ce57 100644 --- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-wasm32-bare compiled with panic=abort by default // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine // should still run destructors as it unwinds the stack. However, From 91a096a9b8c05011c1a76e7ceb578000ce1e91f6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:31:28 -0400 Subject: [PATCH 070/545] move middle::liveness to rustc_passes --- src/librustc/lib.rs | 1 - src/librustc_interface/passes.rs | 1 - src/librustc_passes/lib.rs | 2 ++ .../middle => librustc_passes}/liveness.rs | 26 +++++++++---------- 4 files changed, 15 insertions(+), 15 deletions(-) rename src/{librustc/middle => librustc_passes}/liveness.rs (99%) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index bd9899b644b5..b522de7d43d3 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -111,7 +111,6 @@ pub mod middle { pub mod intrinsicck; pub mod lib_features; pub mod lang_items; - pub mod liveness; pub mod mem_categorization; pub mod privacy; pub mod reachable; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index bf5e86017fc7..ef9da5c2bde8 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -781,7 +781,6 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { traits::provide(providers); stability::provide(providers); middle::intrinsicck::provide(providers); - middle::liveness::provide(providers); reachable::provide(providers); rustc_passes::provide(providers); rustc_traits::provide(providers); diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 6c7958fb365d..7aa353cec082 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -22,7 +22,9 @@ pub mod ast_validation; pub mod hir_stats; pub mod layout_test; pub mod loops; +mod liveness; pub fn provide(providers: &mut Providers<'_>) { loops::provide(providers); + liveness::provide(providers); } diff --git a/src/librustc/middle/liveness.rs b/src/librustc_passes/liveness.rs similarity index 99% rename from src/librustc/middle/liveness.rs rename to src/librustc_passes/liveness.rs index a654a26eb0b7..fb06808619f6 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -96,17 +96,17 @@ use self::LiveNodeKind::*; use self::VarKind::*; -use crate::hir; -use crate::hir::{Expr, HirId}; -use crate::hir::def::*; -use crate::hir::def_id::DefId; -use crate::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; -use crate::hir::Node; -use crate::hir::ptr::P; -use crate::ty::{self, TyCtxt}; -use crate::ty::query::Providers; -use crate::lint; -use crate::util::nodemap::{HirIdMap, HirIdSet}; +use rustc::hir; +use rustc::hir::{Expr, HirId}; +use rustc::hir::def::*; +use rustc::hir::def_id::DefId; +use rustc::hir::intravisit::{self, Visitor, FnKind, NestedVisitorMap}; +use rustc::hir::Node; +use rustc::hir::ptr::P; +use rustc::ty::{self, TyCtxt}; +use rustc::ty::query::Providers; +use rustc::lint; +use rustc::util::nodemap::{HirIdMap, HirIdSet}; use errors::Applicability; use rustc_data_structures::fx::FxIndexMap; @@ -373,7 +373,7 @@ fn visit_fn<'tcx>( for param in &body.params { let is_shorthand = match param.pat.kind { - crate::hir::PatKind::Struct(..) => true, + rustc::hir::PatKind::Struct(..) => true, _ => false, }; param.pat.each_binding(|_bm, hir_id, _x, ident| { @@ -411,7 +411,7 @@ fn add_from_pat(ir: &mut IrMaps<'_>, pat: &P) { let mut pats = VecDeque::new(); pats.push_back(pat); while let Some(pat) = pats.pop_front() { - use crate::hir::PatKind::*; + use rustc::hir::PatKind::*; match &pat.kind { Binding(.., inner_pat) => { pats.extend(inner_pat.iter()); From bb707824d0f8b55a3f8552dd0326d0ae11fefcf6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:33:11 -0400 Subject: [PATCH 071/545] middle::dead -> rustc_passes --- src/librustc/lib.rs | 1 - src/librustc_interface/passes.rs | 2 +- .../middle => librustc_passes}/dead.rs | 22 +++++++++---------- src/librustc_passes/lib.rs | 1 + 4 files changed, 13 insertions(+), 13 deletions(-) rename src/{librustc/middle => librustc_passes}/dead.rs (98%) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index b522de7d43d3..46e39bec3249 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -102,7 +102,6 @@ pub mod lint; pub mod middle { pub mod expr_use_visitor; pub mod cstore; - pub mod dead; pub mod dependency_format; pub mod diagnostic_items; pub mod entry; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index ef9da5c2bde8..2fa6edb46b1c 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -972,7 +972,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { tcx.ensure().check_private_in_public(LOCAL_CRATE); }); }, { - time(sess, "death checking", || middle::dead::check_crate(tcx)); + time(sess, "death checking", || rustc_passes::dead::check_crate(tcx)); }, { time(sess, "unused lib feature checking", || { stability::check_unused_or_stable_features(tcx) diff --git a/src/librustc/middle/dead.rs b/src/librustc_passes/dead.rs similarity index 98% rename from src/librustc/middle/dead.rs rename to src/librustc_passes/dead.rs index 7c75a1447e26..f2aef2c12c7d 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc_passes/dead.rs @@ -2,18 +2,18 @@ // closely. The idea is that all reachable symbols are live, codes called // from live codes are live, and everything else is dead. -use crate::hir::Node; -use crate::hir::{self, PatKind, TyKind}; -use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use crate::hir::itemlikevisit::ItemLikeVisitor; +use rustc::hir::Node; +use rustc::hir::{self, PatKind, TyKind}; +use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use rustc::hir::itemlikevisit::ItemLikeVisitor; -use crate::hir::def::{CtorOf, Res, DefKind}; -use crate::hir::CodegenFnAttrFlags; -use crate::hir::def_id::{DefId, LOCAL_CRATE}; -use crate::lint; -use crate::middle::privacy; -use crate::ty::{self, DefIdTree, TyCtxt}; -use crate::util::nodemap::FxHashSet; +use rustc::hir::def::{CtorOf, Res, DefKind}; +use rustc::hir::CodegenFnAttrFlags; +use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::lint; +use rustc::middle::privacy; +use rustc::ty::{self, DefIdTree, TyCtxt}; +use rustc::util::nodemap::FxHashSet; use rustc_data_structures::fx::FxHashMap; diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 7aa353cec082..c0b4a317cf94 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -22,6 +22,7 @@ pub mod ast_validation; pub mod hir_stats; pub mod layout_test; pub mod loops; +pub mod dead; mod liveness; pub fn provide(providers: &mut Providers<'_>) { From 82bfd8eb0dc8edcf7e231b9d998270a745f9a9c4 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:37:40 -0400 Subject: [PATCH 072/545] middle::entry -> rustc_passes --- src/librustc/error_codes.rs | 75 ------------------ src/librustc/lib.rs | 1 - src/librustc_interface/passes.rs | 3 +- .../middle => librustc_passes}/entry.rs | 16 ++-- src/librustc_passes/error_codes.rs | 77 +++++++++++++++++++ src/librustc_passes/lib.rs | 6 ++ 6 files changed, 92 insertions(+), 86 deletions(-) rename src/{librustc/middle => librustc_passes}/entry.rs (95%) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 968b0b9f2f2b..9b04c2db9ff3 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -466,66 +466,6 @@ fn main() { ``` "##, -// This shouldn't really ever trigger since the repeated value error comes first -E0136: r##" -A binary can only have one entry point, and by default that entry point is the -function `main()`. If there are multiple such functions, please rename one. -"##, - -E0137: r##" -More than one function was declared with the `#[main]` attribute. - -Erroneous code example: - -```compile_fail,E0137 -#![feature(main)] - -#[main] -fn foo() {} - -#[main] -fn f() {} // error: multiple functions with a `#[main]` attribute -``` - -This error indicates that the compiler found multiple functions with the -`#[main]` attribute. This is an error because there must be a unique entry -point into a Rust program. Example: - -``` -#![feature(main)] - -#[main] -fn f() {} // ok! -``` -"##, - -E0138: r##" -More than one function was declared with the `#[start]` attribute. - -Erroneous code example: - -```compile_fail,E0138 -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize {} - -#[start] -fn f(argc: isize, argv: *const *const u8) -> isize {} -// error: multiple 'start' functions -``` - -This error indicates that the compiler found multiple functions with the -`#[start]` attribute. This is an error because there must be a unique entry -point into a Rust program. Example: - -``` -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! -``` -"##, E0139: r##" #### Note: this error code is no longer emitted by the compiler. @@ -1941,21 +1881,6 @@ fn main() { ``` "##, -E0601: r##" -No `main` function was found in a binary crate. To fix this error, add a -`main` function. For example: - -``` -fn main() { - // Your program will start here. - println!("Hello world!"); -} -``` - -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/ -"##, - E0602: r##" An unknown lint was used on the command line. diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 46e39bec3249..197792eebb32 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -104,7 +104,6 @@ pub mod middle { pub mod cstore; pub mod dependency_format; pub mod diagnostic_items; - pub mod entry; pub mod exported_symbols; pub mod free_region; pub mod intrinsicck; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 2fa6edb46b1c..6d90d1c839ff 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -785,7 +785,6 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { rustc_passes::provide(providers); rustc_traits::provide(providers); middle::region::provide(providers); - middle::entry::provide(providers); cstore::provide(providers); lint::provide(providers); rustc_lint::provide(providers); @@ -891,7 +890,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { time(sess, "misc checking 1", || { parallel!({ entry_point = time(sess, "looking for entry point", || { - middle::entry::find_entry_point(tcx) + rustc_passes::entry::find_entry_point(tcx) }); time(sess, "looking for plugin registrar", || { diff --git a/src/librustc/middle/entry.rs b/src/librustc_passes/entry.rs similarity index 95% rename from src/librustc/middle/entry.rs rename to src/librustc_passes/entry.rs index 660fe14ba070..bf68807a0c29 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc_passes/entry.rs @@ -1,15 +1,15 @@ -use crate::hir::map as hir_map; -use crate::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; -use crate::session::{config, Session}; -use crate::session::config::EntryFnType; +use rustc::hir::map as hir_map; +use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; +use rustc::session::{config, Session}; +use rustc::session::config::EntryFnType; use syntax::attr; use syntax::entry::EntryPointType; use syntax::symbol::sym; use syntax_pos::Span; -use crate::hir::{HirId, Item, ItemKind, ImplItem, TraitItem}; -use crate::hir::itemlikevisit::ItemLikeVisitor; -use crate::ty::TyCtxt; -use crate::ty::query::Providers; +use rustc::hir::{HirId, Item, ItemKind, ImplItem, TraitItem}; +use rustc::hir::itemlikevisit::ItemLikeVisitor; +use rustc::ty::TyCtxt; +use rustc::ty::query::Providers; struct EntryContext<'a, 'tcx> { session: &'a Session, diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index af07c790e2a8..78260bd82456 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -319,6 +319,83 @@ async fn foo() {} Switch to the Rust 2018 edition to use `async fn`. "##, + +// This shouldn't really ever trigger since the repeated value error comes first +E0136: r##" +A binary can only have one entry point, and by default that entry point is the +function `main()`. If there are multiple such functions, please rename one. +"##, + +E0137: r##" +More than one function was declared with the `#[main]` attribute. + +Erroneous code example: + +```compile_fail,E0137 +#![feature(main)] + +#[main] +fn foo() {} + +#[main] +fn f() {} // error: multiple functions with a `#[main]` attribute +``` + +This error indicates that the compiler found multiple functions with the +`#[main]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(main)] + +#[main] +fn f() {} // ok! +``` +"##, + +E0138: r##" +More than one function was declared with the `#[start]` attribute. + +Erroneous code example: + +```compile_fail,E0138 +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize {} + +#[start] +fn f(argc: isize, argv: *const *const u8) -> isize {} +// error: multiple 'start' functions +``` + +This error indicates that the compiler found multiple functions with the +`#[start]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! +``` +"##, + +E0601: r##" +No `main` function was found in a binary crate. To fix this error, add a +`main` function. For example: + +``` +fn main() { + // Your program will start here. + println!("Hello world!"); +} +``` + +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/ +"##, + ; E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index c0b4a317cf94..1000770fb41e 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -13,6 +13,10 @@ #[macro_use] extern crate rustc; +#[macro_use] +extern crate log; +#[macro_use] +extern crate syntax; use rustc::ty::query::Providers; @@ -23,9 +27,11 @@ pub mod hir_stats; pub mod layout_test; pub mod loops; pub mod dead; +pub mod entry; mod liveness; pub fn provide(providers: &mut Providers<'_>) { + entry::provide(providers); loops::provide(providers); liveness::provide(providers); } From 7c3f65b3c4691ff0df270505ebfab89f171c0d28 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:46:57 -0400 Subject: [PATCH 073/545] middle::intrinsicck -> rustc_passes --- Cargo.lock | 2 + src/librustc/error_codes.rs | 105 ------------------ src/librustc/lib.rs | 1 - src/librustc_interface/passes.rs | 1 - src/librustc_passes/Cargo.toml | 2 + src/librustc_passes/error_codes.rs | 105 ++++++++++++++++++ .../middle => librustc_passes}/intrinsicck.rs | 14 +-- src/librustc_passes/lib.rs | 2 + 8 files changed, 118 insertions(+), 114 deletions(-) rename src/{librustc/middle => librustc_passes}/intrinsicck.rs (95%) diff --git a/Cargo.lock b/Cargo.lock index 80364515a7cc..512dc5fd887c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3613,6 +3613,8 @@ dependencies = [ "rustc", "rustc_data_structures", "rustc_errors", + "rustc_index", + "rustc_target", "syntax", "syntax_pos", ] diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 9b04c2db9ff3..66c51000066b 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1566,33 +1566,6 @@ It is not possible to use stability attributes outside of the standard library. Also, for now, it is not possible to write deprecation messages either. "##, -E0512: r##" -Transmute with two differently sized types was attempted. Erroneous code -example: - -```compile_fail,E0512 -fn takes_u8(_: u8) {} - -fn main() { - unsafe { takes_u8(::std::mem::transmute(0u16)); } - // error: cannot transmute between types of different sizes, - // or dependently-sized types -} -``` - -Please use types with same size or use the expected type directly. Example: - -``` -fn takes_u8(_: u8) {} - -fn main() { - unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok! - // or: - unsafe { takes_u8(0u8); } // ok! -} -``` -"##, - E0517: r##" This error indicates that a `#[repr(..)]` attribute was placed on an unsupported item. @@ -1787,84 +1760,6 @@ See [RFC 1522] for more details. [RFC 1522]: https://github.com/rust-lang/rfcs/blob/master/text/1522-conservative-impl-trait.md "##, -E0591: r##" -Per [RFC 401][rfc401], if you have a function declaration `foo`: - -``` -// For the purposes of this explanation, all of these -// different kinds of `fn` declarations are equivalent: -struct S; -fn foo(x: S) { /* ... */ } -# #[cfg(for_demonstration_only)] -extern "C" { fn foo(x: S); } -# #[cfg(for_demonstration_only)] -impl S { fn foo(self) { /* ... */ } } -``` - -the type of `foo` is **not** `fn(S)`, as one might expect. -Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. -However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, -so you rarely notice this: - -``` -# struct S; -# fn foo(_: S) {} -let x: fn(S) = foo; // OK, coerces -``` - -The reason that this matter is that the type `fn(S)` is not specific to -any particular function: it's a function _pointer_. So calling `x()` results -in a virtual call, whereas `foo()` is statically dispatched, because the type -of `foo` tells us precisely what function is being called. - -As noted above, coercions mean that most code doesn't have to be -concerned with this distinction. However, you can tell the difference -when using **transmute** to convert a fn item into a fn pointer. - -This is sometimes done as part of an FFI: - -```compile_fail,E0591 -extern "C" fn foo(userdata: Box) { - /* ... */ -} - -# fn callback(_: extern "C" fn(*mut i32)) {} -# use std::mem::transmute; -# unsafe { -let f: extern "C" fn(*mut i32) = transmute(foo); -callback(f); -# } -``` - -Here, transmute is being used to convert the types of the fn arguments. -This pattern is incorrect because, because the type of `foo` is a function -**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`) -is a function pointer, which is not zero-sized. -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: - - ``` - # extern "C" fn foo(_: Box) {} - # use std::mem::transmute; - # unsafe { - let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); - let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too - # } - ``` - -The same applies to transmutes to `*mut fn()`, which were observed in practice. -Note though that use of this type is generally incorrect. -The intention is typically to describe a function pointer, but just `fn()` -alone suffices for that. `*mut fn()` is a pointer to a fn pointer. -(Since these values are typically just passed to C code, however, this rarely -makes a difference in practice.) - -[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md -"##, - E0593: r##" You tried to supply an `Fn`-based type with an incorrect number of arguments than what was expected. diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 197792eebb32..0eea149f30ae 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -106,7 +106,6 @@ pub mod middle { pub mod diagnostic_items; pub mod exported_symbols; pub mod free_region; - pub mod intrinsicck; pub mod lib_features; pub mod lang_items; pub mod mem_categorization; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 6d90d1c839ff..870f804ed447 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -780,7 +780,6 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { ty::provide(providers); traits::provide(providers); stability::provide(providers); - middle::intrinsicck::provide(providers); reachable::provide(providers); rustc_passes::provide(providers); rustc_traits::provide(providers); diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 596ec6c19bcb..9d29a2303144 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -15,3 +15,5 @@ rustc_data_structures = { path = "../librustc_data_structures" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } errors = { path = "../librustc_errors", package = "rustc_errors" } +rustc_target = { path = "../librustc_target" } +rustc_index = { path = "../librustc_index" } diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index 78260bd82456..1c61eb35497d 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -396,6 +396,111 @@ 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/ "##, +E0591: r##" +Per [RFC 401][rfc401], if you have a function declaration `foo`: + +``` +// For the purposes of this explanation, all of these +// different kinds of `fn` declarations are equivalent: +struct S; +fn foo(x: S) { /* ... */ } +# #[cfg(for_demonstration_only)] +extern "C" { fn foo(x: S); } +# #[cfg(for_demonstration_only)] +impl S { fn foo(self) { /* ... */ } } +``` + +the type of `foo` is **not** `fn(S)`, as one might expect. +Rather, it is a unique, zero-sized marker type written here as `typeof(foo)`. +However, `typeof(foo)` can be _coerced_ to a function pointer `fn(S)`, +so you rarely notice this: + +``` +# struct S; +# fn foo(_: S) {} +let x: fn(S) = foo; // OK, coerces +``` + +The reason that this matter is that the type `fn(S)` is not specific to +any particular function: it's a function _pointer_. So calling `x()` results +in a virtual call, whereas `foo()` is statically dispatched, because the type +of `foo` tells us precisely what function is being called. + +As noted above, coercions mean that most code doesn't have to be +concerned with this distinction. However, you can tell the difference +when using **transmute** to convert a fn item into a fn pointer. + +This is sometimes done as part of an FFI: + +```compile_fail,E0591 +extern "C" fn foo(userdata: Box) { + /* ... */ +} + +# fn callback(_: extern "C" fn(*mut i32)) {} +# use std::mem::transmute; +# unsafe { +let f: extern "C" fn(*mut i32) = transmute(foo); +callback(f); +# } +``` + +Here, transmute is being used to convert the types of the fn arguments. +This pattern is incorrect because, because the type of `foo` is a function +**item** (`typeof(foo)`), which is zero-sized, and the target type (`fn()`) +is a function pointer, which is not zero-sized. +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: + + ``` + # extern "C" fn foo(_: Box) {} + # use std::mem::transmute; + # unsafe { + let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); + let f: extern "C" fn(*mut i32) = transmute(foo as usize); // works too + # } + ``` + +The same applies to transmutes to `*mut fn()`, which were observed in practice. +Note though that use of this type is generally incorrect. +The intention is typically to describe a function pointer, but just `fn()` +alone suffices for that. `*mut fn()` is a pointer to a fn pointer. +(Since these values are typically just passed to C code, however, this rarely +makes a difference in practice.) + +[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md +"##, + +E0512: r##" +Transmute with two differently sized types was attempted. Erroneous code +example: + +```compile_fail,E0512 +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0u16)); } + // error: cannot transmute between types of different sizes, + // or dependently-sized types +} +``` + +Please use types with same size or use the expected type directly. Example: + +``` +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok! + // or: + unsafe { takes_u8(0u8); } // ok! +} +``` +"##, + ; E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs similarity index 95% rename from src/librustc/middle/intrinsicck.rs rename to src/librustc_passes/intrinsicck.rs index 7b5aea8ac984..91a7e9f5d7fc 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -1,14 +1,14 @@ -use crate::hir::def::{Res, DefKind}; -use crate::hir::def_id::DefId; -use crate::ty::{self, Ty, TyCtxt}; -use crate::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx}; -use crate::ty::query::Providers; +use rustc::hir::def::{Res, DefKind}; +use rustc::hir::def_id::DefId; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx}; +use rustc::ty::query::Providers; use rustc_target::spec::abi::Abi::RustIntrinsic; use rustc_index::vec::Idx; use syntax_pos::{Span, sym}; -use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; -use crate::hir; +use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; +use rustc::hir; fn check_mod_intrinsics(tcx: TyCtxt<'_>, module_def_id: DefId) { tcx.hir().visit_item_likes_in_module( diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs index 1000770fb41e..db59d8e101f7 100644 --- a/src/librustc_passes/lib.rs +++ b/src/librustc_passes/lib.rs @@ -29,9 +29,11 @@ pub mod loops; pub mod dead; pub mod entry; mod liveness; +mod intrinsicck; pub fn provide(providers: &mut Providers<'_>) { entry::provide(providers); loops::provide(providers); liveness::provide(providers); + intrinsicck::provide(providers); } From d0a6805b0e2711b38a9663a88d23699dd328abb6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 4 Oct 2019 10:43:15 -0400 Subject: [PATCH 074/545] Allow unused attributes to avoid incremental bug --- src/libcore/slice/mod.rs | 1 + src/libcore/str/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index b5462d988378..4e79ea812044 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -63,6 +63,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] // SAFETY: const sound because we transmute out the length field as a usize (which it must be) + #[allow(unused_attributes)] #[allow_internal_unstable(const_fn_union)] pub const fn len(&self) -> usize { unsafe { diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index ece61dde490f..885696e5acf4 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2167,6 +2167,7 @@ impl str { #[stable(feature = "rust1", since = "1.0.0")] #[inline(always)] // SAFETY: const sound because we transmute two types with the same layout + #[allow(unused_attributes)] #[allow_internal_unstable(const_fn_union)] pub const fn as_bytes(&self) -> &[u8] { #[repr(C)] From d152d487276eda48601b5192ffcb8e69c4a83761 Mon Sep 17 00:00:00 2001 From: Yechan Bae Date: Fri, 4 Oct 2019 16:31:38 -0400 Subject: [PATCH 075/545] Fix lonely backtick --- src/librustc_metadata/decoder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 34f86707ad32..eed355cbc135 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -919,7 +919,7 @@ impl<'a, 'tcx> CrateMetadata { self.entry_unless_proc_macro(id) .and_then(|entry| entry.mir.map(|mir| mir.decode((self, tcx)))) .unwrap_or_else(|| { - bug!("get_optimized_mir: missing MIR for `{:?}", self.local_def_id(id)) + bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) } From 37026837a3f23486d3cf1009d9136927168ddb33 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 29 Sep 2019 21:35:20 +0100 Subject: [PATCH 076/545] Make `into` schedule drop for the destination --- src/librustc_mir/build/block.rs | 70 ++++-- src/librustc_mir/build/expr/as_rvalue.rs | 7 +- src/librustc_mir/build/expr/as_temp.rs | 12 +- src/librustc_mir/build/expr/into.rs | 46 +++- src/librustc_mir/build/into.rs | 25 ++- src/librustc_mir/build/matches/mod.rs | 20 +- src/librustc_mir/build/mod.rs | 10 +- src/librustc_mir/build/scope.rs | 26 ++- src/test/mir-opt/box_expr.rs | 19 +- src/test/mir-opt/issue-62289.rs | 53 ++--- src/test/ui/drop/dynamic-drop-async.rs | 149 +++++++++---- src/test/ui/drop/dynamic-drop.rs | 259 +++++++++++++++-------- 12 files changed, 458 insertions(+), 238 deletions(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 7353ca9285dd..f9440866e492 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -1,18 +1,22 @@ use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::build::ForGuard::OutsideGuard; use crate::build::matches::ArmHasGuard; +use crate::build::scope::DropKind; use crate::hair::*; +use rustc::middle::region; use rustc::mir::*; use rustc::hir; use syntax_pos::Span; impl<'a, 'tcx> Builder<'a, 'tcx> { - pub fn ast_block(&mut self, - destination: &Place<'tcx>, - block: BasicBlock, - ast_block: &'tcx hir::Block, - source_info: SourceInfo) - -> BlockAnd<()> { + pub fn ast_block( + &mut self, + destination: &Place<'tcx>, + scope: Option, + block: BasicBlock, + ast_block: &'tcx hir::Block, + source_info: SourceInfo, + ) -> BlockAnd<()> { let Block { region_scope, opt_destruction_scope, @@ -21,37 +25,61 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr, targeted_by_break, safety_mode - } = - self.hir.mirror(ast_block); + } = self.hir.mirror(ast_block); self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), move |this| { this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| { if targeted_by_break { // This is a `break`-able block let exit_block = this.cfg.start_new_block(); + if let Some(scope) = scope { + // Breakable blocks assign to their destination on each + // `break`, as well as when they exit normally. So we + // can't schedule the drop in the last expression like + // normal blocks do. + let local = destination.as_local() + .expect("cannot schedule drop of non-Local place"); + this.schedule_drop(span, scope, local, DropKind::Value); + } let block_exit = this.in_breakable_scope( None, exit_block, destination.clone(), |this| { - this.ast_block_stmts(destination, block, span, stmts, expr, - safety_mode) + this.ast_block_stmts( + destination, + None, + block, + span, + stmts, + expr, + safety_mode, + ) }); this.cfg.terminate(unpack!(block_exit), source_info, TerminatorKind::Goto { target: exit_block }); exit_block.unit() } else { - this.ast_block_stmts(destination, block, span, stmts, expr, - safety_mode) + this.ast_block_stmts( + destination, + scope, + block, + span, + stmts, + expr, + safety_mode, + ) } }) }) } - fn ast_block_stmts(&mut self, - destination: &Place<'tcx>, - mut block: BasicBlock, - span: Span, - stmts: Vec>, - expr: Option>, - safety_mode: BlockSafety) - -> BlockAnd<()> { + fn ast_block_stmts( + &mut self, + destination: &Place<'tcx>, + scope: Option, + mut block: BasicBlock, + span: Span, + stmts: Vec>, + expr: Option>, + safety_mode: BlockSafety, + ) -> BlockAnd<()> { let this = self; // This convoluted structure is to avoid using recursion as we walk down a list @@ -177,7 +205,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.block_context.currently_ignores_tail_results(); this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored }); - unpack!(block = this.into(destination, block, expr)); + unpack!(block = this.into(destination, scope, block, expr)); let popped = this.block_context.pop(); assert!(popped.map_or(false, |bf|bf.is_tail_expr())); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index 7e8c83fe9d3c..7e59419983b4 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -136,11 +136,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg .push_assign(block, source_info, &Place::from(result), box_); - // initialize the box contents: + // Initialize the box contents. No scope is needed since the + // `Box` is already scheduled to be dropped. unpack!( block = this.into( &Place::from(result).deref(), - block, value + None, + block, + value ) ); block.and(Rvalue::Use(Operand::Move(Place::from(result)))) diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index c56a149d8614..bd20f27c945c 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -109,17 +109,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - unpack!(block = this.into(temp_place, block, expr)); - - if let Some(temp_lifetime) = temp_lifetime { - this.schedule_drop( - expr_span, - temp_lifetime, - temp, - expr_ty, - DropKind::Value, - ); - } + unpack!(block = this.into(temp_place, temp_lifetime, block, expr)); block.and(temp) } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 8a6bc5a2a764..c262215ab9be 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -2,7 +2,9 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; +use crate::build::scope::DropKind; use crate::hair::*; +use rustc::middle::region; use rustc::mir::*; use rustc::ty; @@ -11,15 +13,18 @@ use rustc_target::spec::abi::Abi; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which /// is assumed to be uninitialized. + /// If a `drop_scope` is provided, `destination` is scheduled to be dropped + /// in `scope` once it has been initialized. pub fn into_expr( &mut self, destination: &Place<'tcx>, + scope: Option, mut block: BasicBlock, expr: Expr<'tcx>, ) -> BlockAnd<()> { debug!( - "into_expr(destination={:?}, block={:?}, expr={:?})", - destination, block, expr + "into_expr(destination={:?}, scope={:?}, block={:?}, expr={:?})", + destination, scope, block, expr ); // since we frequently have to reference `self` from within a @@ -35,6 +40,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => false, }; + let schedule_drop = move |this: &mut Self| { + if let Some(drop_scope) = scope { + let local = destination.as_local() + .expect("cannot schedule drop of non-Local place"); + this.schedule_drop(expr_span, drop_scope, local, DropKind::Value); + } + }; + if !expr_is_block_or_scope { this.block_context.push(BlockFrame::SubExpr); } @@ -47,14 +60,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } => { let region_scope = (region_scope, source_info); this.in_scope(region_scope, lint_level, |this| { - this.into(destination, block, value) + this.into(destination, scope, block, value) }) } ExprKind::Block { body: ast_block } => { - this.ast_block(destination, block, ast_block, source_info) + this.ast_block(destination, scope, block, ast_block, source_info) } ExprKind::Match { scrutinee, arms } => { - this.match_expr(destination, expr_span, block, scrutinee, arms) + this.match_expr(destination, scope, expr_span, block, scrutinee, arms) } ExprKind::NeverToAny { source } => { let source = this.hir.mirror(source); @@ -67,6 +80,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This is an optimization. If the expression was a call then we already have an // unreachable block. Don't bother to terminate it and create a new one. + schedule_drop(this); if is_call { block.unit() } else { @@ -164,6 +178,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TerminatorKind::Goto { target: loop_block }, ); + // Loops assign to their destination on each `break`. Since we + // can't easily unschedule drops, we schedule the drop now. + schedule_drop(this); this.in_breakable_scope( Some(loop_block), exit_block, @@ -185,7 +202,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // introduce a unit temporary as the destination for the loop body. let tmp = this.get_unit_temp(); // Execute the body, branching back to the test. - let body_block_end = unpack!(this.into(&tmp, body_block, body)); + // No scope is provided, since we've scheduled the drop above. + let body_block_end = unpack!(this.into(&tmp, None, body_block, body)); this.cfg.terminate( body_block_end, source_info, @@ -234,8 +252,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { is_block_tail: None, }); let ptr_temp = Place::from(ptr_temp); - let block = unpack!(this.into(&ptr_temp, block, ptr)); - this.into(&ptr_temp.deref(), block, val) + // No need for a scope, ptr_temp doesn't need drop + let block = unpack!(this.into(&ptr_temp, None, block, ptr)); + // Maybe we should provide a scope here so that + // `move_val_init` wouldn't leak on panic even with an + // arbitrary `val` expression, but `schedule_drop`, + // borrowck and drop elaboration all prevent us from + // dropping `ptr_temp.deref()`. + this.into(&ptr_temp.deref(), None, block, val) } else { let args: Vec<_> = args .into_iter() @@ -265,11 +289,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { from_hir_call, }, ); + schedule_drop(this); success.unit() } } ExprKind::Use { source } => { - this.into(destination, block, source) + this.into(destination, scope, block, source) } // These cases don't actually need a destination @@ -296,6 +321,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); this.cfg .push_assign(block, source_info, destination, rvalue); + schedule_drop(this); block.unit() } ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => { @@ -315,6 +341,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); this.cfg .push_assign(block, source_info, destination, rvalue); + schedule_drop(this); block.unit() } @@ -346,6 +373,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let rvalue = unpack!(block = this.as_local_rvalue(block, expr)); this.cfg.push_assign(block, source_info, destination, rvalue); + schedule_drop(this); block.unit() } }; diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir/build/into.rs index 077840c9ccf1..e57f10f0b14e 100644 --- a/src/librustc_mir/build/into.rs +++ b/src/librustc_mir/build/into.rs @@ -6,6 +6,7 @@ use crate::build::{BlockAnd, Builder}; use crate::hair::*; +use rustc::middle::region; use rustc::mir::*; pub(in crate::build) trait EvalInto<'tcx> { @@ -13,19 +14,23 @@ pub(in crate::build) trait EvalInto<'tcx> { self, builder: &mut Builder<'_, 'tcx>, destination: &Place<'tcx>, + scope: Option, block: BasicBlock, ) -> BlockAnd<()>; } impl<'a, 'tcx> Builder<'a, 'tcx> { - pub fn into(&mut self, - destination: &Place<'tcx>, - block: BasicBlock, - expr: E) - -> BlockAnd<()> - where E: EvalInto<'tcx> + pub fn into( + &mut self, + destination: &Place<'tcx>, + scope: Option, + block: BasicBlock, + expr: E, + ) -> BlockAnd<()> + where + E: EvalInto<'tcx>, { - expr.eval_into(self, destination, block) + expr.eval_into(self, destination, scope, block) } } @@ -34,10 +39,11 @@ impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> { self, builder: &mut Builder<'_, 'tcx>, destination: &Place<'tcx>, + scope: Option, block: BasicBlock, ) -> BlockAnd<()> { let expr = builder.hir.mirror(self); - builder.into_expr(destination, block, expr) + builder.into_expr(destination, scope, block, expr) } } @@ -46,8 +52,9 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> { self, builder: &mut Builder<'_, 'tcx>, destination: &Place<'tcx>, + scope: Option, block: BasicBlock, ) -> BlockAnd<()> { - builder.into_expr(destination, block, self) + builder.into_expr(destination, scope, block, self) } } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index b223d528d72f..914bf4129b0e 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -102,6 +102,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn match_expr( &mut self, destination: &Place<'tcx>, + destination_scope: Option, span: Span, mut block: BasicBlock, scrutinee: ExprRef<'tcx>, @@ -228,6 +229,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; // Step 5. Create everything else: the guards and the arms. + if let Some(scope) = destination_scope { + // `match` assigns to its destination in each arm. Since we can't + // easily unschedule drops, we schedule the drop now. + let local = destination.as_local() + .expect("cannot schedule drop of non-Local place"); + self.schedule_drop(span, scope, local, DropKind::Value); + } + let match_scope = self.scopes.topmost(); let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, mut candidates)| { @@ -275,7 +284,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.source_scope = source_scope; } - this.into(destination, arm_block, body) + // No scope is provided, since we've scheduled the drop above. + this.into(destination, None, arm_block, body) }) }).collect(); @@ -311,8 +321,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } => { let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); - unpack!(block = self.into(&place, block, initializer)); + let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); + unpack!(block = self.into(&place, Some(region_scope), block, initializer)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. let source_info = self.source_info(irrefutable_pat.span); @@ -324,7 +335,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); - self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } @@ -352,9 +362,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { user_ty_span, }, } => { + let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); - unpack!(block = self.into(&place, block, initializer)); + unpack!(block = self.into(&place, Some(region_scope), block, initializer)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. let pattern_source_info = self.source_info(irrefutable_pat.span); @@ -400,7 +411,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); - self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 9414113cefb5..27598959e510 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -616,6 +616,7 @@ where let source_info = builder.source_info(span); let call_site_s = (call_site_scope, source_info); unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| { + builder.schedule_drop(span, call_site_scope, RETURN_PLACE, DropKind::Value); if should_abort_on_panic(tcx, fn_def_id, abi) { builder.schedule_abort(); } @@ -646,6 +647,7 @@ where builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable); } + builder.unschedule_return_place_drop(); return_block.unit() })); assert_eq!(block, builder.return_block()); @@ -687,7 +689,9 @@ fn construct_const<'a, 'tcx>( let mut block = START_BLOCK; let ast_expr = &tcx.hir().body(body_id).value; let expr = builder.hir.mirror(ast_expr); - unpack!(block = builder.into_expr(&Place::return_place(), block, expr)); + // We don't provide a scope because we can't unwind in constants, so won't + // need to drop the return place. + unpack!(block = builder.into_expr(&Place::return_place(), None, block, expr)); let source_info = builder.source_info(span); builder.cfg.terminate(block, source_info, TerminatorKind::Return); @@ -888,7 +892,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let body = self.hir.mirror(ast_body); - self.into(&Place::return_place(), block, body) + // No scope is provided, since we've scheduled the drop of the return + // place. + self.into(&Place::return_place(), None, block, body) } fn set_correct_source_scope_for_arg( diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 9b4ea175e2a9..6206bfd9f3ea 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -513,7 +513,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(value) = value { debug!("stmt_expr Break val block_context.push(SubExpr)"); self.block_context.push(BlockFrame::SubExpr); - unpack!(block = self.into(&destination, block, value)); + unpack!(block = self.into(&destination, None, block, value)); self.block_context.pop(); } else { self.cfg.push_assign_unit(block, source_info, &destination) @@ -742,12 +742,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: Span, region_scope: region::Scope, local: Local, - place_ty: Ty<'tcx>, drop_kind: DropKind, ) { - let needs_drop = self.hir.needs_drop(place_ty); - match drop_kind { - DropKind::Value => if !needs_drop { return }, + let needs_drop = match drop_kind { + DropKind::Value => { + if !self.hir.needs_drop(self.local_decls[local].ty) { return } + true + }, DropKind::Storage => { if local.index() <= self.arg_count { span_bug!( @@ -756,8 +757,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.arg_count, ) } + false } - } + }; for scope in self.scopes.iter_mut() { let this_scope = scope.region_scope == region_scope; @@ -1068,6 +1070,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { success_block } + /// Unschedules the drop of the return place. + /// + /// If the return type of a function requires drop, then we schedule it + /// in the outermost scope so that it's dropped if there's a panic while + /// we drop any local variables. But we don't want to drop it if we + /// return normally. + crate fn unschedule_return_place_drop(&mut self) { + assert_eq!(self.scopes.len(), 1); + assert!(self.scopes.scopes[0].drops.len() <= 1); + self.scopes.scopes[0].drops.clear(); + } + // `match` arm scopes // ================== /// Unschedules any drops in the top scope. diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs index 8dc6b73edf6d..76098731947f 100644 --- a/src/test/mir-opt/box_expr.rs +++ b/src/test/mir-opt/box_expr.rs @@ -41,33 +41,36 @@ impl Drop for S { // // bb2: { // _1 = move _2; -// drop(_2) -> bb4; +// drop(_2) -> [return: bb5, unwind: bb4]; // } // // bb3 (cleanup): { // drop(_2) -> bb1; // } // -// bb4: { +// bb4 (cleanup): { +// drop(_1) -> bb1; +// } +// +// bb5: { // StorageDead(_2); // StorageLive(_3); // StorageLive(_4); // _4 = move _1; -// _3 = const std::mem::drop::>(move _4) -> [return: bb5, unwind: bb7]; +// _3 = const std::mem::drop::>(move _4) -> [return: bb6, unwind: bb7]; // } // -// bb5: { +// bb6: { // StorageDead(_4); // StorageDead(_3); // _0 = (); // drop(_1) -> bb8; // } -// bb6 (cleanup): { -// drop(_1) -> bb1; -// } +// // bb7 (cleanup): { -// drop(_4) -> bb6; +// drop(_4) -> bb4; // } +// // bb8: { // StorageDead(_1); // return; diff --git a/src/test/mir-opt/issue-62289.rs b/src/test/mir-opt/issue-62289.rs index a3b517e9bca8..e8dd56cbbae2 100644 --- a/src/test/mir-opt/issue-62289.rs +++ b/src/test/mir-opt/issue-62289.rs @@ -24,7 +24,7 @@ fn main() { // StorageLive(_3); // StorageLive(_4); // _4 = std::option::Option::::None; -// _3 = const as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb3]; +// _3 = const as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb4]; // } // bb1 (cleanup): { // resume; @@ -32,60 +32,63 @@ fn main() { // bb2: { // StorageDead(_4); // _5 = discriminant(_3); -// switchInt(move _5) -> [0isize: bb10, 1isize: bb5, otherwise: bb4]; +// switchInt(move _5) -> [0isize: bb11, 1isize: bb6, otherwise: bb5]; // } // bb3 (cleanup): { -// drop(_2) -> bb1; +// drop(_0) -> bb1; // } -// bb4: { -// unreachable; +// bb4 (cleanup): { +// drop(_2) -> bb3; // } // bb5: { +// unreachable; +// } +// bb6: { // StorageLive(_6); // _6 = ((_3 as Err).0: std::option::NoneError); // StorageLive(_8); // StorageLive(_9); // _9 = _6; -// _8 = const >::from(move _9) -> [return: bb7, unwind: bb3]; -// } -// bb6: { -// return; +// _8 = const >::from(move _9) -> [return: bb8, unwind: bb4]; // } // bb7: { -// StorageDead(_9); -// _0 = const > as std::ops::Try>::from_error(move _8) -> [return: bb8, unwind: bb3]; +// return; // } // bb8: { -// StorageDead(_8); -// StorageDead(_6); -// drop(_2) -> bb9; +// StorageDead(_9); +// _0 = const > as std::ops::Try>::from_error(move _8) -> [return: bb9, unwind: bb4]; // } // bb9: { +// StorageDead(_8); +// StorageDead(_6); +// drop(_2) -> [return: bb10, unwind: bb3]; +// } +// bb10: { // StorageDead(_2); // StorageDead(_1); // StorageDead(_3); -// goto -> bb6; +// goto -> bb7; // } -// bb10: { +// bb11: { // StorageLive(_10); // _10 = ((_3 as Ok).0: u32); // (*_2) = _10; // StorageDead(_10); // _1 = move _2; -// drop(_2) -> [return: bb12, unwind: bb11]; +// drop(_2) -> [return: bb13, unwind: bb12]; // } -// bb11 (cleanup): { -// drop(_1) -> bb1; -// } -// bb12: { -// StorageDead(_2); -// _0 = std::option::Option::>::Some(move _1,); -// drop(_1) -> bb13; +// bb12 (cleanup): { +// drop(_1) -> bb3; // } // bb13: { +// StorageDead(_2); +// _0 = std::option::Option::>::Some(move _1,); +// drop(_1) -> [return: bb14, unwind: bb3]; +// } +// bb14: { // StorageDead(_1); // StorageDead(_3); -// goto -> bb6; +// goto -> bb7; // } // } // END rustc.test.ElaborateDrops.before.mir diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index 91063edf0f6c..398bcb7ec0e8 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -7,7 +7,7 @@ // edition:2018 // ignore-wasm32-bare compiled with panic=abort by default -#![feature(slice_patterns)] +#![feature(slice_patterns, arbitrary_self_types)] #![allow(unused)] use std::{ @@ -45,6 +45,7 @@ impl Future for Defer { /// The `failing_op`-th operation will panic. struct Allocator { data: RefCell>, + name: &'static str, failing_op: usize, cur_ops: Cell, } @@ -56,23 +57,28 @@ impl Drop for Allocator { fn drop(&mut self) { let data = self.data.borrow(); if data.iter().any(|d| *d) { - panic!("missing free: {:?}", data); + panic!("missing free in {:?}: {:?}", self.name, data); } } } impl Allocator { - fn new(failing_op: usize) -> Self { - Allocator { failing_op, cur_ops: Cell::new(0), data: RefCell::new(vec![]) } + fn new(failing_op: usize, name: &'static str) -> Self { + Allocator { + failing_op, + name, + cur_ops: Cell::new(0), + data: RefCell::new(vec![]), + } } - fn alloc(&self) -> impl Future> + '_ { + fn alloc(self: &Rc) -> impl Future + 'static { self.fallible_operation(); let mut data = self.data.borrow_mut(); let addr = data.len(); data.push(true); - Defer { ready: false, value: Some(Ptr(addr, self)) } + Defer { ready: false, value: Some(Ptr(addr, self.clone())) } } fn fallible_operation(&self) { self.cur_ops.set(self.cur_ops.get() + 1); @@ -85,11 +91,11 @@ impl Allocator { // Type that tracks whether it was dropped and can panic when it's created or // destroyed. -struct Ptr<'a>(usize, &'a Allocator); -impl<'a> Drop for Ptr<'a> { +struct Ptr(usize, Rc); +impl Drop for Ptr { fn drop(&mut self) { match self.1.data.borrow_mut()[self.0] { - false => panic!("double free at index {:?}", self.0), + false => panic!("double free in {:?} at index {:?}", self.1.name, self.0), ref mut d => *d = false, } @@ -113,7 +119,7 @@ async fn dynamic_drop(a: Rc, c: bool) { }; } -struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>); +struct TwoPtrs(Ptr, Ptr); async fn struct_dynamic_drop(a: Rc, c0: bool, c1: bool, c: bool) { for i in 0..2 { let x; @@ -228,21 +234,62 @@ async fn subslice_pattern_reassign(a: Rc) { a.alloc().await; } -fn run_test(cx: &mut Context<'_>, ref f: F) +async fn panic_after_return(a: Rc, c: bool) -> (Ptr,) { + a.alloc().await; + let p = a.alloc().await; + if c { + a.alloc().await; + let q = a.alloc().await; + // We use a return type that isn't used anywhere else to make sure that + // the return place doesn't incorrectly end up in the generator state. + return (a.alloc().await,); + } + (a.alloc().await,) +} + + +async fn panic_after_init_by_loop(a: Rc) { + a.alloc().await; + let p = a.alloc().await; + let q = loop { + a.alloc().await; + let r = a.alloc().await; + break a.alloc().await; + }; +} + +async fn panic_after_init_by_match_with_bindings_and_guard(a: Rc, b: bool) { + a.alloc().await; + let p = a.alloc().await; + let q = match a.alloc().await { + ref _x if b => { + a.alloc().await; + let r = a.alloc().await; + a.alloc().await + } + _x => { + a.alloc().await; + let r = a.alloc().await; + a.alloc().await + }, + }; +} + +fn run_test(cx: &mut Context<'_>, ref f: F, name: &'static str) where F: Fn(Rc) -> G, - G: Future, + G: Future, { for polls in 0.. { // Run without any panics to find which operations happen after the // penultimate `poll`. - let first_alloc = Rc::new(Allocator::new(usize::MAX)); + let first_alloc = Rc::new(Allocator::new(usize::MAX, name)); let mut fut = Box::pin(f(first_alloc.clone())); let mut ops_before_last_poll = 0; let mut completed = false; for _ in 0..polls { ops_before_last_poll = first_alloc.cur_ops.get(); - if let Poll::Ready(()) = fut.as_mut().poll(cx) { + if let Poll::Ready(_) = fut.as_mut().poll(cx) { completed = true; } } @@ -251,7 +298,7 @@ where // Start at `ops_before_last_poll` so that we will always be able to // `poll` the expected number of times. for failing_op in ops_before_last_poll..first_alloc.cur_ops.get() { - let alloc = Rc::new(Allocator::new(failing_op + 1)); + let alloc = Rc::new(Allocator::new(failing_op + 1, name)); let f = &f; let cx = &mut *cx; let result = panic::catch_unwind(panic::AssertUnwindSafe(move || { @@ -281,46 +328,56 @@ fn clone_waker(data: *const ()) -> RawWaker { RawWaker::new(data, &RawWakerVTable::new(clone_waker, drop, drop, drop)) } +macro_rules! run_test { + ($ctxt:expr, $e:expr) => { run_test($ctxt, $e, stringify!($e)); }; +} + fn main() { let waker = unsafe { Waker::from_raw(clone_waker(ptr::null())) }; let context = &mut Context::from_waker(&waker); - run_test(context, |a| dynamic_init(a, false)); - run_test(context, |a| dynamic_init(a, true)); - run_test(context, |a| dynamic_drop(a, false)); - run_test(context, |a| dynamic_drop(a, true)); + run_test!(context, |a| dynamic_init(a, false)); + run_test!(context, |a| dynamic_init(a, true)); + run_test!(context, |a| dynamic_drop(a, false)); + run_test!(context, |a| dynamic_drop(a, true)); - run_test(context, |a| assignment(a, false, false)); - run_test(context, |a| assignment(a, false, true)); - run_test(context, |a| assignment(a, true, false)); - run_test(context, |a| assignment(a, true, true)); + run_test!(context, |a| assignment(a, false, false)); + run_test!(context, |a| assignment(a, false, true)); + run_test!(context, |a| assignment(a, true, false)); + run_test!(context, |a| assignment(a, true, true)); - run_test(context, |a| array_simple(a)); - run_test(context, |a| vec_simple(a)); - run_test(context, |a| vec_unreachable(a)); + run_test!(context, |a| array_simple(a)); + run_test!(context, |a| vec_simple(a)); + run_test!(context, |a| vec_unreachable(a)); - run_test(context, |a| struct_dynamic_drop(a, false, false, false)); - run_test(context, |a| struct_dynamic_drop(a, false, false, true)); - run_test(context, |a| struct_dynamic_drop(a, false, true, false)); - run_test(context, |a| struct_dynamic_drop(a, false, true, true)); - run_test(context, |a| struct_dynamic_drop(a, true, false, false)); - run_test(context, |a| struct_dynamic_drop(a, true, false, true)); - run_test(context, |a| struct_dynamic_drop(a, true, true, false)); - run_test(context, |a| struct_dynamic_drop(a, true, true, true)); + run_test!(context, |a| struct_dynamic_drop(a, false, false, false)); + run_test!(context, |a| struct_dynamic_drop(a, false, false, true)); + run_test!(context, |a| struct_dynamic_drop(a, false, true, false)); + run_test!(context, |a| struct_dynamic_drop(a, false, true, true)); + run_test!(context, |a| struct_dynamic_drop(a, true, false, false)); + run_test!(context, |a| struct_dynamic_drop(a, true, false, true)); + run_test!(context, |a| struct_dynamic_drop(a, true, true, false)); + run_test!(context, |a| struct_dynamic_drop(a, true, true, true)); - run_test(context, |a| field_assignment(a, false)); - run_test(context, |a| field_assignment(a, true)); + run_test!(context, |a| field_assignment(a, false)); + run_test!(context, |a| field_assignment(a, true)); - run_test(context, |a| mixed_drop_and_nondrop(a)); + run_test!(context, |a| mixed_drop_and_nondrop(a)); - run_test(context, |a| slice_pattern_one_of(a, 0)); - run_test(context, |a| slice_pattern_one_of(a, 1)); - run_test(context, |a| slice_pattern_one_of(a, 2)); - run_test(context, |a| slice_pattern_one_of(a, 3)); + run_test!(context, |a| slice_pattern_one_of(a, 0)); + run_test!(context, |a| slice_pattern_one_of(a, 1)); + run_test!(context, |a| slice_pattern_one_of(a, 2)); + run_test!(context, |a| slice_pattern_one_of(a, 3)); - run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, true)); - run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, false)); - run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, true)); - run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, false)); - run_test(context, |a| subslice_pattern_reassign(a)); + run_test!(context, |a| subslice_pattern_from_end_with_drop(a, true, true)); + run_test!(context, |a| subslice_pattern_from_end_with_drop(a, true, false)); + run_test!(context, |a| subslice_pattern_from_end_with_drop(a, false, true)); + run_test!(context, |a| subslice_pattern_from_end_with_drop(a, false, false)); + run_test!(context, |a| subslice_pattern_reassign(a)); + + run_test!(context, |a| panic_after_return(a, false)); + run_test!(context, |a| panic_after_return(a, true)); + run_test!(context, |a| panic_after_init_by_loop(a)); + run_test!(context, |a| panic_after_init_by_match_with_bindings_and_guard(a, false)); + run_test!(context, |a| panic_after_init_by_match_with_bindings_and_guard(a, true)); } diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 8516bc3d9642..6f9112ae0060 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -17,6 +17,7 @@ struct InjectedFailure; struct Allocator { data: RefCell>, + name: &'static str, failing_op: usize, cur_ops: Cell, } @@ -28,17 +29,18 @@ impl Drop for Allocator { fn drop(&mut self) { let data = self.data.borrow(); if data.iter().any(|d| *d) { - panic!("missing free: {:?}", data); + panic!("missing free in {:?}: {:?}", self.name, data); } } } impl Allocator { - fn new(failing_op: usize) -> Self { + fn new(failing_op: usize, name: &'static str) -> Self { Allocator { failing_op: failing_op, cur_ops: Cell::new(0), - data: RefCell::new(vec![]) + data: RefCell::new(vec![]), + name, } } fn alloc(&self) -> Ptr<'_> { @@ -53,20 +55,6 @@ impl Allocator { data.push(true); Ptr(addr, self) } - // FIXME(#47949) Any use of this indicates a bug in rustc: we should never - // be leaking values in the cases here. - // - // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the - // `failing_op` is in the list of exception. - fn alloc_leaked(&self, exceptions: Vec) -> Ptr<'_> { - let ptr = self.alloc(); - - if exceptions.iter().any(|operation| *operation == self.failing_op) { - let mut data = self.data.borrow_mut(); - data[ptr.0] = false; - } - ptr - } } struct Ptr<'a>(usize, &'a Allocator); @@ -74,7 +62,7 @@ impl<'a> Drop for Ptr<'a> { fn drop(&mut self) { match self.1.data.borrow_mut()[self.0] { false => { - panic!("double free at index {:?}", self.0) + panic!("double free in {:?} at index {:?}", self.1.name, self.0) } ref mut d => *d = false } @@ -270,79 +258,148 @@ fn subslice_pattern_reassign(a: &Allocator) { } fn panic_after_return(a: &Allocator) -> Ptr<'_> { - // Panic in the drop of `p` or `q` can leak - let exceptions = vec![8, 9]; a.alloc(); let p = a.alloc(); { a.alloc(); let p = a.alloc(); - // FIXME (#47949) We leak values when we panic in a destructor after - // evaluating an expression with `rustc_mir::build::Builder::into`. - a.alloc_leaked(exceptions) + a.alloc() } } fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> { - // Panic in the drop of `p` or `q` can leak - let exceptions = vec![8, 9]; a.alloc(); let p = a.alloc(); { a.alloc(); let q = a.alloc(); - // FIXME (#47949) - return a.alloc_leaked(exceptions); + return a.alloc(); } } fn panic_after_init(a: &Allocator) { - // Panic in the drop of `r` can leak - let exceptions = vec![8]; a.alloc(); let p = a.alloc(); let q = { a.alloc(); let r = a.alloc(); - // FIXME (#47949) - a.alloc_leaked(exceptions) + a.alloc() }; } fn panic_after_init_temp(a: &Allocator) { - // Panic in the drop of `r` can leak - let exceptions = vec![8]; a.alloc(); let p = a.alloc(); { a.alloc(); let r = a.alloc(); - // FIXME (#47949) - a.alloc_leaked(exceptions) + a.alloc() }; } fn panic_after_init_by_loop(a: &Allocator) { - // Panic in the drop of `r` can leak - let exceptions = vec![8]; a.alloc(); let p = a.alloc(); let q = loop { a.alloc(); let r = a.alloc(); - // FIXME (#47949) - break a.alloc_leaked(exceptions); + break a.alloc(); }; } -fn run_test(mut f: F) +fn panic_after_init_by_match(a: &Allocator, b: bool) { + a.alloc(); + let p = a.alloc(); + loop { + let q = match b { + true => { + a.alloc(); + let r = a.alloc(); + a.alloc() + } + false => { + a.alloc(); + let r = a.alloc(); + break a.alloc(); + } + }; + return; + }; +} + +fn panic_after_init_by_match_with_guard(a: &Allocator, b: bool) { + a.alloc(); + let p = a.alloc(); + let q = match a.alloc() { + _ if b => { + a.alloc(); + let r = a.alloc(); + a.alloc() + } + _ => { + a.alloc(); + let r = a.alloc(); + a.alloc() + }, + }; +} + +fn panic_after_init_by_match_with_bindings_and_guard(a: &Allocator, b: bool) { + a.alloc(); + let p = a.alloc(); + let q = match a.alloc() { + _x if b => { + a.alloc(); + let r = a.alloc(); + a.alloc() + } + _x => { + a.alloc(); + let r = a.alloc(); + a.alloc() + }, + }; +} + +fn panic_after_init_by_match_with_ref_bindings_and_guard(a: &Allocator, b: bool) { + a.alloc(); + let p = a.alloc(); + let q = match a.alloc() { + ref _x if b => { + a.alloc(); + let r = a.alloc(); + a.alloc() + } + ref _x => { + a.alloc(); + let r = a.alloc(); + a.alloc() + }, + }; +} + +fn panic_after_init_by_break_if(a: &Allocator, b: bool) { + a.alloc(); + let p = a.alloc(); + let q = loop { + let r = a.alloc(); + break if b { + let s = a.alloc(); + a.alloc() + } else { + a.alloc() + }; + }; +} + +fn run_test(mut f: F, name: &'static str) where F: FnMut(&Allocator) { - let first_alloc = Allocator::new(usize::MAX); + let first_alloc = Allocator::new(usize::MAX, name); f(&first_alloc); for failing_op in 1..first_alloc.cur_ops.get()+1 { - let alloc = Allocator::new(failing_op); + let alloc = Allocator::new(failing_op, name); let alloc = &alloc; let f = panic::AssertUnwindSafe(&mut f); let result = panic::catch_unwind(move || { @@ -360,77 +417,91 @@ fn run_test(mut f: F) } } -fn run_test_nopanic(mut f: F) +fn run_test_nopanic(mut f: F, name: &'static str) where F: FnMut(&Allocator) { - let first_alloc = Allocator::new(usize::MAX); + let first_alloc = Allocator::new(usize::MAX, name); f(&first_alloc); } +macro_rules! run_test { + ($e:expr) => { run_test($e, stringify!($e)); } +} + fn main() { - run_test(|a| dynamic_init(a, false)); - run_test(|a| dynamic_init(a, true)); - run_test(|a| dynamic_drop(a, false)); - run_test(|a| dynamic_drop(a, true)); + run_test!(|a| dynamic_init(a, false)); + run_test!(|a| dynamic_init(a, true)); + run_test!(|a| dynamic_drop(a, false)); + run_test!(|a| dynamic_drop(a, true)); - run_test(|a| assignment2(a, false, false)); - run_test(|a| assignment2(a, false, true)); - run_test(|a| assignment2(a, true, false)); - run_test(|a| assignment2(a, true, true)); + run_test!(|a| assignment2(a, false, false)); + run_test!(|a| assignment2(a, false, true)); + run_test!(|a| assignment2(a, true, false)); + run_test!(|a| assignment2(a, true, true)); - run_test(|a| assignment1(a, false)); - run_test(|a| assignment1(a, true)); + run_test!(|a| assignment1(a, false)); + run_test!(|a| assignment1(a, true)); - run_test(|a| array_simple(a)); - run_test(|a| vec_simple(a)); - run_test(|a| vec_unreachable(a)); + run_test!(|a| array_simple(a)); + run_test!(|a| vec_simple(a)); + run_test!(|a| vec_unreachable(a)); - run_test(|a| struct_dynamic_drop(a, false, false, false)); - run_test(|a| struct_dynamic_drop(a, false, false, true)); - run_test(|a| struct_dynamic_drop(a, false, true, false)); - run_test(|a| struct_dynamic_drop(a, false, true, true)); - run_test(|a| struct_dynamic_drop(a, true, false, false)); - run_test(|a| struct_dynamic_drop(a, true, false, true)); - run_test(|a| struct_dynamic_drop(a, true, true, false)); - run_test(|a| struct_dynamic_drop(a, true, true, true)); + run_test!(|a| struct_dynamic_drop(a, false, false, false)); + run_test!(|a| struct_dynamic_drop(a, false, false, true)); + run_test!(|a| struct_dynamic_drop(a, false, true, false)); + run_test!(|a| struct_dynamic_drop(a, false, true, true)); + run_test!(|a| struct_dynamic_drop(a, true, false, false)); + run_test!(|a| struct_dynamic_drop(a, true, false, true)); + run_test!(|a| struct_dynamic_drop(a, true, true, false)); + run_test!(|a| struct_dynamic_drop(a, true, true, true)); - run_test(|a| field_assignment(a, false)); - run_test(|a| field_assignment(a, true)); + run_test!(|a| field_assignment(a, false)); + run_test!(|a| field_assignment(a, true)); - run_test(|a| generator(a, 0)); - run_test(|a| generator(a, 1)); - run_test(|a| generator(a, 2)); - run_test(|a| generator(a, 3)); + run_test!(|a| generator(a, 0)); + run_test!(|a| generator(a, 1)); + run_test!(|a| generator(a, 2)); + run_test!(|a| generator(a, 3)); - run_test(|a| mixed_drop_and_nondrop(a)); + run_test!(|a| mixed_drop_and_nondrop(a)); - run_test(|a| slice_pattern_first(a)); - run_test(|a| slice_pattern_middle(a)); - run_test(|a| slice_pattern_two(a)); - run_test(|a| slice_pattern_last(a)); - run_test(|a| slice_pattern_one_of(a, 0)); - run_test(|a| slice_pattern_one_of(a, 1)); - run_test(|a| slice_pattern_one_of(a, 2)); - run_test(|a| slice_pattern_one_of(a, 3)); + run_test!(|a| slice_pattern_first(a)); + run_test!(|a| slice_pattern_middle(a)); + run_test!(|a| slice_pattern_two(a)); + run_test!(|a| slice_pattern_last(a)); + run_test!(|a| slice_pattern_one_of(a, 0)); + run_test!(|a| slice_pattern_one_of(a, 1)); + run_test!(|a| slice_pattern_one_of(a, 2)); + run_test!(|a| slice_pattern_one_of(a, 3)); - run_test(|a| subslice_pattern_from_end(a, true)); - run_test(|a| subslice_pattern_from_end(a, false)); - run_test(|a| subslice_pattern_from_end_with_drop(a, true, true)); - run_test(|a| subslice_pattern_from_end_with_drop(a, true, false)); - run_test(|a| subslice_pattern_from_end_with_drop(a, false, true)); - run_test(|a| subslice_pattern_from_end_with_drop(a, false, false)); - run_test(|a| slice_pattern_reassign(a)); - run_test(|a| subslice_pattern_reassign(a)); + run_test!(|a| subslice_pattern_from_end(a, true)); + run_test!(|a| subslice_pattern_from_end(a, false)); + run_test!(|a| subslice_pattern_from_end_with_drop(a, true, true)); + run_test!(|a| subslice_pattern_from_end_with_drop(a, true, false)); + run_test!(|a| subslice_pattern_from_end_with_drop(a, false, true)); + run_test!(|a| subslice_pattern_from_end_with_drop(a, false, false)); + run_test!(|a| slice_pattern_reassign(a)); + run_test!(|a| subslice_pattern_reassign(a)); - run_test(|a| { + run_test!(|a| { panic_after_return(a); }); - run_test(|a| { + run_test!(|a| { panic_after_return_expr(a); }); - run_test(|a| panic_after_init(a)); - run_test(|a| panic_after_init_temp(a)); - run_test(|a| panic_after_init_by_loop(a)); + run_test!(|a| panic_after_init(a)); + run_test!(|a| panic_after_init_temp(a)); + run_test!(|a| panic_after_init_by_loop(a)); + run_test!(|a| panic_after_init_by_match(a, false)); + run_test!(|a| panic_after_init_by_match(a, true)); + run_test!(|a| panic_after_init_by_match_with_guard(a, false)); + run_test!(|a| panic_after_init_by_match_with_guard(a, true)); + run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, false)); + run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, true)); + run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, false)); + run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, true)); + run_test!(|a| panic_after_init_by_break_if(a, false)); + run_test!(|a| panic_after_init_by_break_if(a, true)); - run_test_nopanic(|a| union1(a)); + run_test_nopanic(|a| union1(a), "|a| union1(a)"); } From c5f80aa50874ab814e1ece15bc324de351ea28fc Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 4 Oct 2019 18:10:19 -0300 Subject: [PATCH 077/545] Remove unneeded visit_statement definition visit_statement default definition does just this, there's no need to redefine it. --- src/librustc_mir/transform/erase_regions.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 21ca339eb968..38a04ce8f381 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -39,12 +39,6 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) { *substs = self.tcx.erase_regions(substs); } - - fn visit_statement(&mut self, - statement: &mut Statement<'tcx>, - location: Location) { - self.super_statement(statement, location); - } } pub struct EraseRegions; From 8bb5c12c0b6bc305cdd83941679ca95c9dc109b6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 4 Oct 2019 16:53:18 -0700 Subject: [PATCH 078/545] Update the documented default of -Z mutable-noalias It has been fully disabled by default since #54639. --- 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 2771ce69b9e0..b48353e73308 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1345,7 +1345,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, mir_opt_level: usize = (1, parse_uint, [TRACKED], "set the MIR optimization level (0-3, default: 1)"), mutable_noalias: Option = (None, parse_opt_bool, [TRACKED], - "emit noalias metadata for mutable references (default: yes on LLVM >= 6)"), + "emit noalias metadata for mutable references (default: no)"), dump_mir: Option = (None, parse_opt_string, [UNTRACKED], "dump MIR state to file. `val` is used to select which passes and functions to dump. For example: From 4414068cc49803b0dacba133b7788b8b95b0b473 Mon Sep 17 00:00:00 2001 From: AnthonyMikh Date: Sat, 5 Oct 2019 03:08:05 +0300 Subject: [PATCH 079/545] Correctly estimate required space for string `.len()` returns length in bytes so it overestimates the required space --- src/librustc_errors/styled_buffer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_errors/styled_buffer.rs b/src/librustc_errors/styled_buffer.rs index 6e03618d2b0b..b12ab9e45760 100644 --- a/src/librustc_errors/styled_buffer.rs +++ b/src/librustc_errors/styled_buffer.rs @@ -111,7 +111,7 @@ impl StyledBuffer { pub fn prepend(&mut self, line: usize, string: &str, style: Style) { self.ensure_lines(line); - let string_len = string.len(); + let string_len = string.chars().count(); // Push the old content over to make room for new content for _ in 0..string_len { From 5f94a53d1a4e03787886b8bca750566d80255f85 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 5 Oct 2019 04:34:26 +0200 Subject: [PATCH 080/545] Account for macro invocation in `let mut $pat` diagnostic. --- src/libsyntax/parse/parser/pat.rs | 6 ++- .../issue-65122-mac-invoc-in-mut-patterns.rs | 26 +++++++++++ ...sue-65122-mac-invoc-in-mut-patterns.stderr | 45 +++++++++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs create mode 100644 src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 7eb2a73a11a8..48f9e3016103 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -4,7 +4,7 @@ use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use crate::ptr::P; use crate::ast::{self, Attribute, Pat, PatKind, FieldPat, RangeEnd, RangeSyntax, Mac}; use crate::ast::{BindingMode, Ident, Mutability, Path, QSelf, Expr, ExprKind}; -use crate::mut_visit::{noop_visit_pat, MutVisitor}; +use crate::mut_visit::{noop_visit_pat, noop_visit_mac, MutVisitor}; use crate::parse::token::{self}; use crate::print::pprust; use crate::source_map::{respan, Span, Spanned}; @@ -481,6 +481,10 @@ impl<'a> Parser<'a> { fn make_all_value_bindings_mutable(pat: &mut P) -> bool { struct AddMut(bool); impl MutVisitor for AddMut { + fn visit_mac(&mut self, mac: &mut Mac) { + noop_visit_mac(mac, self); + } + fn visit_pat(&mut self, pat: &mut P) { if let PatKind::Ident(BindingMode::ByValue(ref mut m @ Mutability::Immutable), ..) = pat.kind diff --git a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs new file mode 100644 index 000000000000..97a405b6999c --- /dev/null +++ b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.rs @@ -0,0 +1,26 @@ +// Regression test; used to ICE with 'visit_mac disabled by default' due to a +// `MutVisitor` in `fn make_all_value_bindings_mutable` (`parse/parser/pat.rs`). + +macro_rules! mac1 { + ($eval:expr) => { + let mut $eval = (); + //~^ ERROR `mut` must be followed by a named binding + }; +} + +macro_rules! mac2 { + ($eval:pat) => { + let mut $eval = (); + //~^ ERROR `mut` must be followed by a named binding + //~| ERROR expected identifier, found `does_not_exist!()` + }; +} + +fn foo() { + mac1! { does_not_exist!() } + //~^ ERROR cannot find macro `does_not_exist` in this scope + mac2! { does_not_exist!() } + //~^ ERROR cannot find macro `does_not_exist` in this scope +} + +fn main() {} diff --git a/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr new file mode 100644 index 000000000000..dd193d6a86eb --- /dev/null +++ b/src/test/ui/parser/issue-65122-mac-invoc-in-mut-patterns.stderr @@ -0,0 +1,45 @@ +error: `mut` must be followed by a named binding + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:6:13 + | +LL | let mut $eval = (); + | ^^^^^^^^^ help: remove the `mut` prefix: `does_not_exist!()` +... +LL | mac1! { does_not_exist!() } + | --------------------------- in this macro invocation + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: expected identifier, found `does_not_exist!()` + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:17 + | +LL | let mut $eval = (); + | ^^^^^ expected identifier +... +LL | mac2! { does_not_exist!() } + | --------------------------- in this macro invocation + +error: `mut` must be followed by a named binding + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:13 + | +LL | let mut $eval = (); + | ^^^ help: remove the `mut` prefix: `does_not_exist!()` +... +LL | mac2! { does_not_exist!() } + | --------------------------- in this macro invocation + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: cannot find macro `does_not_exist` in this scope + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:20:13 + | +LL | mac1! { does_not_exist!() } + | ^^^^^^^^^^^^^^ + +error: cannot find macro `does_not_exist` in this scope + --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:22:13 + | +LL | mac2! { does_not_exist!() } + | ^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + From 173958ac80056416fd1905c1a07cd1b9faca82d5 Mon Sep 17 00:00:00 2001 From: memoryruins Date: Sat, 5 Oct 2019 03:48:14 -0400 Subject: [PATCH 081/545] Replaces some instances of `as *[const | mut] _` with `.cast()` --- src/librustc_codegen_llvm/allocator.rs | 4 ++-- src/librustc_codegen_llvm/back/lto.rs | 6 +++--- src/librustc_codegen_llvm/back/write.rs | 14 +++++++------- src/librustc_codegen_llvm/consts.rs | 6 +++--- src/librustc_codegen_llvm/context.rs | 2 +- src/librustc_codegen_llvm/debuginfo/gdb.rs | 4 ++-- src/librustc_codegen_llvm/debuginfo/metadata.rs | 6 +++--- src/librustc_codegen_llvm/debuginfo/mod.rs | 6 +++--- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index 5d43bf6ae28b..f31765cea4f1 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -68,7 +68,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, - "entry\0".as_ptr() as *const _); + "entry\0".as_ptr().cast()); let llbuilder = llvm::LLVMCreateBuilderInContext(llcx); llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb); @@ -80,7 +80,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc args.as_ptr(), args.len() as c_uint, None, - "\0".as_ptr() as *const _); + "\0".as_ptr().cast()); llvm::LLVMSetTailCall(ret, True); if output.is_some() { llvm::LLVMBuildRet(llbuilder, ret); diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index c4368d2cb8b4..e49c64923aa6 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -546,7 +546,7 @@ pub(crate) fn run_pass_manager(cgcx: &CodegenContext, llvm::LLVMRustAddAnalysisPasses(module.module_llvm.tm, pm, module.module_llvm.llmod()); if config.verify_llvm_ir { - let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); + let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast()); llvm::LLVMRustAddPass(pm, pass.unwrap()); } @@ -581,12 +581,12 @@ pub(crate) fn run_pass_manager(cgcx: &CodegenContext, // We always generate bitcode through ThinLTOBuffers, // which do not support anonymous globals if config.bitcode_needed() { - let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr() as *const _); + let pass = llvm::LLVMRustFindAndCreatePass("name-anon-globals\0".as_ptr().cast()); llvm::LLVMRustAddPass(pm, pass.unwrap()); } if config.verify_llvm_ir { - let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr() as *const _); + let pass = llvm::LLVMRustFindAndCreatePass("verify\0".as_ptr().cast()); llvm::LLVMRustAddPass(pm, pass.unwrap()); } diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 78db90b57b53..b1a9552d56fb 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -221,8 +221,8 @@ impl<'a> DiagnosticHandlers<'a> { llcx: &'a llvm::Context) -> Self { let data = Box::into_raw(Box::new((cgcx, handler))); unsafe { - llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data as *mut _); - llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data as *mut _); + llvm::LLVMRustSetInlineAsmDiagnosticHandler(llcx, inline_asm_handler, data.cast()); + llvm::LLVMContextSetDiagnosticHandler(llcx, diagnostic_handler, data.cast()); } DiagnosticHandlers { data, llcx } } @@ -672,7 +672,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - "rustc.embedded.module\0".as_ptr() as *const _, + "rustc.embedded.module\0".as_ptr().cast(), ); llvm::LLVMSetInitializer(llglobal, llconst); @@ -684,7 +684,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, } else { ".llvmbc\0" }; - llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _); + llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); llvm::LLVMSetGlobalConstant(llglobal, llvm::True); @@ -692,7 +692,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, let llglobal = llvm::LLVMAddGlobal( llmod, common::val_ty(llconst), - "rustc.embedded.cmdline\0".as_ptr() as *const _, + "rustc.embedded.cmdline\0".as_ptr().cast(), ); llvm::LLVMSetInitializer(llglobal, llconst); let section = if is_apple { @@ -700,7 +700,7 @@ unsafe fn embed_bitcode(cgcx: &CodegenContext, } else { ".llvmcmd\0" }; - llvm::LLVMSetSection(llglobal, section.as_ptr() as *const _); + llvm::LLVMSetSection(llglobal, section.as_ptr().cast()); llvm::LLVMRustSetLinkage(llglobal, llvm::Linkage::PrivateLinkage); } @@ -842,7 +842,7 @@ fn create_msvc_imps( for (imp_name, val) in globals { let imp = llvm::LLVMAddGlobal(llmod, i8p_ty, - imp_name.as_ptr() as *const _); + imp_name.as_ptr().cast()); llvm::LLVMSetInitializer(imp, consts::ptrcast(val, i8p_ty)); llvm::LLVMRustSetLinkage(imp, llvm::Linkage::ExternalLinkage); } diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index cba5ee3260c1..d4df5b4a804e 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -488,7 +488,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { if let Some(section) = attrs.link_section { let section = llvm::LLVMMDStringInContext( self.llcx, - section.as_str().as_ptr() as *const _, + section.as_str().as_ptr().cast(), section.as_str().len() as c_uint, ); assert!(alloc.relocations().is_empty()); @@ -500,14 +500,14 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> { 0..alloc.len()); let alloc = llvm::LLVMMDStringInContext( self.llcx, - bytes.as_ptr() as *const _, + bytes.as_ptr().cast(), bytes.len() as c_uint, ); let data = [section, alloc]; let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2); llvm::LLVMAddNamedMetadataOperand( self.llmod, - "wasm.custom_sections\0".as_ptr() as *const _, + "wasm.custom_sections\0".as_ptr().cast(), meta, ); } diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 58ce97039099..18a5970fcd04 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -211,7 +211,7 @@ pub unsafe fn create_module( // If skipping the PLT is enabled, we need to add some module metadata // to ensure intrinsic calls don't use it. if !sess.needs_plt() { - let avoid_plt = "RtLibUseGOT\0".as_ptr() as *const _; + let avoid_plt = "RtLibUseGOT\0".as_ptr().cast(); llvm::LLVMRustAddModuleFlag(llmod, avoid_plt, 1); } diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 04c9e93c7a52..9ed1c1730a69 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -37,7 +37,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) let section_var = unsafe { llvm::LLVMGetNamedGlobal(cx.llmod, - c_section_var_name.as_ptr() as *const _) + c_section_var_name.as_ptr().cast()) }; section_var.unwrap_or_else(|| { @@ -52,7 +52,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(cx: &CodegenCx<'ll, '_>) llvm_type).unwrap_or_else(||{ bug!("symbol `{}` is already defined", section_var_name) }); - llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _); + llvm::LLVMSetSection(section_var, section_name.as_ptr().cast()); llvm::LLVMSetInitializer(section_var, cx.const_bytes(section_contents)); llvm::LLVMSetGlobalConstant(section_var, llvm::True); llvm::LLVMSetUnnamedAddr(section_var, llvm::True); diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 544d6794e219..c25622392068 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -960,9 +960,9 @@ pub fn compile_unit_metadata( file_metadata, producer.as_ptr(), tcx.sess.opts.optimize != config::OptLevel::No, - flags.as_ptr() as *const _, + flags.as_ptr().cast(), 0, - split_name.as_ptr() as *const _, + split_name.as_ptr().cast(), kind); if tcx.sess.opts.debugging_opts.profile { @@ -991,7 +991,7 @@ pub fn compile_unit_metadata( if tcx.sess.opts.target_triple.triple().starts_with("wasm32") { let name_metadata = llvm::LLVMMDStringInContext( debug_context.llcontext, - rustc_producer.as_ptr() as *const _, + rustc_producer.as_ptr().cast(), rustc_producer.as_bytes().len() as c_uint, ); llvm::LLVMAddNamedMetadataOperand( diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index e0e0cd5f739e..6e4ed42c45e9 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -127,20 +127,20 @@ pub fn finalize(cx: &CodegenCx<'_, '_>) { if cx.sess().target.target.options.is_like_osx || cx.sess().target.target.options.is_like_android { llvm::LLVMRustAddModuleFlag(cx.llmod, - "Dwarf Version\0".as_ptr() as *const _, + "Dwarf Version\0".as_ptr().cast(), 2) } // Indicate that we want CodeView debug information on MSVC if cx.sess().target.target.options.is_like_msvc { llvm::LLVMRustAddModuleFlag(cx.llmod, - "CodeView\0".as_ptr() as *const _, + "CodeView\0".as_ptr().cast(), 1) } // Prevent bitcode readers from deleting the debug info. let ptr = "Debug Info Version\0".as_ptr(); - llvm::LLVMRustAddModuleFlag(cx.llmod, ptr as *const _, + llvm::LLVMRustAddModuleFlag(cx.llmod, ptr.cast(), llvm::LLVMRustDebugMetadataVersion()); }; } From 318ff305ea2a39e2ddab5d83a9363fd041b9aea4 Mon Sep 17 00:00:00 2001 From: BO41 Date: Sat, 5 Oct 2019 12:23:10 +0200 Subject: [PATCH 082/545] Fix typo on `now()` comments --- src/libstd/time.rs | 51 +++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/src/libstd/time.rs b/src/libstd/time.rs index 3bf2b8be1fe8..e1ae01b602a8 100644 --- a/src/libstd/time.rs +++ b/src/libstd/time.rs @@ -15,10 +15,10 @@ use crate::cmp; use crate::error::Error; use crate::fmt; -use crate::ops::{Add, Sub, AddAssign, SubAssign}; +use crate::ops::{Add, AddAssign, Sub, SubAssign}; use crate::sys::time; -use crate::sys_common::FromInner; use crate::sys_common::mutex::Mutex; +use crate::sys_common::FromInner; #[stable(feature = "time", since = "1.3.0")] pub use core::time::Duration; @@ -216,17 +216,17 @@ impl Instant { // * https://bugzilla.mozilla.org/show_bug.cgi?id=1487778 - a similar // Firefox bug // - // It simply seems that this it just happens so that a lot in the wild - // we're seeing panics across various platforms where consecutive calls + // It seems that this just happens a lot in the wild. + // We're seeing panics across various platforms where consecutive calls // to `Instant::now`, such as via the `elapsed` function, are panicking // as they're going backwards. Placed here is a last-ditch effort to try // to fix things up. We keep a global "latest now" instance which is // returned instead of what the OS says if the OS goes backwards. // - // To hopefully mitigate the impact of this though a few platforms are + // To hopefully mitigate the impact of this, a few platforms are // whitelisted as "these at least haven't gone backwards yet". if time::Instant::actually_monotonic() { - return Instant(os_now) + return Instant(os_now); } static LOCK: Mutex = Mutex::new(); @@ -353,8 +353,7 @@ impl Add for Instant { /// /// [`checked_add`]: ../../std/time/struct.Instant.html#method.checked_add fn add(self, other: Duration) -> Instant { - self.checked_add(other) - .expect("overflow when adding duration to instant") + self.checked_add(other).expect("overflow when adding duration to instant") } } @@ -370,8 +369,7 @@ impl Sub for Instant { type Output = Instant; fn sub(self, other: Duration) -> Instant { - self.checked_sub(other) - .expect("overflow when subtracting duration from instant") + self.checked_sub(other).expect("overflow when subtracting duration from instant") } } @@ -464,8 +462,7 @@ impl SystemTime { /// println!("{:?}", difference); /// ``` #[stable(feature = "time2", since = "1.8.0")] - pub fn duration_since(&self, earlier: SystemTime) - -> Result { + pub fn duration_since(&self, earlier: SystemTime) -> Result { self.0.sub_time(&earlier.0).map_err(SystemTimeError) } @@ -532,8 +529,7 @@ impl Add for SystemTime { /// /// [`checked_add`]: ../../std/time/struct.SystemTime.html#method.checked_add fn add(self, dur: Duration) -> SystemTime { - self.checked_add(dur) - .expect("overflow when adding duration to instant") + self.checked_add(dur).expect("overflow when adding duration to instant") } } @@ -549,8 +545,7 @@ impl Sub for SystemTime { type Output = SystemTime; fn sub(self, dur: Duration) -> SystemTime { - self.checked_sub(dur) - .expect("overflow when subtracting duration from instant") + self.checked_sub(dur).expect("overflow when subtracting duration from instant") } } @@ -626,7 +621,9 @@ impl SystemTimeError { #[stable(feature = "time2", since = "1.8.0")] impl Error for SystemTimeError { - fn description(&self) -> &str { "other time was not earlier than self" } + fn description(&self) -> &str { + "other time was not earlier than self" + } } #[stable(feature = "time2", since = "1.8.0")] @@ -644,17 +641,16 @@ impl FromInner for SystemTime { #[cfg(test)] mod tests { - use super::{Instant, SystemTime, Duration, UNIX_EPOCH}; + use super::{Duration, Instant, SystemTime, UNIX_EPOCH}; macro_rules! assert_almost_eq { - ($a:expr, $b:expr) => ({ + ($a:expr, $b:expr) => {{ let (a, b) = ($a, $b); if a != b { - let (a, b) = if a > b {(a, b)} else {(b, a)}; - assert!(a - Duration::new(0, 1000) <= b, - "{:?} is not almost equal to {:?}", a, b); + let (a, b) = if a > b { (a, b) } else { (b, a) }; + assert!(a - Duration::new(0, 1000) <= b, "{:?} is not almost equal to {:?}", a, b); } - }) + }}; } #[test] @@ -729,7 +725,7 @@ mod tests { fn instant_saturating_duration_since_nopanic() { let a = Instant::now(); let ret = (a - Duration::new(1, 0)).saturating_duration_since(a); - assert_eq!(ret, Duration::new(0,0)); + assert_eq!(ret, Duration::new(0, 0)); } #[test] @@ -755,15 +751,14 @@ mod tests { let second = Duration::new(1, 0); assert_almost_eq!(a.duration_since(a - second).unwrap(), second); - assert_almost_eq!(a.duration_since(a + second).unwrap_err() - .duration(), second); + assert_almost_eq!(a.duration_since(a + second).unwrap_err().duration(), second); assert_almost_eq!(a - second + second, a); assert_almost_eq!(a.checked_sub(second).unwrap().checked_add(second).unwrap(), a); let one_second_from_epoch = UNIX_EPOCH + Duration::new(1, 0); - let one_second_from_epoch2 = UNIX_EPOCH + Duration::new(0, 500_000_000) - + Duration::new(0, 500_000_000); + let one_second_from_epoch2 = + UNIX_EPOCH + Duration::new(0, 500_000_000) + Duration::new(0, 500_000_000); assert_eq!(one_second_from_epoch, one_second_from_epoch2); // checked_add_duration will not panic on overflow From 080aa8663550c221221123a87f7c56bd1b7dc564 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 5 Oct 2019 14:06:51 +0100 Subject: [PATCH 083/545] lint: extern non-exhaustive types are improper This commit makes the `improper_ctype` lint trigger for non-exhaustive types when those types aren't defined in the current crate. Signed-off-by: David Wood --- src/librustc_lint/types.rs | 27 +++++++++++ .../improper_ctypes/auxiliary/types.rs | 31 ++++++++++++ .../improper_ctypes/extern_crate_improper.rs | 24 ++++++++++ .../extern_crate_improper.stderr | 47 +++++++++++++++++++ .../improper_ctypes/same_crate_proper.rs | 46 ++++++++++++++++++ 5 files changed, 175 insertions(+) create mode 100644 src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs create mode 100644 src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr create mode 100644 src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 3d14a78c33f7..aa6dfa50dddf 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -631,6 +631,16 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { }; } + let is_non_exhaustive = + def.non_enum_variant().is_field_list_non_exhaustive(); + if is_non_exhaustive && !def.did.is_local() { + return FfiUnsafe { + ty, + reason: "this struct is non-exhaustive", + help: None, + }; + } + if def.non_enum_variant().fields.is_empty() { return FfiUnsafe { ty, @@ -730,8 +740,25 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } } + if def.is_variant_list_non_exhaustive() && !def.did.is_local() { + return FfiUnsafe { + ty, + reason: "this enum is non-exhaustive", + help: None, + }; + } + // Check the contained variants. for variant in &def.variants { + let is_non_exhaustive = variant.is_field_list_non_exhaustive(); + if is_non_exhaustive && !variant.def_id.is_local() { + return FfiUnsafe { + ty, + reason: "this enum has non-exhaustive variants", + help: None, + }; + } + for field in &variant.fields { let field_ty = cx.normalize_erasing_regions( ParamEnv::reveal_all(), diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs new file mode 100644 index 000000000000..1a187d042517 --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/auxiliary/types.rs @@ -0,0 +1,31 @@ +#![feature(non_exhaustive)] + +#[non_exhaustive] +#[repr(C)] +pub enum NonExhaustiveEnum { + Unit, + Tuple(u32), + Struct { field: u32 } +} + +#[non_exhaustive] +#[repr(C)] +pub struct NormalStruct { + pub first_field: u16, + pub second_field: u16, +} + +#[non_exhaustive] +#[repr(C)] +pub struct UnitStruct; + +#[non_exhaustive] +#[repr(C)] +pub struct TupleStruct (pub u16, pub u16); + +#[repr(C)] +pub enum NonExhaustiveVariants { + #[non_exhaustive] Unit, + #[non_exhaustive] Tuple(u32), + #[non_exhaustive] Struct { field: u32 } +} diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs new file mode 100644 index 000000000000..900b9333f76e --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.rs @@ -0,0 +1,24 @@ +// aux-build:types.rs +#![deny(improper_ctypes)] + +extern crate types; + +// This test checks that non-exhaustive types with `#[repr(C)]` from an extern crate are considered +// improper. + +use types::{NonExhaustiveEnum, NormalStruct, UnitStruct, TupleStruct, NonExhaustiveVariants}; + +extern { + pub fn non_exhaustive_enum(_: NonExhaustiveEnum); + //~^ ERROR `extern` block uses type `types::NonExhaustiveEnum`, which is not FFI-safe + pub fn non_exhaustive_normal_struct(_: NormalStruct); + //~^ ERROR `extern` block uses type `types::NormalStruct`, which is not FFI-safe + pub fn non_exhaustive_unit_struct(_: UnitStruct); + //~^ ERROR `extern` block uses type `types::UnitStruct`, which is not FFI-safe + pub fn non_exhaustive_tuple_struct(_: TupleStruct); + //~^ ERROR `extern` block uses type `types::TupleStruct`, which is not FFI-safe + pub fn non_exhaustive_variant(_: NonExhaustiveVariants); + //~^ ERROR `extern` block uses type `types::NonExhaustiveVariants`, which is not FFI-safe +} + +fn main() { } diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr new file mode 100644 index 000000000000..7fbf1157e56f --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/extern_crate_improper.stderr @@ -0,0 +1,47 @@ +error: `extern` block uses type `types::NonExhaustiveEnum`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:12:35 + | +LL | pub fn non_exhaustive_enum(_: NonExhaustiveEnum); + | ^^^^^^^^^^^^^^^^^ not FFI-safe + | +note: lint level defined here + --> $DIR/extern_crate_improper.rs:2:9 + | +LL | #![deny(improper_ctypes)] + | ^^^^^^^^^^^^^^^ + = note: this enum is non-exhaustive + +error: `extern` block uses type `types::NormalStruct`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:14:44 + | +LL | pub fn non_exhaustive_normal_struct(_: NormalStruct); + | ^^^^^^^^^^^^ not FFI-safe + | + = note: this struct is non-exhaustive + +error: `extern` block uses type `types::UnitStruct`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:16:42 + | +LL | pub fn non_exhaustive_unit_struct(_: UnitStruct); + | ^^^^^^^^^^ not FFI-safe + | + = note: this struct is non-exhaustive + +error: `extern` block uses type `types::TupleStruct`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:18:43 + | +LL | pub fn non_exhaustive_tuple_struct(_: TupleStruct); + | ^^^^^^^^^^^ not FFI-safe + | + = note: this struct is non-exhaustive + +error: `extern` block uses type `types::NonExhaustiveVariants`, which is not FFI-safe + --> $DIR/extern_crate_improper.rs:20:38 + | +LL | pub fn non_exhaustive_variant(_: NonExhaustiveVariants); + | ^^^^^^^^^^^^^^^^^^^^^ not FFI-safe + | + = note: this enum has non-exhaustive variants + +error: aborting due to 5 previous errors + diff --git a/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs new file mode 100644 index 000000000000..3f38e3cd8e5a --- /dev/null +++ b/src/test/ui/rfc-2008-non-exhaustive/improper_ctypes/same_crate_proper.rs @@ -0,0 +1,46 @@ +// check-pass +#![feature(non_exhaustive)] +#![deny(improper_ctypes)] + +// This test checks that non-exhaustive types with `#[repr(C)]` are considered proper within +// the defining crate. + +#[non_exhaustive] +#[repr(C)] +pub enum NonExhaustiveEnum { + Unit, + Tuple(u32), + Struct { field: u32 } +} + +#[non_exhaustive] +#[repr(C)] +pub struct NormalStruct { + pub first_field: u16, + pub second_field: u16, +} + +#[non_exhaustive] +#[repr(C)] +pub struct UnitStruct; + +#[non_exhaustive] +#[repr(C)] +pub struct TupleStruct (pub u16, pub u16); + +#[repr(C)] +pub enum NonExhaustiveVariants { + #[non_exhaustive] Unit, + #[non_exhaustive] Tuple(u32), + #[non_exhaustive] Struct { field: u32 } +} + +extern { + // Unit structs aren't tested here because they will trigger `improper_ctypes` anyway. + pub fn non_exhaustive_enum(_: NonExhaustiveEnum); + pub fn non_exhaustive_normal_struct(_: NormalStruct); + pub fn non_exhaustive_tuple_struct(_: TupleStruct); + pub fn non_exhaustive_variant(_: NonExhaustiveVariants); +} + +fn main() { } From 2cd5030ef592a2d4094145060c031dcae66e624f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 18 Sep 2019 00:09:19 +0200 Subject: [PATCH 084/545] Deny specializing items not in the parent impl --- src/liballoc/boxed.rs | 5 ++ src/librustc/traits/project.rs | 4 +- src/librustc/traits/specialize/mod.rs | 2 +- .../traits/specialize/specialization_graph.rs | 63 ++++++++++++------- src/librustc/traits/util.rs | 5 +- src/librustc_typeck/check/mod.rs | 55 +++++++++++++--- .../auxiliary/cross_crates_defaults.rs | 4 +- src/test/ui/specialization/issue-36804.rs | 4 ++ .../specialization-default-methods.rs | 5 +- 9 files changed, 104 insertions(+), 43 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index b2789a535fe4..adbc0e6ba2c0 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -871,6 +871,11 @@ impl Iterator for Box { fn nth(&mut self, n: usize) -> Option { (**self).nth(n) } + default fn last(self) -> Option { + let mut last = None; + for x in self { last = Some(x); } + last + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index a7bb29c699e0..c6255e56b6d1 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1505,8 +1505,8 @@ fn assoc_ty_def( if let Some(assoc_item) = trait_def .ancestors(tcx, impl_def_id) - .defs(tcx, assoc_ty_name, ty::AssocKind::Type, trait_def_id) - .next() { + .leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) { + assoc_item } else { // This is saying that neither the trait nor diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index f0389bb037ac..9c80ef7d4a23 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -125,7 +125,7 @@ pub fn find_associated_item<'tcx>( let trait_def = tcx.trait_def(trait_def_id); let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id); - match ancestors.defs(tcx, item.ident, item.kind, trait_def_id).next() { + 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(); diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 43f558d64430..0febdbe161d4 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -7,7 +7,6 @@ use crate::traits; use crate::ty::{self, TyCtxt, TypeFoldable}; use crate::ty::fast_reject::{self, SimplifiedType}; use syntax::ast::Ident; -use crate::util::captures::Captures; use crate::util::nodemap::{DefIdMap, FxHashMap}; /// A per-trait graph of impls in specialization order. At the moment, this @@ -419,6 +418,35 @@ impl<'tcx> Node { tcx.associated_items(self.def_id()) } + /// Finds an associated item defined in this node. + /// + /// If this returns `None`, the item can potentially still be found in + /// parents of this node. + pub fn item( + &self, + tcx: TyCtxt<'tcx>, + trait_item_name: Ident, + trait_item_kind: ty::AssocKind, + trait_def_id: DefId, + ) -> Option { + use crate::ty::AssocKind::*; + + tcx.associated_items(self.def_id()) + .find(move |impl_item| match (trait_item_kind, impl_item.kind) { + | (Const, Const) + | (Method, Method) + | (Type, Type) + | (Type, OpaqueTy) + => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id), + + | (Const, _) + | (Method, _) + | (Type, _) + | (OpaqueTy, _) + => false, + }) + } + pub fn def_id(&self) -> DefId { match *self { Node::Impl(did) => did, @@ -427,6 +455,7 @@ impl<'tcx> Node { } } +#[derive(Copy, Clone)] pub struct Ancestors<'tcx> { trait_def_id: DefId, specialization_graph: &'tcx Graph, @@ -465,32 +494,18 @@ impl NodeItem { } impl<'tcx> Ancestors<'tcx> { - /// Search the items from the given ancestors, returning each definition - /// with the given name and the given kind. - // FIXME(#35870): avoid closures being unexported due to `impl Trait`. - #[inline] - pub fn defs( - self, + /// Finds the bottom-most (ie. most specialized) definition of an associated + /// item. + pub fn leaf_def( + mut self, tcx: TyCtxt<'tcx>, trait_item_name: Ident, trait_item_kind: ty::AssocKind, - trait_def_id: DefId, - ) -> impl Iterator> + Captures<'tcx> + 'tcx { - self.flat_map(move |node| { - use crate::ty::AssocKind::*; - node.items(tcx).filter(move |impl_item| match (trait_item_kind, impl_item.kind) { - | (Const, Const) - | (Method, Method) - | (Type, Type) - | (Type, OpaqueTy) - => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id), - - | (Const, _) - | (Method, _) - | (Type, _) - | (OpaqueTy, _) - => false, - }).map(move |item| NodeItem { node: node, item: item }) + ) -> Option> { + let trait_def_id = self.trait_def_id; + self.find_map(|node| { + node.item(tcx, trait_item_name, trait_item_kind, trait_def_id) + .map(|item| NodeItem { node, item }) }) } } diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index 18ec2241b2df..d8b1effe09bf 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -4,7 +4,6 @@ use syntax_pos::Span; use crate::hir; use crate::hir::def_id::DefId; -use crate::traits::specialize::specialization_graph::NodeItem; use crate::ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef}; use crate::ty::outlives::Component; use crate::ty::subst::{GenericArg, Subst, SubstsRef}; @@ -667,8 +666,8 @@ impl<'tcx> TyCtxt<'tcx> { } } - pub fn impl_item_is_final(self, node_item: &NodeItem) -> bool { - node_item.item.is_final() && !self.impl_is_default(node_item.node.def_id()) + pub fn impl_item_is_final(self, assoc_item: &ty::AssocItem) -> bool { + assoc_item.defaultness.is_final() && !self.impl_is_default(assoc_item.container.id()) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7380bf7536de..f130ee821d17 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1713,8 +1713,6 @@ fn check_specialization_validity<'tcx>( impl_id: DefId, impl_item: &hir::ImplItem, ) { - let ancestors = trait_def.ancestors(tcx, impl_id); - let kind = match impl_item.kind { hir::ImplItemKind::Const(..) => ty::AssocKind::Const, hir::ImplItemKind::Method(..) => ty::AssocKind::Method, @@ -1722,15 +1720,53 @@ fn check_specialization_validity<'tcx>( hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type, }; - let parent = ancestors.defs(tcx, trait_item.ident, kind, trait_def.def_id).nth(1) - .map(|node_item| node_item.map(|parent| parent.defaultness)); + let mut ancestor_impls = trait_def.ancestors(tcx, impl_id) + .skip(1) + .filter_map(|parent| { + if parent.is_from_trait() { + None + } else { + Some((parent, parent.item(tcx, trait_item.ident, kind, trait_def.def_id))) + } + }) + .peekable(); - if let Some(parent) = parent { - if tcx.impl_item_is_final(&parent) { - report_forbidden_specialization(tcx, impl_item, parent.node.def_id()); - } + if ancestor_impls.peek().is_none() { + // No parent, nothing to specialize. + return; } + let opt_result = ancestor_impls.find_map(|(parent_impl, parent_item)| { + match parent_item { + // Parent impl exists, and contains the parent item we're trying to specialize, but + // doesn't mark it `default`. + Some(parent_item) if tcx.impl_item_is_final(&parent_item) => { + Some(Err(parent_impl.def_id())) + } + + // Parent impl contains item and makes it specializable. + Some(_) => { + Some(Ok(())) + } + + // Parent impl doesn't mention the item. This means it's inherited from the + // grandparent. In that case, if parent is a `default impl`, inherited items use the + // "defaultness" from the grandparent, else they are final. + None => if tcx.impl_is_default(parent_impl.def_id()) { + None + } else { + Some(Err(parent_impl.def_id())) + } + } + }); + + // If `opt_result` is `None`, we have only encoutered `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(())); + + if let Err(parent_impl) = result { + report_forbidden_specialization(tcx, impl_item, parent_impl); + } } fn check_impl_items_against_trait<'tcx>( @@ -1846,8 +1882,7 @@ fn check_impl_items_against_trait<'tcx>( let associated_type_overridden = overridden_associated_type.is_some(); for trait_item in tcx.associated_items(impl_trait_ref.def_id) { let is_implemented = trait_def.ancestors(tcx, impl_id) - .defs(tcx, trait_item.ident, trait_item.kind, impl_trait_ref.def_id) - .next() + .leaf_def(tcx, trait_item.ident, trait_item.kind) .map(|node_item| !node_item.node.is_from_trait()) .unwrap_or(false); diff --git a/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs index 5cf975b5752f..1e5555355c3b 100644 --- a/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs +++ b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs @@ -22,7 +22,9 @@ pub trait Bar { fn bar(&self) -> i32 { 0 } } -impl Bar for T {} // use the provided method +impl Bar for T { + default fn bar(&self) -> i32 { 0 } +} impl Bar for i32 { fn bar(&self) -> i32 { 1 } diff --git a/src/test/ui/specialization/issue-36804.rs b/src/test/ui/specialization/issue-36804.rs index 36cb939bc48f..9546a5dd5f51 100644 --- a/src/test/ui/specialization/issue-36804.rs +++ b/src/test/ui/specialization/issue-36804.rs @@ -13,6 +13,10 @@ where fn next(&mut self) -> Option { unimplemented!() } + + default fn count(self) -> usize where Self: Sized { + self.fold(0, |cnt, _| cnt + 1) + } } impl<'a, I, T: 'a> Iterator for Cloned diff --git a/src/test/ui/specialization/specialization-default-methods.rs b/src/test/ui/specialization/specialization-default-methods.rs index 5d65a0457e79..9ae3d1e9f393 100644 --- a/src/test/ui/specialization/specialization-default-methods.rs +++ b/src/test/ui/specialization/specialization-default-methods.rs @@ -55,8 +55,9 @@ trait Bar { // / \ // Vec $Vec -// use the provided method -impl Bar for T {} +impl Bar for T { + default fn bar(&self) -> i32 { 0 } +} impl Bar for i32 { fn bar(&self) -> i32 { 1 } From 55277d4a6ebbf1de00437c268cbf6caf07ddf458 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 18 Sep 2019 23:00:59 +0200 Subject: [PATCH 085/545] Add comment to `Type` and `OpaqueTy` match --- src/librustc/traits/specialize/specialization_graph.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs index 0febdbe161d4..c64d6748ea97 100644 --- a/src/librustc/traits/specialize/specialization_graph.rs +++ b/src/librustc/traits/specialize/specialization_graph.rs @@ -436,7 +436,7 @@ impl<'tcx> Node { | (Const, Const) | (Method, Method) | (Type, Type) - | (Type, OpaqueTy) + | (Type, OpaqueTy) // assoc. types can be made opaque in impls => tcx.hygienic_eq(impl_item.ident, trait_item_name, trait_def_id), | (Const, _) From 02f36e52a656f1baa717538e18ae96137cbc83f9 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 18 Sep 2019 23:41:57 +0200 Subject: [PATCH 086/545] Hide the `Iterator` specialization behind a trait --- src/liballoc/boxed.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index adbc0e6ba2c0..9b5d9431ae20 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -871,16 +871,33 @@ impl Iterator for Box { fn nth(&mut self, n: usize) -> Option { (**self).nth(n) } - default fn last(self) -> Option { - let mut last = None; - for x in self { last = Some(x); } - last + fn last(self) -> Option { + BoxIter::last(self) } } +trait BoxIter { + type Item; + fn last(self) -> Option; +} + +impl BoxIter for Box { + type Item = I::Item; + default fn last(self) -> Option { + #[inline] + fn some(_: Option, x: T) -> Option { + Some(x) + } + + self.fold(None, some) + } +} + +/// Specialization for sized `I`s that uses `I`s implementation of `last()` +/// instead of the default. #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Box { - fn last(self) -> Option where I: Sized { +impl BoxIter for Box { + fn last(self) -> Option { (*self).last() } } From 9aaef06cf6a0c4e671c51f0d13a4ae6cf8b8dec5 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 00:14:02 +0200 Subject: [PATCH 087/545] Fix the bootstrap --- src/librustc/ty/query/config.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index 91082c59ba05..c4b7b9d29b96 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -73,6 +73,14 @@ impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M { format!("processing {:?} with query `{}`", def_id, name).into() } } + + default fn cache_on_disk(_: TyCtxt<'tcx>, _: Self::Key, _: Option<&Self::Value>) -> bool { + false + } + + default fn try_load_from_disk(_: TyCtxt<'tcx>, _: SerializedDepNodeIndex) -> Option { + bug!("QueryDescription::load_from_disk() called for an unsupported query.") + } } impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> { From a0cf5315ef516c4f79bea39c5446a3a6ef6a0d24 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 00:37:28 +0200 Subject: [PATCH 088/545] Test that we get the proper errors --- .../specialization-default-methods-fail.rs | 43 +++++++++++++++++++ ...specialization-default-methods-fail.stderr | 27 ++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 src/test/ui/specialization/specialization-default-methods-fail.rs create mode 100644 src/test/ui/specialization/specialization-default-methods-fail.stderr diff --git a/src/test/ui/specialization/specialization-default-methods-fail.rs b/src/test/ui/specialization/specialization-default-methods-fail.rs new file mode 100644 index 000000000000..3bd2d31ef635 --- /dev/null +++ b/src/test/ui/specialization/specialization-default-methods-fail.rs @@ -0,0 +1,43 @@ +// compile-fail + +#![feature(specialization)] + +// Test that attempting to override a non-default method or one not in the +// parent impl causes an error + +trait Foo { + fn foo(&self) -> bool { true } +} + +// Specialization tree for Foo: +// +// Box Vec +// / \ / \ +// Box Box Vec<()> Vec + +impl Foo for Box { + fn foo(&self) -> bool { false } +} + +// Allowed +impl Foo for Box {} + +// Can't override a non-`default` fn +impl Foo for Box { + fn foo(&self) -> bool { true } + //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + + +// Doesn't mention the method = provided body is used and the method is final +impl Foo for Vec {} + +// Allowed +impl Foo for Vec<()> {} + +impl Foo for Vec { + fn foo(&self) -> bool { true } + //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + +fn main() {} diff --git a/src/test/ui/specialization/specialization-default-methods-fail.stderr b/src/test/ui/specialization/specialization-default-methods-fail.stderr new file mode 100644 index 000000000000..f962ccca83d0 --- /dev/null +++ b/src/test/ui/specialization/specialization-default-methods-fail.stderr @@ -0,0 +1,27 @@ +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:27:5 + | +LL | / impl Foo for Box { +LL | | fn foo(&self) -> bool { false } +LL | | } + | |_- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:39:5 + | +LL | impl Foo for Vec {} + | ------------------------- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0520`. From 98f02b23628d3b46e25f83634d5db2ffbe8ee725 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 00:42:50 +0200 Subject: [PATCH 089/545] Pacify tidy --- src/librustc/ty/query/config.rs | 5 ++++- .../ui/specialization/specialization-default-methods-fail.rs | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index c4b7b9d29b96..c1c6a655d96a 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -78,7 +78,10 @@ impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M { false } - default fn try_load_from_disk(_: TyCtxt<'tcx>, _: SerializedDepNodeIndex) -> Option { + default fn try_load_from_disk( + _: TyCtxt<'tcx>, + _: SerializedDepNodeIndex, + ) -> Option { bug!("QueryDescription::load_from_disk() called for an unsupported query.") } } diff --git a/src/test/ui/specialization/specialization-default-methods-fail.rs b/src/test/ui/specialization/specialization-default-methods-fail.rs index 3bd2d31ef635..c50982141884 100644 --- a/src/test/ui/specialization/specialization-default-methods-fail.rs +++ b/src/test/ui/specialization/specialization-default-methods-fail.rs @@ -25,7 +25,7 @@ impl Foo for Box {} // Can't override a non-`default` fn impl Foo for Box { fn foo(&self) -> bool { true } - //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` } @@ -37,7 +37,7 @@ impl Foo for Vec<()> {} impl Foo for Vec { fn foo(&self) -> bool { true } - //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` } fn main() {} From 33d23cdf042af4a2b8acd32098114ad7e8ac8f5e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 00:54:47 +0200 Subject: [PATCH 090/545] Extend test and fix nits --- .../specialization-default-methods-fail.rs | 20 ++++-- ...specialization-default-methods-fail.stderr | 62 +++++++++++++++++-- 2 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/test/ui/specialization/specialization-default-methods-fail.rs b/src/test/ui/specialization/specialization-default-methods-fail.rs index c50982141884..403f718d7dd9 100644 --- a/src/test/ui/specialization/specialization-default-methods-fail.rs +++ b/src/test/ui/specialization/specialization-default-methods-fail.rs @@ -1,11 +1,11 @@ -// compile-fail - -#![feature(specialization)] +#![feature(specialization, associated_type_defaults)] // Test that attempting to override a non-default method or one not in the -// parent impl causes an error +// parent impl causes an error. trait Foo { + type Ty = (); + const CONST: u8 = 123; fn foo(&self) -> bool { true } } @@ -16,6 +16,8 @@ trait Foo { // Box Box Vec<()> Vec impl Foo for Box { + type Ty = bool; + const CONST: u8 = 0; fn foo(&self) -> bool { false } } @@ -24,18 +26,26 @@ impl Foo for Box {} // Can't override a non-`default` fn impl Foo for Box { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` fn foo(&self) -> bool { true } //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` } -// Doesn't mention the method = provided body is used and the method is final +// Doesn't mention the item = provided body/value is used and the method is final. impl Foo for Vec {} // Allowed impl Foo for Vec<()> {} impl Foo for Vec { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` fn foo(&self) -> bool { true } //~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` } diff --git a/src/test/ui/specialization/specialization-default-methods-fail.stderr b/src/test/ui/specialization/specialization-default-methods-fail.stderr index f962ccca83d0..f215191a8cec 100644 --- a/src/test/ui/specialization/specialization-default-methods-fail.stderr +++ b/src/test/ui/specialization/specialization-default-methods-fail.stderr @@ -1,7 +1,39 @@ -error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:27:5 +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:29:5 | LL | / impl Foo for Box { +LL | | type Ty = bool; +LL | | const CONST: u8 = 0; +LL | | fn foo(&self) -> bool { false } +LL | | } + | |_- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:31:5 + | +LL | / impl Foo for Box { +LL | | type Ty = bool; +LL | | const CONST: u8 = 0; +LL | | fn foo(&self) -> bool { false } +LL | | } + | |_- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:33:5 + | +LL | / impl Foo for Box { +LL | | type Ty = bool; +LL | | const CONST: u8 = 0; LL | | fn foo(&self) -> bool { false } LL | | } | |_- parent `impl` is here @@ -11,8 +43,30 @@ LL | fn foo(&self) -> bool { true } | = note: to specialize, `foo` in the parent `impl` must be marked `default` +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:45:5 + | +LL | impl Foo for Vec {} + | ------------------------- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/specialization-default-methods-fail.rs:47:5 + | +LL | impl Foo for Vec {} + | ------------------------- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:39:5 + --> $DIR/specialization-default-methods-fail.rs:49:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here @@ -22,6 +76,6 @@ LL | fn foo(&self) -> bool { true } | = note: to specialize, `foo` in the parent `impl` must be marked `default` -error: aborting due to 2 previous errors +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0520`. From 47f89e7485ed7a76d8bfcbedcad07fd6b74fa927 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 19 Sep 2019 01:04:23 +0200 Subject: [PATCH 091/545] Rename the test --- ...lt-methods-fail.rs => non-defaulted-item-fail.rs} | 0 ...ds-fail.stderr => non-defaulted-item-fail.stderr} | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) rename src/test/ui/specialization/{specialization-default-methods-fail.rs => non-defaulted-item-fail.rs} (100%) rename src/test/ui/specialization/{specialization-default-methods-fail.stderr => non-defaulted-item-fail.stderr} (89%) diff --git a/src/test/ui/specialization/specialization-default-methods-fail.rs b/src/test/ui/specialization/non-defaulted-item-fail.rs similarity index 100% rename from src/test/ui/specialization/specialization-default-methods-fail.rs rename to src/test/ui/specialization/non-defaulted-item-fail.rs diff --git a/src/test/ui/specialization/specialization-default-methods-fail.stderr b/src/test/ui/specialization/non-defaulted-item-fail.stderr similarity index 89% rename from src/test/ui/specialization/specialization-default-methods-fail.stderr rename to src/test/ui/specialization/non-defaulted-item-fail.stderr index f215191a8cec..e6c5fc1441b2 100644 --- a/src/test/ui/specialization/specialization-default-methods-fail.stderr +++ b/src/test/ui/specialization/non-defaulted-item-fail.stderr @@ -1,5 +1,5 @@ error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:29:5 + --> $DIR/non-defaulted-item-fail.rs:29:5 | LL | / impl Foo for Box { LL | | type Ty = bool; @@ -14,7 +14,7 @@ LL | type Ty = Vec<()>; = note: to specialize, `Ty` in the parent `impl` must be marked `default` error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:31:5 + --> $DIR/non-defaulted-item-fail.rs:31:5 | LL | / impl Foo for Box { LL | | type Ty = bool; @@ -29,7 +29,7 @@ LL | const CONST: u8 = 42; = note: to specialize, `CONST` in the parent `impl` must be marked `default` error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:33:5 + --> $DIR/non-defaulted-item-fail.rs:33:5 | LL | / impl Foo for Box { LL | | type Ty = bool; @@ -44,7 +44,7 @@ LL | fn foo(&self) -> bool { true } = note: to specialize, `foo` in the parent `impl` must be marked `default` error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:45:5 + --> $DIR/non-defaulted-item-fail.rs:45:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here @@ -55,7 +55,7 @@ LL | type Ty = Vec<()>; = note: to specialize, `Ty` in the parent `impl` must be marked `default` error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:47:5 + --> $DIR/non-defaulted-item-fail.rs:47:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here @@ -66,7 +66,7 @@ LL | const CONST: u8 = 42; = note: to specialize, `CONST` in the parent `impl` must be marked `default` error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` - --> $DIR/specialization-default-methods-fail.rs:49:5 + --> $DIR/non-defaulted-item-fail.rs:49:5 | LL | impl Foo for Vec {} | ------------------------- parent `impl` is here From 993e3a52cb33c4ea97ab8c73b449743669747497 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Sat, 5 Oct 2019 21:12:04 +0200 Subject: [PATCH 092/545] remove event that causes panics in measureme tools the measureme tools summarize and crox do not alow a event to go out of scope of the parent event codegen_and_optimize_crate ends after the codegen_crate event --- src/librustc_codegen_ssa/back/write.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index caaa500766d0..81129f0ad7a7 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -321,8 +321,6 @@ pub fn start_async_codegen( let (coordinator_send, coordinator_receive) = channel(); let sess = tcx.sess; - sess.prof.generic_activity_start("codegen_and_optimize_crate"); - 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); @@ -1774,8 +1772,6 @@ impl OngoingCodegen { self.backend.print_pass_timings() } - sess.prof.generic_activity_end("codegen_and_optimize_crate"); - (CodegenResults { crate_name: self.crate_name, crate_hash: self.crate_hash, From dd403e4ab0ae25a27c35a803eb229416625b8e55 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Thu, 3 Oct 2019 00:31:21 -0400 Subject: [PATCH 093/545] Make re-export collection deterministic Previously, we were using an `FxHashMap` to collect module re-exports. However, re-exports end up getting serialized into crate metadata, which means that metadata generation was non-deterministic. This resulted in spurious error messages changes (e.g. PR #64906) due to pretty-printing implicitly depending on the order of re-exports when computing the proper path to show to the user. See #65042 for a long-term strategy to detect this kind of issue --- src/librustc_resolve/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e7292b52ab3e..2995ce2daefa 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -58,6 +58,7 @@ use std::{cmp, fmt, iter, ptr}; use std::collections::BTreeSet; use rustc_data_structures::ptr_key::PtrKey; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::fx::FxIndexMap; use diagnostics::{Suggestion, ImportSuggestion}; use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding}; @@ -431,7 +432,7 @@ impl ModuleKind { } } -type Resolutions<'a> = RefCell>>>; +type Resolutions<'a> = RefCell>>>; /// One node in the tree of modules. pub struct ModuleData<'a> { From add0a42034b4e3d565ae5934e355bce9b88d15a1 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 5 Oct 2019 16:02:34 -0400 Subject: [PATCH 094/545] Remove `for_each_child_stable` Now that `Resolutions` has a deterministic iteration order, it's no longer necessary to sort its entries before iterating over them --- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_resolve/late/diagnostics.rs | 4 +-- src/librustc_resolve/lib.rs | 11 -------- ...issue-43871-enum-instead-of-variant.stderr | 26 +++++++++---------- src/test/ui/issues/issue-35675.stderr | 2 +- 5 files changed, 17 insertions(+), 28 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 7f819486f5bd..5c85650718c1 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -527,7 +527,7 @@ impl<'a> Resolver<'a> { in_module_is_extern)) = worklist.pop() { // We have to visit module children in deterministic order to avoid // instabilities in reported imports (#43552). - in_module.for_each_child_stable(self, |this, ident, ns, name_binding| { + in_module.for_each_child(self, |this, ident, ns, name_binding| { // avoid imports entirely if name_binding.is_import() && !name_binding.is_extern_crate() { return; } // avoid non-importable candidates as well diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index d3bf82b66ad1..1016989ca6e3 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -728,7 +728,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { // abort if the module is already found if result.is_some() { break; } - in_module.for_each_child_stable(self.r, |_, ident, _, name_binding| { + in_module.for_each_child(self.r, |_, ident, _, name_binding| { // abort if the module is already found or if name_binding is private external if result.is_some() || !name_binding.vis.is_visible_locally() { return @@ -760,7 +760,7 @@ impl<'a> LateResolutionVisitor<'a, '_> { fn collect_enum_variants(&mut self, def_id: DefId) -> Option> { self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| { let mut variants = Vec::new(); - enum_module.for_each_child_stable(self.r, |_, ident, _, name_binding| { + enum_module.for_each_child(self.r, |_, ident, _, name_binding| { if let Res::Def(DefKind::Variant, _) = name_binding.res() { let mut segms = enum_import_suggestion.path.segments.clone(); segms.push(ast::PathSegment::from_ident(ident)); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2995ce2daefa..eaa4850f65c0 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -497,17 +497,6 @@ impl<'a> ModuleData<'a> { } } - fn for_each_child_stable(&'a self, resolver: &mut R, mut f: F) - where R: AsMut>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>) - { - let resolutions = resolver.as_mut().resolutions(self).borrow(); - let mut resolutions = resolutions.iter().collect::>(); - resolutions.sort_by_cached_key(|&(&(ident, ns), _)| (ident.as_str(), ns)); - for &(&(ident, ns), &resolution) in resolutions.iter() { - resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding)); - } - } - fn res(&self) -> Option { match self.kind { ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)), diff --git a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr index d02f30152d68..d8826d4072a9 100644 --- a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr +++ b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr @@ -5,10 +5,10 @@ LL | let x = Option(1); | ^^^^^^ help: try using one of the enum's variants | -LL | let x = std::prelude::v1::Option::None(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | let x = std::prelude::v1::Option::Some(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = std::option::Option::None(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = std::option::Option::Some(1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0532]: expected tuple struct/variant, found enum `Option` --> $DIR/issue-43871-enum-instead-of-variant.rs:21:12 @@ -17,10 +17,10 @@ LL | if let Option(_) = x { | ^^^^^^ help: try using one of the enum's variants | -LL | if let std::prelude::v1::Option::None(_) = x { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | if let std::prelude::v1::Option::Some(_) = x { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let std::option::Option::None(_) = x { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let std::option::Option::Some(_) = x { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0532]: expected tuple struct/variant, found enum `Example` --> $DIR/issue-43871-enum-instead-of-variant.rs:27:12 @@ -47,14 +47,14 @@ LL | let z = ManyVariants(); | ^^^^^^^^^^^^ help: try using one of the enum's variants | -LL | let z = ManyVariants::Eight(); +LL | let z = ManyVariants::One(); + | ^^^^^^^^^^^^^^^^^ +LL | let z = ManyVariants::Two(); + | ^^^^^^^^^^^^^^^^^ +LL | let z = ManyVariants::Three(); | ^^^^^^^^^^^^^^^^^^^ -LL | let z = ManyVariants::Five(); - | ^^^^^^^^^^^^^^^^^^ LL | let z = ManyVariants::Four(); | ^^^^^^^^^^^^^^^^^^ -LL | let z = ManyVariants::Nine(); - | ^^^^^^^^^^^^^^^^^^ and 6 other candidates error: aborting due to 5 previous errors diff --git a/src/test/ui/issues/issue-35675.stderr b/src/test/ui/issues/issue-35675.stderr index 28555a15afae..856d6506f2a9 100644 --- a/src/test/ui/issues/issue-35675.stderr +++ b/src/test/ui/issues/issue-35675.stderr @@ -63,7 +63,7 @@ LL | fn qux() -> Some { | ^^^^ | | | not a type - | help: try using the variant's enum: `Option` + | help: try using the variant's enum: `std::option::Option` error: aborting due to 7 previous errors From fcd98cf5dc7d5555147a3ce18c1875c5a7becced Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 5 Oct 2019 23:28:49 +0300 Subject: [PATCH 095/545] resolve: Remove an incorrect assert --- src/librustc_resolve/macros.rs | 1 - .../ui/proc-macro/disappearing-resolution.rs | 22 +++++++++++++++++++ .../proc-macro/disappearing-resolution.stderr | 15 +++++++++++++ 3 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/proc-macro/disappearing-resolution.rs create mode 100644 src/test/ui/proc-macro/disappearing-resolution.stderr diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 73ad0670659b..ae483354a40d 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -773,7 +773,6 @@ impl<'a> Resolver<'a> { check_consistency(self, &[seg], ident.span, kind, initial_res, res); } Err(..) => { - assert!(initial_binding.is_none()); let expected = kind.descr_expected(); let msg = format!("cannot find {} `{}` in this scope", expected, ident); let mut err = self.session.struct_span_err(ident.span, &msg); diff --git a/src/test/ui/proc-macro/disappearing-resolution.rs b/src/test/ui/proc-macro/disappearing-resolution.rs new file mode 100644 index 000000000000..a01b8f302cae --- /dev/null +++ b/src/test/ui/proc-macro/disappearing-resolution.rs @@ -0,0 +1,22 @@ +// Regression test for issue #64803 (initial attribute resolution can disappear later). + +// aux-build:test-macros.rs + +#[macro_use] +extern crate test_macros; + +mod m { + use test_macros::Empty; +} +use m::Empty; //~ ERROR derive macro `Empty` is private + +// To resolve `empty_helper` we need to resolve `Empty`. +// During initial resolution `use m::Empty` introduces no entries, so we proceed to `macro_use`, +// successfully resolve `Empty` from there, and then resolve `empty_helper` as its helper. +// During validation `use m::Empty` introduces a `Res::Err` stub, so `Empty` resolves to it, +// and `empty_helper` can no longer be resolved. +#[empty_helper] //~ ERROR cannot find attribute `empty_helper` in this scope +#[derive(Empty)] +struct S; + +fn main() {} diff --git a/src/test/ui/proc-macro/disappearing-resolution.stderr b/src/test/ui/proc-macro/disappearing-resolution.stderr new file mode 100644 index 000000000000..a3377ef515f9 --- /dev/null +++ b/src/test/ui/proc-macro/disappearing-resolution.stderr @@ -0,0 +1,15 @@ +error: cannot find attribute `empty_helper` in this scope + --> $DIR/disappearing-resolution.rs:18:3 + | +LL | #[empty_helper] + | ^^^^^^^^^^^^ + +error[E0603]: derive macro `Empty` is private + --> $DIR/disappearing-resolution.rs:11:8 + | +LL | use m::Empty; + | ^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0603`. From 45835e9957e2872a3918eda0504d4a1ecc1642cd Mon Sep 17 00:00:00 2001 From: BO41 Date: Sat, 5 Oct 2019 22:55:19 +0200 Subject: [PATCH 096/545] Remove the code of conduct; instead link https://www.rust-lang.org/conduct.html --- CODE_OF_CONDUCT.md | 39 +-------------------------------------- 1 file changed, 1 insertion(+), 38 deletions(-) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 58b829e31d67..e3708bc48539 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,40 +1,3 @@ # The Rust Code of Conduct -A version of this document [can be found online](https://www.rust-lang.org/conduct.html). - -## Conduct - -**Contact**: [rust-mods@rust-lang.org](mailto:rust-mods@rust-lang.org) - -* We are committed to providing a friendly, safe and welcoming environment for all, regardless of level of experience, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, nationality, or other similar characteristic. -* On IRC, please avoid using overtly sexual nicknames or other nicknames that might detract from a friendly, safe and welcoming environment for all. -* Please be kind and courteous. There's no need to be mean or rude. -* Respect that people have differences of opinion and that every design or implementation choice carries a trade-off and numerous costs. There is seldom a right answer. -* Please keep unstructured critique to a minimum. If you have solid ideas you want to experiment with, make a fork and see how it works. -* We will exclude you from interaction if you insult, demean or harass anyone. That is not welcome behavior. We interpret the term "harassment" as including the definition in the Citizen Code of Conduct; if you have any lack of clarity about what might be included in that concept, please read their definition. In particular, we don't tolerate behavior that excludes people in socially marginalized groups. -* Private harassment is also unacceptable. No matter who you are, if you feel you have been or are being harassed or made uncomfortable by a community member, please contact one of the channel ops or any of the [Rust moderation team][mod_team] immediately. Whether you're a regular contributor or a newcomer, we care about making this community a safe place for you and we've got your back. -* Likewise any spamming, trolling, flaming, baiting or other attention-stealing behavior is not welcome. - -## Moderation - - -These are the policies for upholding our community's standards of conduct. If you feel that a thread needs moderation, please contact the [Rust moderation team][mod_team]. - -1. Remarks that violate the Rust standards of conduct, including hateful, hurtful, oppressive, or exclusionary remarks, are not allowed. (Cursing is allowed, but never targeting another user, and never in a hateful manner.) -2. Remarks that moderators find inappropriate, whether listed in the code of conduct or not, are also not allowed. -3. Moderators will first respond to such remarks with a warning. -4. If the warning is unheeded, the user will be "kicked," i.e., kicked out of the communication channel to cool off. -5. If the user comes back and continues to make trouble, they will be banned, i.e., indefinitely excluded. -6. Moderators may choose at their discretion to un-ban the user if it was a first offense and they offer the offended party a genuine apology. -7. If a moderator bans someone and you think it was unjustified, please take it up with that moderator, or with a different moderator, **in private**. Complaints about bans in-channel are not allowed. -8. Moderators are held to a higher standard than other community members. If a moderator creates an inappropriate situation, they should expect less leeway than others. - -In the Rust community we strive to go the extra step to look out for each other. Don't just aim to be technically unimpeachable, try to be your best self. In particular, avoid flirting with offensive or sensitive issues, particularly if they're off-topic; this all too often leads to unnecessary fights, hurt feelings, and damaged trust; worse, it can drive people away from the community entirely. - -And if someone takes issue with something you said or did, resist the urge to be defensive. Just stop doing what it was they complained about and apologize. Even if you feel you were misinterpreted or unfairly accused, chances are good there was something you could've communicated better — remember that it's your responsibility to make your fellow Rustaceans comfortable. Everyone wants to get along and we are all here first and foremost because we want to talk about cool technology. You will find that people will be eager to assume good intent and forgive as long as you earn their trust. - -The enforcement policies listed above apply to all official Rust venues; including all communication channels (Rust Discord server, Rust Zulip server); GitHub repositories under rust-lang, rust-lang-nursery, and rust-lang-deprecated; and all forums under rust-lang.org (users.rust-lang.org, internals.rust-lang.org). For other projects adopting the Rust Code of Conduct, please contact the maintainers of those projects for enforcement. If you wish to use this code of conduct for your own project, consider explicitly mentioning your moderation policy or making a copy with your own moderation policy so as to avoid confusion. - -*Adapted from the [Node.js Policy on Trolling](https://blog.izs.me/2012/08/policy-on-trolling) as well as the [Contributor Covenant v1.3.0](https://www.contributor-covenant.org/version/1/3/0/).* - -[mod_team]: https://www.rust-lang.org/team.html#Moderation-team +The Code of Conduct for this repository [can be found online](https://www.rust-lang.org/conduct.html). From 1471f0bc1bc060922cf953250294e968b3e62c7f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 5 Oct 2019 22:24:55 +0100 Subject: [PATCH 097/545] Ensure that associated `async fn`s have unique fresh param names --- src/librustc/hir/lowering.rs | 2 +- .../async-assoc-fn-anon-lifetimes.rs | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 2238a56b29d0..d773c454432d 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -844,7 +844,7 @@ impl<'a> LoweringContext<'a> { /// header, we convert it to an in-band lifetime. fn collect_fresh_in_band_lifetime(&mut self, span: Span) -> ParamName { assert!(self.is_collecting_in_band_lifetimes); - let index = self.lifetimes_to_define.len(); + let index = self.lifetimes_to_define.len() + self.in_scope_lifetimes.len(); let hir_name = ParamName::Fresh(index); self.lifetimes_to_define.push((span, hir_name)); hir_name diff --git a/src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs b/src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs new file mode 100644 index 000000000000..8e08b82b9d3e --- /dev/null +++ b/src/test/ui/async-await/async-assoc-fn-anon-lifetimes.rs @@ -0,0 +1,23 @@ +// check-pass +// Check that the anonymous lifetimes used here aren't considered to shadow one +// another. Note that `async fn` is different to `fn` here because the lifetimes +// are numbered by HIR lowering, rather than lifetime resolution. + +// edition:2018 + +struct A<'a, 'b>(&'a &'b i32); +struct B<'a>(&'a i32); + +impl A<'_, '_> { + async fn assoc(x: &u32, y: B<'_>) { + async fn nested(x: &u32, y: A<'_, '_>) {} + } + + async fn assoc2(x: &u32, y: A<'_, '_>) { + impl A<'_, '_> { + async fn nested_assoc(x: &u32, y: B<'_>) {} + } + } +} + +fn main() {} From 5497ba1690a1cbf65db8cd1a018bf7fc8b82a73a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 5 Oct 2019 16:11:36 -0700 Subject: [PATCH 098/545] When suggesting assoc function with type params, include turbofish --- src/librustc_typeck/check/method/suggest.rs | 27 +++++++++++++------ .../suggest-assoc-fn-call-with-turbofish.rs | 11 ++++++++ ...uggest-assoc-fn-call-with-turbofish.stderr | 22 +++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 2b34c24b266d..7ce855c73c7c 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -462,15 +462,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if static_sources.len() == 1 { if let SelfSource::MethodCall(expr) = source { - err.span_suggestion(expr.span.to(span), - "use associated function syntax instead", - format!("{}::{}", - self.ty_to_string(actual), - item_name), - Applicability::MachineApplicable); + err.span_suggestion( + expr.span.to(span), + "use associated function syntax instead", + format!("{}::{}", self.ty_to_value_string(actual), item_name), + Applicability::MachineApplicable, + ); } else { - err.help(&format!("try with `{}::{}`", - self.ty_to_string(actual), item_name)); + err.help(&format!( + "try with `{}::{}`", + self.ty_to_value_string(actual), + item_name, + )); } report_candidates(span, &mut err, static_sources); @@ -579,6 +582,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None } + /// Print out the type for use in value namespace. + fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String { + match ty.kind { + ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)), + _ => self.ty_to_string(ty), + } + } + fn suggest_use_candidates(&self, err: &mut DiagnosticBuilder<'_>, mut msg: String, diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs new file mode 100644 index 000000000000..ef4b38de9473 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.rs @@ -0,0 +1,11 @@ +struct GenericAssocMethod(T); + +impl GenericAssocMethod { + fn default_hello() {} +} + +fn main() { + let x = GenericAssocMethod(33i32); + x.default_hello(); + //~^ ERROR no method named `default_hello` found for type `GenericAssocMethod` +} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr new file mode 100644 index 000000000000..8cfa7de08bb3 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish.stderr @@ -0,0 +1,22 @@ +error[E0599]: no method named `default_hello` found for type `GenericAssocMethod` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:9:7 + | +LL | struct GenericAssocMethod(T); + | -------------------------------- method `default_hello` not found for this +... +LL | x.default_hello(); + | --^^^^^^^^^^^^^ + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `GenericAssocMethod::::default_hello` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `GenericAssocMethod<_>` + --> $DIR/suggest-assoc-fn-call-with-turbofish.rs:4:5 + | +LL | fn default_hello() {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 3166ce81ec664a0982937050fcedeb3d8538f686 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 5 Oct 2019 16:57:14 -0700 Subject: [PATCH 099/545] Account for derefs when suggesting assoc function --- src/librustc_typeck/check/method/suggest.rs | 21 +++++++++++++++++-- src/test/ui/issues/issue-3707.stderr | 2 +- ...oc-fn-call-with-turbofish-through-deref.rs | 13 ++++++++++++ ...n-call-with-turbofish-through-deref.stderr | 19 +++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs create mode 100644 src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 7ce855c73c7c..621124541d11 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -461,17 +461,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(span, "this is an associated function, not a method"); } if static_sources.len() == 1 { + let ty_str = if let Some(CandidateSource::ImplSource( + impl_did, + )) = static_sources.get(0) { + // When the "method" is resolved through dereferencing, we really want the + // original type that has the associated function for accurate suggestions. + // (#61411) + let ty = self.impl_self_ty(span, *impl_did).ty; + match (&ty.peel_refs().kind, &actual.peel_refs().kind) { + (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => { + // Use `actual` as it will have more `substs` filled in. + self.ty_to_value_string(actual.peel_refs()) + } + _ => self.ty_to_value_string(ty.peel_refs()), + } + } else { + self.ty_to_value_string(actual.peel_refs()) + }; if let SelfSource::MethodCall(expr) = source { err.span_suggestion( expr.span.to(span), "use associated function syntax instead", - format!("{}::{}", self.ty_to_value_string(actual), item_name), + format!("{}::{}", ty_str, item_name), Applicability::MachineApplicable, ); } else { err.help(&format!( "try with `{}::{}`", - self.ty_to_value_string(actual), + ty_str, item_name, )); } diff --git a/src/test/ui/issues/issue-3707.stderr b/src/test/ui/issues/issue-3707.stderr index 05c8ce4c3f11..b98bc572a397 100644 --- a/src/test/ui/issues/issue-3707.stderr +++ b/src/test/ui/issues/issue-3707.stderr @@ -5,7 +5,7 @@ LL | self.boom(); | -----^^^^ | | | | | this is an associated function, not a method - | help: use associated function syntax instead: `&Obj::boom` + | help: use associated function syntax instead: `Obj::boom` | = note: found the following associated functions; to be used as methods, functions must have a `self` parameter note: the candidate is defined in an impl for the type `Obj` diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs new file mode 100644 index 000000000000..5480adb31015 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.rs @@ -0,0 +1,13 @@ +use std::cell::RefCell; + +struct HasAssocMethod; + +impl HasAssocMethod { + fn hello() {} +} +fn main() { + let shared_state = RefCell::new(HasAssocMethod); + let state = shared_state.borrow_mut(); + state.hello(); + //~^ ERROR no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>` +} diff --git a/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr new file mode 100644 index 000000000000..a1c0126146e7 --- /dev/null +++ b/src/test/ui/suggestions/suggest-assoc-fn-call-with-turbofish-through-deref.stderr @@ -0,0 +1,19 @@ +error[E0599]: no method named `hello` found for type `std::cell::RefMut<'_, HasAssocMethod>` in the current scope + --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:11:11 + | +LL | state.hello(); + | ------^^^^^ + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `HasAssocMethod::hello` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `HasAssocMethod` + --> $DIR/suggest-assoc-fn-call-with-turbofish-through-deref.rs:6:5 + | +LL | fn hello() {} + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 0b0aeaca43bc457db2be70114fa7c6ab7925fd78 Mon Sep 17 00:00:00 2001 From: wangxiangqing Date: Sun, 6 Oct 2019 12:03:53 +0800 Subject: [PATCH 100/545] Suggest dereferencing boolean reference when used in 'if' or 'while' Change-Id: I0c5c4d767be2647e6f017ae7bf83558c56dbca97 --- src/librustc_typeck/check/demand.rs | 6 +++++- src/librustc_typeck/check/expr.rs | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 2ea0afb17935..78bd4508e21a 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -349,7 +349,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the span is from a macro, then it's hard to extract the text // and make a good suggestion, so don't bother. - let is_macro = sp.from_expansion(); + let is_desugaring = match sp.desugaring_kind() { + Some(k) => sp.is_desugaring(k), + None => false + }; + let is_macro = sp.from_expansion() && !is_desugaring; match (&expr.kind, &expected.kind, &checked_ty.kind) { (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) { diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 7a6fe9560fbf..aa26c74967a1 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -87,6 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { + self.suggest_ref_or_into(&mut err, expr, expected_ty, ty); + let expr = match &expr.kind { ExprKind::DropTemps(expr) => expr, _ => expr, From d16b7f705bd7c266a924e43a31495477dc4c9321 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Sat, 5 Oct 2019 21:38:45 -0700 Subject: [PATCH 101/545] Revert "Auto merge of #63649 - tlively:emscripten-upstream-upgrade, r=alexcrichton" This reverts commit 7870050796e5904a0fc85ecbe6fa6dde1cfe0c91, reversing changes made to 2e7244807a7878f6eca3eb7d97ae9b413aa49014. --- config.toml.example | 1 - src/bootstrap/builder.rs | 1 - src/bootstrap/test.rs | 5 +- src/ci/docker/asmjs/Dockerfile | 29 +++- src/ci/docker/disabled/wasm32-exp/Dockerfile | 35 ++++ src/ci/docker/disabled/wasm32-exp/node.sh | 9 + src/ci/docker/disabled/wasm32/Dockerfile | 22 +-- src/ci/docker/scripts/emscripten-wasm.sh | 37 ++++ src/ci/docker/scripts/emscripten.sh | 11 +- src/liballoc/tests/binary_heap.rs | 13 +- src/liballoc/tests/str.rs | 2 +- src/liballoc/tests/str.rs.rej | 10 -- src/liballoc/tests/vec.rs | 7 +- src/libcore/ffi.rs | 56 ++++-- src/libcore/hint.rs | 16 ++ src/librustc_codegen_llvm/llvm_util.rs | 3 +- src/librustc_codegen_ssa/back/write.rs | 7 +- src/librustc_target/abi/call/asmjs.rs | 47 +++++ src/librustc_target/abi/call/mod.rs | 13 +- src/librustc_target/abi/call/wasm32.rs | 52 +----- .../abi/call/wasm32_bindgen_compat.rs | 27 --- .../spec/asmjs_unknown_emscripten.rs | 44 ++++- src/librustc_target/spec/mod.rs | 1 + .../spec/wasm32_experimental_emscripten.rs | 44 +++++ .../spec/wasm32_unknown_emscripten.rs | 41 +++-- src/librustdoc/clean/cfg.rs | 2 +- src/libstd/sys/unix/fast_thread_local.rs | 3 +- src/libtest/lib.rs | 6 +- src/libtest/tests.rs | 11 +- src/test/codegen/c-variadic.rs | 1 - src/test/codegen/drop.rs | 1 - src/test/codegen/extern-functions.rs | 1 - .../codegen/external-no-mangle-statics.rs | 1 - src/test/codegen/link_section.rs | 1 - src/test/codegen/no-output-asm-is-volatile.rs | 2 + src/test/codegen/personality_lifetimes.rs | 1 - .../codegen/repr-transparent-aggregates-2.rs | 3 +- .../simd-intrinsic-float-abs.rs | 2 + .../simd-intrinsic-float-ceil.rs | 2 + .../simd-intrinsic-float-cos.rs | 2 + .../simd-intrinsic-float-exp.rs | 2 + .../simd-intrinsic-float-exp2.rs | 2 + .../simd-intrinsic-float-floor.rs | 2 + .../simd-intrinsic-float-fma.rs | 2 + .../simd-intrinsic-float-fsqrt.rs | 2 + .../simd-intrinsic-float-log.rs | 2 + .../simd-intrinsic-float-log10.rs | 2 + .../simd-intrinsic-float-log2.rs | 2 + .../simd-intrinsic-float-minmax.rs | 1 + .../simd-intrinsic-float-pow.rs | 2 + .../simd-intrinsic-float-powi.rs | 2 + .../simd-intrinsic-float-sin.rs | 2 + ...intrinsic-generic-arithmetic-saturating.rs | 160 +++++++++--------- .../simd-intrinsic-generic-bitmask.rs | 6 +- .../simd-intrinsic-generic-gather.rs | 1 + .../simd-intrinsic-generic-scatter.rs | 1 + src/test/codegen/union-abi.rs | 1 - src/test/compile-fail/weak-lang-item.rs | 2 +- src/test/incremental/change_crate_dep_kind.rs | 1 - src/test/incremental/commandline-args.rs | 1 - .../incremental/remapped_paths_cc/main.rs | 1 - src/test/incremental/span_hash_stable/main.rs | 1 - .../incremental/spans_in_type_debuginfo.rs | 1 - .../spans_significant_w_debuginfo.rs | 1 - src/test/mir-opt/box_expr.rs | 2 +- .../mir-opt/generator-storage-dead-unwind.rs | 2 +- src/test/mir-opt/issue-41110.rs | 2 +- src/test/mir-opt/issue-62289.rs | 2 +- .../mir-opt/no-spurious-drop-after-call.rs | 2 +- .../mir-opt/packed-struct-drop-aligned.rs | 2 +- src/test/mir-opt/remove_fake_borrows.rs | 2 +- src/test/mir-opt/retag.rs | 2 +- .../run-make/wasm-custom-section/Makefile | 2 +- .../wasm-custom-sections-opt/Makefile | 2 +- .../run-make/wasm-export-all-symbols/Makefile | 2 +- src/test/run-make/wasm-import-module/Makefile | 2 +- src/test/run-make/wasm-panic-small/Makefile | 2 +- .../wasm-symbols-not-exported/Makefile | 2 +- .../wasm-symbols-not-imported/Makefile | 2 +- src/test/ui/abi/statics/static-mut-foreign.rs | 4 - .../async-await/async-fn-size-moved-locals.rs | 2 +- src/test/ui/async-await/issue-60709.rs | 1 - .../fn-arg-incomplete-pattern-drop-order.rs | 2 +- src/test/ui/binding/match-arm-statics.rs | 1 - src/test/ui/builtin-clone-unwind.rs | 2 +- src/test/ui/catch-unwind-bang.rs | 2 +- .../ui/consts/const-int-saturating-arith.rs | 1 + src/test/ui/debuginfo-lto.rs | 1 - src/test/ui/drop/dynamic-drop-async.rs | 2 +- src/test/ui/drop/dynamic-drop.rs | 2 +- src/test/ui/extern/extern-const.fixed | 3 +- src/test/ui/extern/extern-const.rs | 3 +- src/test/ui/extern/extern-const.stderr | 2 +- src/test/ui/generator/issue-58888.rs | 1 - src/test/ui/generator/panic-drops.rs | 2 +- src/test/ui/generator/panic-safe.rs | 2 +- src/test/ui/generator/resume-after-return.rs | 2 +- src/test/ui/generator/size-moved-locals.rs | 1 - src/test/ui/intrinsics/intrinsics-integer.rs | 1 + src/test/ui/issues/issue-14875.rs | 2 +- src/test/ui/issues/issue-23477.rs | 1 - .../issue-24687-embed-debuginfo/main.rs | 1 - .../ui/issues/issue-24945-repeat-dash-opts.rs | 1 - src/test/ui/issues/issue-26484.rs | 1 - src/test/ui/issues/issue-29948.rs | 2 +- src/test/ui/issues/issue-33096.rs | 1 - src/test/ui/issues/issue-33992.rs | 2 +- src/test/ui/issues/issue-34569.rs | 1 - src/test/ui/issues/issue-36856.rs | 1 - src/test/ui/issues/issue-42210.rs | 1 - src/test/ui/issues/issue-43853.rs | 2 +- src/test/ui/issues/issue-45731.rs | 1 - src/test/ui/issues/issue-46519.rs | 2 - src/test/ui/issues/issue-48508.rs | 1 - src/test/ui/issues/issue-49579.rs | 1 + src/test/ui/issues/issue-58463.rs | 2 - .../ui/iterators/iter-count-overflow-debug.rs | 2 +- .../iterators/iter-position-overflow-debug.rs | 2 +- .../ui/iterators/iter-step-overflow-debug.rs | 2 +- .../ui/iterators/iter-sum-overflow-debug.rs | 2 +- .../iter-sum-overflow-overflow-checks.rs | 2 +- .../ui/macros/macro-comma-behavior-rpass.rs | 2 - src/test/ui/mir/mir_calls_to_shims.rs | 2 +- src/test/ui/mir/mir_drop_order.rs | 2 +- .../float-int-invalid-const-cast.rs | 1 + src/test/ui/numbers-arithmetic/i128.rs | 3 + .../next-power-of-two-overflow-debug.rs | 2 +- src/test/ui/numbers-arithmetic/u128-as-f32.rs | 1 + src/test/ui/numbers-arithmetic/u128.rs | 2 + .../panic-runtime/transitive-link-a-bunch.rs | 2 +- .../ui/panic-runtime/want-unwind-got-abort.rs | 2 +- .../panic-runtime/want-unwind-got-abort2.rs | 2 +- src/test/ui/panic-uninitialized-zeroed.rs | 2 +- src/test/ui/proc-macro/expand-with-a-macro.rs | 2 +- src/test/ui/reachable-unnameable-items.rs | 2 +- .../termination-trait-in-test.rs | 2 - src/test/ui/rfcs/rfc1857-drop-order.rs | 2 +- src/test/ui/sepcomp/sepcomp-lib-lto.rs | 1 - .../ui/test-attrs/test-allow-fail-attr.rs | 2 +- .../test-should-fail-good-message.rs | 2 +- .../unboxed-closures-unique-type-id.rs | 1 - src/tools/compiletest/src/header.rs | 5 +- 142 files changed, 537 insertions(+), 377 deletions(-) create mode 100644 src/ci/docker/disabled/wasm32-exp/Dockerfile create mode 100755 src/ci/docker/disabled/wasm32-exp/node.sh create mode 100644 src/ci/docker/scripts/emscripten-wasm.sh delete mode 100644 src/liballoc/tests/str.rs.rej create mode 100644 src/librustc_target/abi/call/asmjs.rs delete mode 100644 src/librustc_target/abi/call/wasm32_bindgen_compat.rs create mode 100644 src/librustc_target/spec/wasm32_experimental_emscripten.rs diff --git a/config.toml.example b/config.toml.example index 2e3b714f9228..848147c2974c 100644 --- a/config.toml.example +++ b/config.toml.example @@ -377,7 +377,6 @@ # but you can also optionally enable the "emscripten" backend for asm.js or # make this an empty array (but that probably won't get too far in the # bootstrap) -# FIXME: remove the obsolete emscripten backend option. #codegen-backends = ["llvm"] # This is the name of the directory in which codegen backends will get installed diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 9b43bb0eff0e..5d586f0c461d 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -970,7 +970,6 @@ impl<'a> Builder<'a> { Some("-Wl,-rpath,@loader_path/../lib") } else if !target.contains("windows") && !target.contains("wasm32") && - !target.contains("emscripten") && !target.contains("fuchsia") { Some("-Wl,-rpath,$ORIGIN/../lib") } else { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index e09e25de64a3..b7ce9c7b3970 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1047,11 +1047,10 @@ impl Step for Compiletest { // Also provide `rust_test_helpers` for the host. builder.ensure(native::TestHelpers { target: compiler.host }); - // As well as the target, except for plain wasm32, which can't build it - if !target.contains("wasm32") || target.contains("emscripten") { + // wasm32 can't build the test helpers + if !target.contains("wasm32") { builder.ensure(native::TestHelpers { target }); } - builder.ensure(RemoteCopyLibs { compiler, target }); let mut cmd = builder.tool_cmd(Tool::Compiletest); diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile index d136fae79aa4..3abaab6b34ef 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -11,8 +11,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - xz-utils \ - bzip2 + xz-utils COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh @@ -21,16 +20,28 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV PATH=$PATH:/emsdk-portable -ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/ -ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/ -ENV BINARYEN_ROOT=/emsdk-portable/upstream/ +ENV PATH=$PATH:/emsdk-portable/clang/e1.38.15_64bit/ +ENV PATH=$PATH:/emsdk-portable/emscripten/1.38.15/ +ENV PATH=$PATH:/emsdk-portable/node/8.9.1_64bit/bin/ +ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.38.15/ +ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.38.15_64bit/binaryen/ ENV EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=asmjs-unknown-emscripten -ENV SCRIPT python2.7 ../x.py test --target $TARGETS +ENV RUST_CONFIGURE_ARGS --enable-emscripten --disable-optimize-tests -# This is almost identical to the wasm32-unknown-emscripten target, so -# running with assertions again is not useful -ENV NO_DEBUG_ASSERTIONS=1 +ENV SCRIPT python2.7 ../x.py test --target $TARGETS \ + src/test/ui \ + src/test/run-fail \ + src/libstd \ + src/liballoc \ + src/libcore + +# Debug assertions in rustc are largely covered by other builders, and LLVM +# assertions cause this builder to slow down by quite a large amount and don't +# buy us a huge amount over other builders (not sure if we've ever seen an +# asmjs-specific backend assertion trip), so disable assertions for these +# tests. ENV NO_LLVM_ASSERTIONS=1 +ENV NO_DEBUG_ASSERTIONS=1 diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile new file mode 100644 index 000000000000..420d47b314c0 --- /dev/null +++ b/src/ci/docker/disabled/wasm32-exp/Dockerfile @@ -0,0 +1,35 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y --no-install-recommends \ + g++ \ + make \ + file \ + curl \ + ca-certificates \ + python \ + git \ + cmake \ + sudo \ + gdb \ + xz-utils \ + jq \ + bzip2 + +# emscripten +COPY scripts/emscripten-wasm.sh /scripts/ +COPY wasm32-exp/node.sh /usr/local/bin/node +RUN bash /scripts/emscripten-wasm.sh + +# cache +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +# env +ENV PATH=/wasm-install/emscripten:/wasm-install/bin:$PATH +ENV EM_CONFIG=/root/.emscripten + +ENV TARGETS=wasm32-experimental-emscripten + +ENV RUST_CONFIGURE_ARGS --experimental-targets=WebAssembly + +ENV SCRIPT python2.7 ../x.py test --target $TARGETS diff --git a/src/ci/docker/disabled/wasm32-exp/node.sh b/src/ci/docker/disabled/wasm32-exp/node.sh new file mode 100755 index 000000000000..aa938971c702 --- /dev/null +++ b/src/ci/docker/disabled/wasm32-exp/node.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +path="$(dirname $1)" +file="$(basename $1)" + +shift + +cd "$path" +exec /node-v8.0.0-linux-x64/bin/node "$file" "$@" diff --git a/src/ci/docker/disabled/wasm32/Dockerfile b/src/ci/docker/disabled/wasm32/Dockerfile index b2cf862c0a51..0d2bd39303ef 100644 --- a/src/ci/docker/disabled/wasm32/Dockerfile +++ b/src/ci/docker/disabled/wasm32/Dockerfile @@ -11,9 +11,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - xz-utils \ - bzip2 + xz-utils +# emscripten COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh @@ -21,18 +21,12 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV PATH=$PATH:/emsdk-portable -ENV PATH=$PATH:/emsdk-portable/upstream/emscripten/ -ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/ -ENV BINARYEN_ROOT=/emsdk-portable/upstream/ +ENV PATH=$PATH:/emsdk-portable/clang/e1.38.15_64bit/ +ENV PATH=$PATH:/emsdk-portable/emscripten/1.38.15/ +ENV PATH=$PATH:/emsdk-portable/node/8.9.1_64bit/bin/ +ENV EMSCRIPTEN=/emsdk-portable/emscripten/1.38.15/ +ENV BINARYEN_ROOT=/emsdk-portable/clang/e1.38.15_64bit/binaryen/ ENV EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=wasm32-unknown-emscripten - -# FIXME: Re-enable these tests once Cargo stops trying to execute wasms -ENV SCRIPT python2.7 ../x.py test --target $TARGETS \ - --exclude src/libcore \ - --exclude src/liballoc \ - --exclude src/libproc_macro \ - --exclude src/libstd \ - --exclude src/libterm \ - --exclude src/libtest +ENV SCRIPT python2.7 ../x.py test --target $TARGETS diff --git a/src/ci/docker/scripts/emscripten-wasm.sh b/src/ci/docker/scripts/emscripten-wasm.sh new file mode 100644 index 000000000000..e4a93d7a1009 --- /dev/null +++ b/src/ci/docker/scripts/emscripten-wasm.sh @@ -0,0 +1,37 @@ +set -ex + +hide_output() { + set +x + on_err=" +echo ERROR: An error was encountered with the build. +cat /tmp/build.log +exit 1 +" + trap "$on_err" ERR + bash -c "while true; do sleep 30; echo \$(date) - building ...; done" & + PING_LOOP_PID=$! + $@ &> /tmp/build.log + trap - ERR + kill $PING_LOOP_PID + rm -f /tmp/build.log + set -x +} + +# Download last known good emscripten from WebAssembly waterfall +BUILD=$(curl -fL https://storage.googleapis.com/wasm-llvm/builds/linux/lkgr.json | \ + jq '.build | tonumber') +curl -sL https://storage.googleapis.com/wasm-llvm/builds/linux/$BUILD/wasm-binaries.tbz2 | \ + hide_output tar xvkj + +# node 8 is required to run wasm +cd / +curl -sL https://nodejs.org/dist/v8.0.0/node-v8.0.0-linux-x64.tar.xz | \ + tar -xJ + +# Make emscripten use wasm-ready node and LLVM tools +echo "EMSCRIPTEN_ROOT = '/wasm-install/emscripten'" >> /root/.emscripten +echo "NODE_JS='/usr/local/bin/node'" >> /root/.emscripten +echo "LLVM_ROOT='/wasm-install/bin'" >> /root/.emscripten +echo "BINARYEN_ROOT = '/wasm-install'" >> /root/.emscripten +echo "COMPILER_ENGINE = NODE_JS" >> /root/.emscripten +echo "JS_ENGINES = [NODE_JS]" >> /root/.emscripten diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh index 9c7a09e227a4..47196e893962 100644 --- a/src/ci/docker/scripts/emscripten.sh +++ b/src/ci/docker/scripts/emscripten.sh @@ -17,15 +17,20 @@ exit 1 set -x } -git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable +cd / +curl -fL https://mozilla-games.s3.amazonaws.com/emscripten/releases/emsdk-portable.tar.gz | \ + tar -xz + cd /emsdk-portable -hide_output ./emsdk install 1.38.46-upstream -./emsdk activate 1.38.46-upstream +./emsdk update +hide_output ./emsdk install sdk-1.38.15-64bit +./emsdk activate sdk-1.38.15-64bit # Compile and cache libc source ./emsdk_env.sh echo "main(){}" > a.c HOME=/emsdk-portable/ emcc a.c +HOME=/emsdk-portable/ emcc -s BINARYEN=1 a.c rm -f a.* # Make emsdk usable by any user diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs index b8c720264d0a..0685fa943c0b 100644 --- a/src/liballoc/tests/binary_heap.rs +++ b/src/liballoc/tests/binary_heap.rs @@ -1,5 +1,10 @@ +use std::cmp; use std::collections::BinaryHeap; use std::collections::binary_heap::{Drain, PeekMut}; +use std::panic::{self, AssertUnwindSafe}; +use std::sync::atomic::{AtomicUsize, Ordering}; + +use rand::{thread_rng, seq::SliceRandom}; #[test] fn test_iterator() { @@ -276,15 +281,9 @@ fn assert_covariance() { // even if the order may not be correct. // // Destructors must be called exactly once per element. -// FIXME: re-enable emscripten once it can unwind again #[test] -#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics +#[cfg(not(miri))] // Miri does not support catching panics fn panic_safe() { - use std::cmp; - use std::panic::{self, AssertUnwindSafe}; - use std::sync::atomic::{AtomicUsize, Ordering}; - use rand::{thread_rng, seq::SliceRandom}; - static DROP_COUNTER: AtomicUsize = AtomicUsize::new(0); #[derive(Eq, PartialEq, Ord, Clone, Debug)] diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index cb73c7c179cb..4332b2e90fda 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -483,7 +483,7 @@ mod slice_index { } #[test] - #[cfg(not(target_os = "emscripten"))] // hits an OOM + #[cfg(not(target_arch = "asmjs"))] // hits an OOM #[cfg(not(miri))] // Miri is too slow fn simple_big() { fn a_million_letter_x() -> String { diff --git a/src/liballoc/tests/str.rs.rej b/src/liballoc/tests/str.rs.rej deleted file mode 100644 index abcba0c2e847..000000000000 --- a/src/liballoc/tests/str.rs.rej +++ /dev/null @@ -1,10 +0,0 @@ -diff a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs (rejected hunks) -@@ -483,7 +483,7 @@ mod slice_index { - } - - #[test] -- #[cfg(not(target_arch = "asmjs"))] // hits an OOM -+ #[cfg(not(target_arch = "js"))] // hits an OOM - #[cfg(not(miri))] // Miri is too slow - fn simple_big() { - fn a_million_letter_x() -> String { diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 80537217697a..98d013dfa2b5 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -944,10 +944,8 @@ fn drain_filter_complex() { } } -// Miri does not support catching panics -// FIXME: re-enable emscripten once it can unwind again #[test] -#[cfg(not(any(miri, target_os = "emscripten")))] +#[cfg(not(miri))] // Miri does not support catching panics fn drain_filter_consumed_panic() { use std::rc::Rc; use std::sync::Mutex; @@ -997,9 +995,8 @@ fn drain_filter_consumed_panic() { } } -// FIXME: Re-enable emscripten once it can catch panics #[test] -#[cfg(not(any(miri, target_os = "emscripten")))] // Miri does not support catching panics +#[cfg(not(miri))] // Miri does not support catching panics fn drain_filter_unconsumed_panic() { use std::rc::Rc; use std::sync::Mutex; diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs index 0ea4187ccd48..eda0e7c518c5 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -49,10 +49,8 @@ impl fmt::Debug for c_void { /// Basic implementation of a `va_list`. // The name is WIP, using `VaListImpl` for now. #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", windows))] #[repr(transparent)] #[unstable(feature = "c_variadic", @@ -69,10 +67,8 @@ pub struct VaListImpl<'f> { } #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", windows))] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ @@ -141,6 +137,38 @@ pub struct VaListImpl<'f> { _marker: PhantomData<&'f mut &'f c_void>, } +/// asm.js ABI implementation of a `va_list`. +// asm.js uses the PNaCl ABI, which specifies that a `va_list` is +// an array of 4 32-bit integers, according to the old PNaCl docs at +// https://web.archive.org/web/20130518054430/https://www.chromium.org/nativeclient/pnacl/bitcode-abi#TOC-Derived-Types +// and clang does the same in `CreatePNaClABIBuiltinVaListDecl` from `lib/AST/ASTContext.cpp` +#[cfg(all(target_arch = "asmjs", not(windows)))] +#[repr(C)] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +#[lang = "va_list"] +pub struct VaListImpl<'f> { + inner: [crate::mem::MaybeUninit; 4], + _marker: PhantomData<&'f mut &'f c_void>, +} + +#[cfg(all(target_arch = "asmjs", not(windows)))] +#[unstable(feature = "c_variadic", + reason = "the `c_variadic` feature has not been properly tested on \ + all supported platforms", + issue = "44930")] +impl<'f> fmt::Debug for VaListImpl<'f> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + unsafe { + write!(f, "va_list* [{:#x}, {:#x}, {:#x}, {:#x}]", + self.inner[0].read(), self.inner[1].read(), + self.inner[2].read(), self.inner[3].read()) + } + } +} + /// A wrapper for a `va_list` #[repr(transparent)] #[derive(Debug)] @@ -150,18 +178,14 @@ pub struct VaListImpl<'f> { issue = "44930")] pub struct VaList<'a, 'f: 'a> { #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", windows))] inner: VaListImpl<'f>, #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", - target_arch = "x86_64"), + target_arch = "x86_64", target_arch = "asmjs"), any(not(target_arch = "aarch64"), not(target_os = "ios")), - not(target_arch = "wasm32"), - not(target_arch = "asmjs"), not(windows)))] inner: &'a mut VaListImpl<'f>, @@ -169,10 +193,8 @@ pub struct VaList<'a, 'f: 'a> { } #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64")), + not(target_arch = "x86_64"), not(target_arch = "asmjs")), all(target_arch = "aarch64", target_os = "ios"), - target_arch = "wasm32", - target_arch = "asmjs", windows))] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ @@ -190,10 +212,8 @@ impl<'f> VaListImpl<'f> { } #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", - target_arch = "x86_64"), + target_arch = "x86_64", target_arch = "asmjs"), any(not(target_arch = "aarch64"), not(target_os = "ios")), - not(target_arch = "wasm32"), - not(target_arch = "asmjs"), not(windows)))] #[unstable(feature = "c_variadic", reason = "the `c_variadic` feature has not been properly tested on \ diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs index 368a2f16b281..ee4be6c91511 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -114,8 +114,24 @@ pub fn black_box(dummy: T) -> T { // this. LLVM's intepretation of inline assembly is that it's, well, a black // box. This isn't the greatest implementation since it probably deoptimizes // more than we want, but it's so far good enough. + #[cfg(not(any( + target_arch = "asmjs", + all( + target_arch = "wasm32", + target_os = "emscripten" + ) + )))] unsafe { asm!("" : : "r"(&dummy)); return dummy; } + + // Not all platforms support inline assembly so try to do something without + // inline assembly which in theory still hinders at least some optimizations + // on those targets. This is the "best effort" scenario. + unsafe { + let ret = crate::ptr::read_volatile(&dummy); + crate::mem::forget(dummy); + ret + } } diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 2dce9b04c9e9..541d3d98b79b 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -257,7 +257,8 @@ pub fn target_feature_whitelist(sess: &Session) "hexagon" => HEXAGON_WHITELIST, "mips" | "mips64" => MIPS_WHITELIST, "powerpc" | "powerpc64" => POWERPC_WHITELIST, - "wasm32" => WASM_WHITELIST, + // wasm32 on emscripten does not support these target features + "wasm32" if !sess.target.target.options.is_like_emscripten => WASM_WHITELIST, _ => &[], } } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index caaa500766d0..f1cfac270332 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -142,12 +142,15 @@ impl ModuleConfig { // Copy what clang does by turning on loop vectorization at O2 and // slp vectorization at O3. Otherwise configure other optimization aspects // of this pass manager builder. + // Turn off vectorization for emscripten, as it's not very well supported. self.vectorize_loop = !sess.opts.cg.no_vectorize_loops && (sess.opts.optimize == config::OptLevel::Default || - sess.opts.optimize == config::OptLevel::Aggressive); + sess.opts.optimize == config::OptLevel::Aggressive) && + !sess.target.target.options.is_like_emscripten; self.vectorize_slp = !sess.opts.cg.no_vectorize_slp && - sess.opts.optimize == config::OptLevel::Aggressive; + sess.opts.optimize == config::OptLevel::Aggressive && + !sess.target.target.options.is_like_emscripten; // Some targets (namely, NVPTX) interact badly with the MergeFunctions // pass. This is because MergeFunctions can generate new function calls diff --git a/src/librustc_target/abi/call/asmjs.rs b/src/librustc_target/abi/call/asmjs.rs new file mode 100644 index 000000000000..92c86372a86f --- /dev/null +++ b/src/librustc_target/abi/call/asmjs.rs @@ -0,0 +1,47 @@ +use crate::abi::call::{FnType, ArgType, Uniform}; +use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; + +// Data layout: e-p:32:32-i64:64-v128:32:128-n32-S128 + +// See the https://github.com/kripken/emscripten-fastcomp-clang repository. +// The class `EmscriptenABIInfo` in `/lib/CodeGen/TargetInfo.cpp` contains the ABI definitions. + +fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + if ret.layout.is_aggregate() { + if let Some(unit) = ret.layout.homogeneous_aggregate(cx).unit() { + let size = ret.layout.size; + if unit.size == size { + ret.cast_to(Uniform { + unit, + total: size + }); + return; + } + } + + ret.make_indirect(); + } +} + +fn classify_arg_ty(arg: &mut ArgType<'_, Ty>) { + if arg.layout.is_aggregate() { + arg.make_indirect_byval(); + } +} + +pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ + if !fty.ret.is_ignore() { + classify_ret_ty(cx, &mut fty.ret); + } + + for arg in &mut fty.args { + if arg.is_ignore() { continue; } + classify_arg_ty(arg); + } +} diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 17bad189bcfd..bc21113527ec 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -5,6 +5,7 @@ use crate::spec::{self, HasTargetSpec}; mod aarch64; mod amdgpu; mod arm; +mod asmjs; mod hexagon; mod mips; mod mips64; @@ -21,7 +22,6 @@ mod x86; mod x86_64; mod x86_win64; mod wasm32; -mod wasm32_bindgen_compat; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum PassMode { @@ -557,6 +557,14 @@ impl<'a, Ty> FnType<'a, Ty> { "powerpc" => powerpc::compute_abi_info(cx, self), "powerpc64" => powerpc64::compute_abi_info(cx, self), "s390x" => s390x::compute_abi_info(cx, self), + "asmjs" => asmjs::compute_abi_info(cx, self), + "wasm32" => { + if cx.target_spec().llvm_target.contains("emscripten") { + asmjs::compute_abi_info(cx, self) + } else { + wasm32::compute_abi_info(self) + } + } "msp430" => msp430::compute_abi_info(self), "sparc" => sparc::compute_abi_info(cx, self), "sparc64" => sparc64::compute_abi_info(cx, self), @@ -565,9 +573,6 @@ impl<'a, Ty> FnType<'a, Ty> { "hexagon" => hexagon::compute_abi_info(self), "riscv32" => riscv::compute_abi_info(self, 32), "riscv64" => riscv::compute_abi_info(self, 64), - "wasm32" if cx.target_spec().target_os != "emscripten" - => wasm32_bindgen_compat::compute_abi_info(self), - "wasm32" | "asmjs" => wasm32::compute_abi_info(cx, self), a => return Err(format!("unrecognized arch \"{}\" in target specification", a)) } diff --git a/src/librustc_target/abi/call/wasm32.rs b/src/librustc_target/abi/call/wasm32.rs index 27799edab919..1fdcbb8e39bd 100644 --- a/src/librustc_target/abi/call/wasm32.rs +++ b/src/librustc_target/abi/call/wasm32.rs @@ -1,60 +1,20 @@ -use crate::abi::call::{FnType, ArgType, Uniform}; -use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; +use crate::abi::call::{FnType, ArgType}; -fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgType<'a, Ty>) -> bool - where Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout -{ - if val.layout.is_aggregate() { - if let Some(unit) = val.layout.homogeneous_aggregate(cx).unit() { - let size = val.layout.size; - if unit.size == size { - val.cast_to(Uniform { - unit, - total: size - }); - return true; - } - } - } - false -} - - -fn classify_ret_ty<'a, Ty, C>(cx: &C, ret: &mut ArgType<'a, Ty>) - where Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout -{ +fn classify_ret_ty(ret: &mut ArgType<'_, Ty>) { ret.extend_integer_width_to(32); - if ret.layout.is_aggregate() { - if !unwrap_trivial_aggregate(cx, ret) { - ret.make_indirect(); - } - } } -fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>) - where Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout -{ +fn classify_arg_ty(arg: &mut ArgType<'_, Ty>) { arg.extend_integer_width_to(32); - if arg.layout.is_aggregate() { - if !unwrap_trivial_aggregate(cx, arg) { - arg.make_indirect_byval(); - } - } } -pub fn compute_abi_info<'a, Ty, C>(cx: &C, fty: &mut FnType<'a, Ty>) - where Ty: TyLayoutMethods<'a, C> + Copy, - C: LayoutOf> + HasDataLayout -{ +pub fn compute_abi_info(fty: &mut FnType<'_, Ty>) { if !fty.ret.is_ignore() { - classify_ret_ty(cx, &mut fty.ret); + classify_ret_ty(&mut fty.ret); } for arg in &mut fty.args { if arg.is_ignore() { continue; } - classify_arg_ty(cx, arg); + classify_arg_ty(arg); } } diff --git a/src/librustc_target/abi/call/wasm32_bindgen_compat.rs b/src/librustc_target/abi/call/wasm32_bindgen_compat.rs deleted file mode 100644 index 2645e30594ce..000000000000 --- a/src/librustc_target/abi/call/wasm32_bindgen_compat.rs +++ /dev/null @@ -1,27 +0,0 @@ -// This is not and has never been a correct C ABI for WebAssembly, but -// for a long time this was the C ABI that Rust used. wasm-bindgen -// depends on ABI details for this ABI and is incompatible with the -// correct C ABI, so this ABI is being kept around until wasm-bindgen -// can be fixed to work with the correct ABI. See #63649 for further -// discussion. - -use crate::abi::call::{FnType, ArgType}; - -fn classify_ret_ty(ret: &mut ArgType<'_, Ty>) { - ret.extend_integer_width_to(32); -} - -fn classify_arg_ty(arg: &mut ArgType<'_, Ty>) { - arg.extend_integer_width_to(32); -} - -pub fn compute_abi_info(fty: &mut FnType<'_, Ty>) { - if !fty.ret.is_ignore() { - classify_ret_ty(&mut fty.ret); - } - - for arg in &mut fty.args { - if arg.is_ignore() { continue; } - classify_arg_ty(arg); - } -} diff --git a/src/librustc_target/spec/asmjs_unknown_emscripten.rs b/src/librustc_target/spec/asmjs_unknown_emscripten.rs index e8f9c1f3d61d..6dc140cf160e 100644 --- a/src/librustc_target/spec/asmjs_unknown_emscripten.rs +++ b/src/librustc_target/spec/asmjs_unknown_emscripten.rs @@ -1,10 +1,40 @@ -use super::{LinkerFlavor, Target, wasm32_unknown_emscripten}; +use super::{LinkArgs, LinkerFlavor, Target, TargetOptions}; pub fn target() -> Result { - let mut target = wasm32_unknown_emscripten::target()?; - target.options.post_link_args - .entry(LinkerFlavor::Em) - .or_default() - .extend(vec!["-s".to_string(), "WASM=0".to_string()]); - Ok(target) + let mut args = LinkArgs::new(); + args.insert(LinkerFlavor::Em, + vec!["-s".to_string(), + "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(), + "-s".to_string(), + "ABORTING_MALLOC=0".to_string(), + "-s".to_string(), + "WASM=0".to_string()]); + + let opts = TargetOptions { + dynamic_linking: false, + executables: true, + exe_suffix: ".js".to_string(), + linker_is_gnu: true, + allow_asm: false, + obj_is_bitcode: true, + is_like_emscripten: true, + max_atomic_width: Some(32), + post_link_args: args, + target_family: Some("unix".to_string()), + codegen_backend: "emscripten".to_string(), + .. Default::default() + }; + Ok(Target { + llvm_target: "asmjs-unknown-emscripten".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + target_os: "emscripten".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(), + arch: "asmjs".to_string(), + linker_flavor: LinkerFlavor::Em, + options: opts, + }) } diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index cf1a84dec97b..25add0cc6a4b 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -462,6 +462,7 @@ supported_targets! { ("wasm32-unknown-emscripten", wasm32_unknown_emscripten), ("wasm32-unknown-unknown", wasm32_unknown_unknown), ("wasm32-wasi", wasm32_wasi), + ("wasm32-experimental-emscripten", wasm32_experimental_emscripten), ("thumbv6m-none-eabi", thumbv6m_none_eabi), ("thumbv7m-none-eabi", thumbv7m_none_eabi), diff --git a/src/librustc_target/spec/wasm32_experimental_emscripten.rs b/src/librustc_target/spec/wasm32_experimental_emscripten.rs new file mode 100644 index 000000000000..b802bee25ae7 --- /dev/null +++ b/src/librustc_target/spec/wasm32_experimental_emscripten.rs @@ -0,0 +1,44 @@ +use super::{LinkArgs, LinkerFlavor, Target, TargetOptions}; + +pub fn target() -> Result { + let mut post_link_args = LinkArgs::new(); + post_link_args.insert(LinkerFlavor::Em, + vec!["-s".to_string(), + "WASM=1".to_string(), + "-s".to_string(), + "ASSERTIONS=1".to_string(), + "-s".to_string(), + "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(), + "-g3".to_string()]); + + let opts = TargetOptions { + dynamic_linking: false, + executables: true, + // Today emcc emits two files - a .js file to bootstrap and + // possibly interpret the wasm, and a .wasm file + exe_suffix: ".js".to_string(), + linker_is_gnu: true, + link_env: vec![("EMCC_WASM_BACKEND".to_string(), "1".to_string())], + allow_asm: false, + obj_is_bitcode: true, + is_like_emscripten: true, + max_atomic_width: Some(32), + post_link_args, + limit_rdylib_exports: false, + target_family: Some("unix".to_string()), + .. Default::default() + }; + Ok(Target { + llvm_target: "wasm32-unknown-unknown".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + target_os: "emscripten".to_string(), + target_env: String::new(), + target_vendor: "unknown".to_string(), + data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + arch: "wasm32".to_string(), + linker_flavor: LinkerFlavor::Em, + options: opts, + }) +} diff --git a/src/librustc_target/spec/wasm32_unknown_emscripten.rs b/src/librustc_target/spec/wasm32_unknown_emscripten.rs index 6a2c8c495372..e0df36884bf5 100644 --- a/src/librustc_target/spec/wasm32_unknown_emscripten.rs +++ b/src/librustc_target/spec/wasm32_unknown_emscripten.rs @@ -1,46 +1,45 @@ -use super::wasm32_base; -use super::{LinkArgs, LinkerFlavor, Target, TargetOptions, PanicStrategy}; +use super::{LinkArgs, LinkerFlavor, Target, TargetOptions}; pub fn target() -> Result { + // FIXME(nikic) BINARYEN_TRAP_MODE=clamp is needed to avoid trapping in our + // -Zsaturating-float-casts implementation. This can be dropped if/when + // we have native fpto[su]i.sat intrinsics, or the implementation otherwise + // stops relying on non-trapping fpto[su]i. let mut post_link_args = LinkArgs::new(); post_link_args.insert(LinkerFlavor::Em, vec!["-s".to_string(), + "BINARYEN=1".to_string(), + "-s".to_string(), "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(), "-s".to_string(), - "ASSERTIONS=1".to_string(), - "-s".to_string(), - "DISABLE_EXCEPTION_CATCHING=1".to_string(), - "-s".to_string(), - "ABORTING_MALLOC=0".to_string(), - // FIXME(tlively): Enable this linker option once libc type errors - // are resolved. See https://github.com/rust-lang/libc/pull/1478. - // "-Wl,--fatal-warnings".to_string(), - ]); + "BINARYEN_TRAP_MODE='clamp'".to_string()]); let opts = TargetOptions { - // emcc emits two files - a .js file to instantiate the wasm and supply platform - // functionality, and a .wasm file. + dynamic_linking: false, + executables: true, + // Today emcc emits two files - a .js file to bootstrap and + // possibly interpret the wasm, and a .wasm file exe_suffix: ".js".to_string(), - linker: None, linker_is_gnu: true, + allow_asm: false, + obj_is_bitcode: true, is_like_emscripten: true, - // FIXME(tlively): Emscripten supports unwinding, but we would have to pass - // -enable-emscripten-cxx-exceptions to LLVM at codegen time and merge - // https://reviews.llvm.org/rG5c3cdef84b82464756bb571c13c31cf7773860c3to use it. - panic_strategy: PanicStrategy::Abort, + max_atomic_width: Some(32), post_link_args, + limit_rdylib_exports: false, target_family: Some("unix".to_string()), - .. wasm32_base::options() + codegen_backend: "emscripten".to_string(), + .. Default::default() }; Ok(Target { - llvm_target: "wasm32-unknown-emscripten".to_string(), + llvm_target: "asmjs-unknown-emscripten".to_string(), target_endian: "little".to_string(), target_pointer_width: "32".to_string(), target_c_int_width: "32".to_string(), target_os: "emscripten".to_string(), target_env: String::new(), target_vendor: "unknown".to_string(), - data_layout: "e-m:e-p:32:32-i64:64-n32:64-S128".to_string(), + data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(), arch: "wasm32".to_string(), linker_flavor: LinkerFlavor::Em, options: opts, diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 7de2583b9f6c..da3b52afadff 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -360,7 +360,7 @@ impl<'a> fmt::Display for Html<'a> { ("target_arch", Some(arch)) => match &*arch.as_str() { "aarch64" => "AArch64", "arm" => "ARM", - "asmjs" => "JavaScript", + "asmjs" => "asm.js", "mips" => "MIPS", "mips64" => "MIPS-64", "msp430" => "MSP430", diff --git a/src/libstd/sys/unix/fast_thread_local.rs b/src/libstd/sys/unix/fast_thread_local.rs index d7e733b7fa03..952ba40ee87a 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -10,8 +10,7 @@ // fallback implementation to use as well. // // Due to rust-lang/rust#18804, make sure this is not generic! -#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit", target_os = "redox", - target_os = "emscripten"))] +#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit", target_os = "redox"))] pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) { use crate::mem; use crate::sys_common::thread_local::register_dtor_fallback; diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index e8f3434b958d..8b76080fc68c 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1478,9 +1478,9 @@ pub fn run_test( ) { let TestDescAndFn { desc, testfn } = test; - // FIXME: Re-enable emscripten once it can catch panics again - let ignore_because_no_process_support = desc.should_panic != ShouldPanic::No - && (cfg!(target_arch = "wasm32") || cfg!(target_os = "emscripten")); + let ignore_because_no_process_support = cfg!(target_arch = "wasm32") + && !cfg!(target_os = "emscripten") + && desc.should_panic != ShouldPanic::No; if force_ignore || desc.ignore || ignore_because_no_process_support { monitor_ch.send((desc, TrIgnored, None, Vec::new())).unwrap(); diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs index c3727b3013fc..b95fb5df710d 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -2,7 +2,7 @@ use super::*; use crate::test::{ filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, RunStrategy, - ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, + ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TrFailedMsg, TrIgnored, TrOk, }; use std::sync::mpsc::channel; @@ -90,9 +90,7 @@ pub fn ignored_tests_result_in_ignored() { assert!(res == TrIgnored); } -// FIXME: Re-enable emscripten once it can catch panics again #[test] -#[cfg(not(target_os = "emscripten"))] fn test_should_panic() { fn f() { panic!(); @@ -112,9 +110,7 @@ fn test_should_panic() { assert!(res == TrOk); } -// FIXME: Re-enable emscripten once it can catch panics again #[test] -#[cfg(not(target_os = "emscripten"))] fn test_should_panic_good_message() { fn f() { panic!("an error message"); @@ -134,11 +130,8 @@ fn test_should_panic_good_message() { assert!(res == TrOk); } -// FIXME: Re-enable emscripten once it can catch panics again #[test] -#[cfg(not(target_os = "emscripten"))] fn test_should_panic_bad_message() { - use crate::tests::TrFailedMsg; fn f() { panic!("an error message"); } @@ -159,9 +152,7 @@ fn test_should_panic_bad_message() { assert!(res == TrFailedMsg(format!("{} '{}'", failed_msg, expected))); } -// FIXME: Re-enable emscripten once it can catch panics again #[test] -#[cfg(not(target_os = "emscripten"))] fn test_should_panic_but_succeeds() { fn f() {} let desc = TestDescAndFn { diff --git a/src/test/codegen/c-variadic.rs b/src/test/codegen/c-variadic.rs index 7fa61d15f77c..2acf95de97ee 100644 --- a/src/test/codegen/c-variadic.rs +++ b/src/test/codegen/c-variadic.rs @@ -1,4 +1,3 @@ -// ignore-emscripten compiled with panic=abort by default // compile-flags: -C no-prepopulate-passes // ignore-tidy-linelength diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs index 49e40d5f243f..307c4e2c1e27 100644 --- a/src/test/codegen/drop.rs +++ b/src/test/codegen/drop.rs @@ -1,4 +1,3 @@ -// ignore-emscripten compiled with panic=abort by default // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/extern-functions.rs b/src/test/codegen/extern-functions.rs index 786f2c8422b7..a935d8865226 100644 --- a/src/test/codegen/extern-functions.rs +++ b/src/test/codegen/extern-functions.rs @@ -1,4 +1,3 @@ -// ignore-emscripten compiled with panic=abort by default // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/external-no-mangle-statics.rs b/src/test/codegen/external-no-mangle-statics.rs index ee61814678ce..e44373926b76 100644 --- a/src/test/codegen/external-no-mangle-statics.rs +++ b/src/test/codegen/external-no-mangle-statics.rs @@ -1,4 +1,3 @@ -// ignore-emscripten default visibility is hidden // compile-flags: -O // `#[no_mangle]`d static variables always have external linkage, i.e., no `internal` in their // definitions diff --git a/src/test/codegen/link_section.rs b/src/test/codegen/link_section.rs index 88b8692b0ac5..86c1365fdb71 100644 --- a/src/test/codegen/link_section.rs +++ b/src/test/codegen/link_section.rs @@ -1,4 +1,3 @@ -// ignore-emscripten default visibility is hidden // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/no-output-asm-is-volatile.rs b/src/test/codegen/no-output-asm-is-volatile.rs index 47b38d294174..ad497b25a9ec 100644 --- a/src/test/codegen/no-output-asm-is-volatile.rs +++ b/src/test/codegen/no-output-asm-is-volatile.rs @@ -1,5 +1,7 @@ // compile-flags: -O +// ignore-asmjs + #![feature(asm)] #![crate_type = "lib"] diff --git a/src/test/codegen/personality_lifetimes.rs b/src/test/codegen/personality_lifetimes.rs index c82ae476b1b2..05888c0e733a 100644 --- a/src/test/codegen/personality_lifetimes.rs +++ b/src/test/codegen/personality_lifetimes.rs @@ -1,5 +1,4 @@ // ignore-msvc -// ignore-emscripten compiled with panic=abort by default // compile-flags: -O -C no-prepopulate-passes diff --git a/src/test/codegen/repr-transparent-aggregates-2.rs b/src/test/codegen/repr-transparent-aggregates-2.rs index afefb9c9f71a..5521c3c849f5 100644 --- a/src/test/codegen/repr-transparent-aggregates-2.rs +++ b/src/test/codegen/repr-transparent-aggregates-2.rs @@ -1,7 +1,7 @@ // compile-flags: -C no-prepopulate-passes // ignore-aarch64 -// ignore-emscripten +// ignore-asmjs // ignore-mips64 // ignore-powerpc // ignore-powerpc64 @@ -9,6 +9,7 @@ // ignore-s390x // ignore-sparc // ignore-sparc64 +// ignore-wasm // ignore-x86 // ignore-x86_64 // See repr-transparent.rs diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs index 0a687078cd8e..acb993d51fb8 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs index 9d47339d163c..58667af7e50e 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs index 770b2a730377..affbe17d3341 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs index 33c860506668..43472d9dece8 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs index f7a8986242d1..471d49b7841e 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs index a4070317a62b..bd8ba8b6cd77 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs index 0800a498cb71..8ad9e9004c2c 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs index adc44ffd8117..ecffca960dab 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs index 9c236f196362..79e6ed54690b 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs index a922161affab..db92a94fca84 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs index 9624acb383fb..90d9ec3cedd6 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs index 7b9b1aec6c85..2761392e6a92 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs @@ -1,3 +1,4 @@ +// ignore-emscripten // min-llvm-version 7.0 // compile-flags: -C no-prepopulate-passes diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs index 6639e5d652b0..1dd2c2ccb83d 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs index 5e82ea023d8e..09f31bdd6bbd 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs index 8ca2ca860764..dc87651c2aa1 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs @@ -1,3 +1,5 @@ +// ignore-emscripten + // compile-flags: -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs index 237d15a5c68c..adee796d2475 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-arithmetic-saturating.rs @@ -119,140 +119,140 @@ extern "platform-intrinsic" { // CHECK-LABEL: @sadd_i8x2 #[no_mangle] pub unsafe fn sadd_i8x2(x: i8x2, y: i8x2) -> i8x2 { - // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{[0-9]+}}, <2 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x4 #[no_mangle] pub unsafe fn sadd_i8x4(x: i8x4, y: i8x4) -> i8x4 { - // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{[0-9]+}}, <4 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x8 #[no_mangle] pub unsafe fn sadd_i8x8(x: i8x8, y: i8x8) -> i8x8 { - // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{[0-9]+}}, <8 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x16 #[no_mangle] pub unsafe fn sadd_i8x16(x: i8x16, y: i8x16) -> i8x16 { - // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x32 #[no_mangle] pub unsafe fn sadd_i8x32(x: i8x32, y: i8x32) -> i8x32 { - // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{[0-9]+}}, <32 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i8x64 #[no_mangle] pub unsafe fn sadd_i8x64(x: i8x64, y: i8x64) -> i8x64 { - // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{[0-9]+}}, <64 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x2 #[no_mangle] pub unsafe fn sadd_i16x2(x: i16x2, y: i16x2) -> i16x2 { - // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{[0-9]+}}, <2 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x4 #[no_mangle] pub unsafe fn sadd_i16x4(x: i16x4, y: i16x4) -> i16x4 { - // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{[0-9]+}}, <4 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x8 #[no_mangle] pub unsafe fn sadd_i16x8(x: i16x8, y: i16x8) -> i16x8 { - // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x16 #[no_mangle] pub unsafe fn sadd_i16x16(x: i16x16, y: i16x16) -> i16x16 { - // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{[0-9]+}}, <16 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i16x32 #[no_mangle] pub unsafe fn sadd_i16x32(x: i16x32, y: i16x32) -> i16x32 { - // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{[0-9]+}}, <32 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i32x2 #[no_mangle] pub unsafe fn sadd_i32x2(x: i32x2, y: i32x2) -> i32x2 { - // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{[0-9]+}}, <2 x i32> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i32x4 #[no_mangle] pub unsafe fn sadd_i32x4(x: i32x4, y: i32x4) -> i32x4 { - // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i32x8 #[no_mangle] pub unsafe fn sadd_i32x8(x: i32x8, y: i32x8) -> i32x8 { - // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{[0-9]+}}, <8 x i32> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i32x16 #[no_mangle] pub unsafe fn sadd_i32x16(x: i32x16, y: i32x16) -> i32x16 { - // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i64x2 #[no_mangle] pub unsafe fn sadd_i64x2(x: i64x2, y: i64x2) -> i64x2 { - // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i64x4 #[no_mangle] pub unsafe fn sadd_i64x4(x: i64x4, y: i64x4) -> i64x4 { - // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{[0-9]+}}, <4 x i64> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i64x8 #[no_mangle] pub unsafe fn sadd_i64x8(x: i64x8, y: i64x8) -> i64x8 { - // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{[0-9]+}}, <8 x i64> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i128x2 #[no_mangle] pub unsafe fn sadd_i128x2(x: i128x2, y: i128x2) -> i128x2 { - // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{[0-9]+}}, <2 x i128> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @sadd_i128x4 #[no_mangle] pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 { - // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{[0-9]+}}, <4 x i128> %{{[0-9]+}}) simd_saturating_add(x, y) } @@ -261,140 +261,140 @@ pub unsafe fn sadd_i128x4(x: i128x4, y: i128x4) -> i128x4 { // CHECK-LABEL: @uadd_u8x2 #[no_mangle] pub unsafe fn uadd_u8x2(x: u8x2, y: u8x2) -> u8x2 { - // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{[0-9]+}}, <2 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x4 #[no_mangle] pub unsafe fn uadd_u8x4(x: u8x4, y: u8x4) -> u8x4 { - // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{[0-9]+}}, <4 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x8 #[no_mangle] pub unsafe fn uadd_u8x8(x: u8x8, y: u8x8) -> u8x8 { - // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{[0-9]+}}, <8 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x16 #[no_mangle] pub unsafe fn uadd_u8x16(x: u8x16, y: u8x16) -> u8x16 { - // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x32 #[no_mangle] pub unsafe fn uadd_u8x32(x: u8x32, y: u8x32) -> u8x32 { - // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{[0-9]+}}, <32 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u8x64 #[no_mangle] pub unsafe fn uadd_u8x64(x: u8x64, y: u8x64) -> u8x64 { - // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{[0-9]+}}, <64 x i8> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x2 #[no_mangle] pub unsafe fn uadd_u16x2(x: u16x2, y: u16x2) -> u16x2 { - // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{[0-9]+}}, <2 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x4 #[no_mangle] pub unsafe fn uadd_u16x4(x: u16x4, y: u16x4) -> u16x4 { - // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{[0-9]+}}, <4 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x8 #[no_mangle] pub unsafe fn uadd_u16x8(x: u16x8, y: u16x8) -> u16x8 { - // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x16 #[no_mangle] pub unsafe fn uadd_u16x16(x: u16x16, y: u16x16) -> u16x16 { - // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{[0-9]+}}, <16 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u16x32 #[no_mangle] pub unsafe fn uadd_u16x32(x: u16x32, y: u16x32) -> u16x32 { - // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{[0-9]+}}, <32 x i16> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u32x2 #[no_mangle] pub unsafe fn uadd_u32x2(x: u32x2, y: u32x2) -> u32x2 { - // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{[0-9]+}}, <2 x i32> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u32x4 #[no_mangle] pub unsafe fn uadd_u32x4(x: u32x4, y: u32x4) -> u32x4 { - // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u32x8 #[no_mangle] pub unsafe fn uadd_u32x8(x: u32x8, y: u32x8) -> u32x8 { - // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{[0-9]+}}, <8 x i32> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u32x16 #[no_mangle] pub unsafe fn uadd_u32x16(x: u32x16, y: u32x16) -> u32x16 { - // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u64x2 #[no_mangle] pub unsafe fn uadd_u64x2(x: u64x2, y: u64x2) -> u64x2 { - // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u64x4 #[no_mangle] pub unsafe fn uadd_u64x4(x: u64x4, y: u64x4) -> u64x4 { - // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{[0-9]+}}, <4 x i64> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u64x8 #[no_mangle] pub unsafe fn uadd_u64x8(x: u64x8, y: u64x8) -> u64x8 { - // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{[0-9]+}}, <8 x i64> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u128x2 #[no_mangle] pub unsafe fn uadd_u128x2(x: u128x2, y: u128x2) -> u128x2 { - // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{[0-9]+}}, <2 x i128> %{{[0-9]+}}) simd_saturating_add(x, y) } // CHECK-LABEL: @uadd_u128x4 #[no_mangle] pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 { - // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{[0-9]+}}, <4 x i128> %{{[0-9]+}}) simd_saturating_add(x, y) } @@ -405,140 +405,140 @@ pub unsafe fn uadd_u128x4(x: u128x4, y: u128x4) -> u128x4 { // CHECK-LABEL: @ssub_i8x2 #[no_mangle] pub unsafe fn ssub_i8x2(x: i8x2, y: i8x2) -> i8x2 { - // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{[0-9]+}}, <2 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x4 #[no_mangle] pub unsafe fn ssub_i8x4(x: i8x4, y: i8x4) -> i8x4 { - // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{[0-9]+}}, <4 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x8 #[no_mangle] pub unsafe fn ssub_i8x8(x: i8x8, y: i8x8) -> i8x8 { - // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{[0-9]+}}, <8 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x16 #[no_mangle] pub unsafe fn ssub_i8x16(x: i8x16, y: i8x16) -> i8x16 { - // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x32 #[no_mangle] pub unsafe fn ssub_i8x32(x: i8x32, y: i8x32) -> i8x32 { - // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{[0-9]+}}, <32 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i8x64 #[no_mangle] pub unsafe fn ssub_i8x64(x: i8x64, y: i8x64) -> i8x64 { - // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{[0-9]+}}, <64 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x2 #[no_mangle] pub unsafe fn ssub_i16x2(x: i16x2, y: i16x2) -> i16x2 { - // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{[0-9]+}}, <2 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x4 #[no_mangle] pub unsafe fn ssub_i16x4(x: i16x4, y: i16x4) -> i16x4 { - // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{[0-9]+}}, <4 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x8 #[no_mangle] pub unsafe fn ssub_i16x8(x: i16x8, y: i16x8) -> i16x8 { - // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x16 #[no_mangle] pub unsafe fn ssub_i16x16(x: i16x16, y: i16x16) -> i16x16 { - // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{[0-9]+}}, <16 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i16x32 #[no_mangle] pub unsafe fn ssub_i16x32(x: i16x32, y: i16x32) -> i16x32 { - // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{[0-9]+}}, <32 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i32x2 #[no_mangle] pub unsafe fn ssub_i32x2(x: i32x2, y: i32x2) -> i32x2 { - // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{[0-9]+}}, <2 x i32> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i32x4 #[no_mangle] pub unsafe fn ssub_i32x4(x: i32x4, y: i32x4) -> i32x4 { - // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i32x8 #[no_mangle] pub unsafe fn ssub_i32x8(x: i32x8, y: i32x8) -> i32x8 { - // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{[0-9]+}}, <8 x i32> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i32x16 #[no_mangle] pub unsafe fn ssub_i32x16(x: i32x16, y: i32x16) -> i32x16 { - // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i64x2 #[no_mangle] pub unsafe fn ssub_i64x2(x: i64x2, y: i64x2) -> i64x2 { - // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i64x4 #[no_mangle] pub unsafe fn ssub_i64x4(x: i64x4, y: i64x4) -> i64x4 { - // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{[0-9]+}}, <4 x i64> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i64x8 #[no_mangle] pub unsafe fn ssub_i64x8(x: i64x8, y: i64x8) -> i64x8 { - // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{[0-9]+}}, <8 x i64> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i128x2 #[no_mangle] pub unsafe fn ssub_i128x2(x: i128x2, y: i128x2) -> i128x2 { - // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{[0-9]+}}, <2 x i128> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @ssub_i128x4 #[no_mangle] pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 { - // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{[0-9]+}}, <4 x i128> %{{[0-9]+}}) simd_saturating_sub(x, y) } @@ -547,139 +547,139 @@ pub unsafe fn ssub_i128x4(x: i128x4, y: i128x4) -> i128x4 { // CHECK-LABEL: @usub_u8x2 #[no_mangle] pub unsafe fn usub_u8x2(x: u8x2, y: u8x2) -> u8x2 { - // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{[0-9]+}}, <2 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x4 #[no_mangle] pub unsafe fn usub_u8x4(x: u8x4, y: u8x4) -> u8x4 { - // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{[0-9]+}}, <4 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x8 #[no_mangle] pub unsafe fn usub_u8x8(x: u8x8, y: u8x8) -> u8x8 { - // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{[0-9]+}}, <8 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x16 #[no_mangle] pub unsafe fn usub_u8x16(x: u8x16, y: u8x16) -> u8x16 { - // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{[0-9]+}}, <16 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x32 #[no_mangle] pub unsafe fn usub_u8x32(x: u8x32, y: u8x32) -> u8x32 { - // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{[0-9]+}}, <32 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u8x64 #[no_mangle] pub unsafe fn usub_u8x64(x: u8x64, y: u8x64) -> u8x64 { - // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{[0-9]+}}, <64 x i8> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x2 #[no_mangle] pub unsafe fn usub_u16x2(x: u16x2, y: u16x2) -> u16x2 { - // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{[0-9]+}}, <2 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x4 #[no_mangle] pub unsafe fn usub_u16x4(x: u16x4, y: u16x4) -> u16x4 { - // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{[0-9]+}}, <4 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x8 #[no_mangle] pub unsafe fn usub_u16x8(x: u16x8, y: u16x8) -> u16x8 { - // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{[0-9]+}}, <8 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x16 #[no_mangle] pub unsafe fn usub_u16x16(x: u16x16, y: u16x16) -> u16x16 { - // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{[0-9]+}}, <16 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u16x32 #[no_mangle] pub unsafe fn usub_u16x32(x: u16x32, y: u16x32) -> u16x32 { - // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{[0-9]+}}, <32 x i16> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u32x2 #[no_mangle] pub unsafe fn usub_u32x2(x: u32x2, y: u32x2) -> u32x2 { - // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{[0-9]+}}, <2 x i32> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u32x4 #[no_mangle] pub unsafe fn usub_u32x4(x: u32x4, y: u32x4) -> u32x4 { - // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{[0-9]+}}, <4 x i32> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u32x8 #[no_mangle] pub unsafe fn usub_u32x8(x: u32x8, y: u32x8) -> u32x8 { - // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{[0-9]+}}, <8 x i32> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u32x16 #[no_mangle] pub unsafe fn usub_u32x16(x: u32x16, y: u32x16) -> u32x16 { - // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{[0-9]+}}, <16 x i32> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u64x2 #[no_mangle] pub unsafe fn usub_u64x2(x: u64x2, y: u64x2) -> u64x2 { - // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{[0-9]+}}, <2 x i64> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u64x4 #[no_mangle] pub unsafe fn usub_u64x4(x: u64x4, y: u64x4) -> u64x4 { - // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{[0-9]+}}, <4 x i64> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u64x8 #[no_mangle] pub unsafe fn usub_u64x8(x: u64x8, y: u64x8) -> u64x8 { - // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{[0-9]+}}, <8 x i64> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u128x2 #[no_mangle] pub unsafe fn usub_u128x2(x: u128x2, y: u128x2) -> u128x2 { - // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{[0-9]+}}, <2 x i128> %{{[0-9]+}}) simd_saturating_sub(x, y) } // CHECK-LABEL: @usub_u128x4 #[no_mangle] pub unsafe fn usub_u128x4(x: u128x4, y: u128x4) -> u128x4 { - // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{[0-9]+}}, <4 x i128> %{{[0-9]+}}) simd_saturating_sub(x, y) } diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs index 543664014868..cd8130f92314 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-bitmask.rs @@ -29,7 +29,7 @@ extern "platform-intrinsic" { // CHECK-LABEL: @bitmask_int #[no_mangle] pub unsafe fn bitmask_int(x: i32x2) -> u8 { - // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9a-z]+}}, + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9]+}}, // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2 // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8 @@ -39,7 +39,7 @@ pub unsafe fn bitmask_int(x: i32x2) -> u8 { // CHECK-LABEL: @bitmask_uint #[no_mangle] pub unsafe fn bitmask_uint(x: u32x2) -> u8 { - // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9a-z]+}}, + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9]+}}, // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> // CHECK: [[C:%[0-9]+]] = bitcast <2 x i1> [[B]] to i2 // CHECK: %{{[0-9]+}} = zext i2 [[C]] to i8 @@ -49,7 +49,7 @@ pub unsafe fn bitmask_uint(x: u32x2) -> u8 { // CHECK-LABEL: @bitmask_int16 #[no_mangle] pub unsafe fn bitmask_int16(x: i8x16) -> u16 { - // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{[0-9a-z]+}}, + // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{[0-9]+}}, // CHECK: [[B:%[0-9]+]] = trunc <16 x i8> [[A]] to <16 x i1> // CHECK: %{{[0-9]+}} = bitcast <16 x i1> [[B]] to i16 // CHECK-NOT: zext diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs index 3b1f4398f900..3389104219dd 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs @@ -1,3 +1,4 @@ +// ignore-emscripten // ignore-tidy-linelength // compile-flags: -C no-prepopulate-passes diff --git a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs index 9fce849e5238..dd0a9801bc5f 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs @@ -1,3 +1,4 @@ +// ignore-emscripten // ignore-tidy-linelength // compile-flags: -C no-prepopulate-passes diff --git a/src/test/codegen/union-abi.rs b/src/test/codegen/union-abi.rs index 98a9ff9cbe44..7339df17b057 100644 --- a/src/test/codegen/union-abi.rs +++ b/src/test/codegen/union-abi.rs @@ -1,4 +1,3 @@ -// ignore-emscripten vectors passed directly // compile-flags: -C no-prepopulate-passes // This test that using union forward the abi of the inner type, as diff --git a/src/test/compile-fail/weak-lang-item.rs b/src/test/compile-fail/weak-lang-item.rs index 3fa3822831b5..768b936dc271 100644 --- a/src/test/compile-fail/weak-lang-item.rs +++ b/src/test/compile-fail/weak-lang-item.rs @@ -1,7 +1,7 @@ // aux-build:weak-lang-items.rs // error-pattern: `#[panic_handler]` function required, but not found // error-pattern: language item required, but not found: `eh_personality` -// ignore-emscripten compiled with panic=abort, personality not required +// ignore-wasm32-bare compiled with panic=abort, personality not required #![no_std] diff --git a/src/test/incremental/change_crate_dep_kind.rs b/src/test/incremental/change_crate_dep_kind.rs index 2bcb06d6eb8b..f5d1acb621be 100644 --- a/src/test/incremental/change_crate_dep_kind.rs +++ b/src/test/incremental/change_crate_dep_kind.rs @@ -1,7 +1,6 @@ // Test that we detect changes to the `dep_kind` query. If the change is not // detected then -Zincremental-verify-ich will trigger an assertion. -// ignore-emscripten compiled with panic=abort by default // revisions:cfail1 cfail2 // compile-flags: -Z query-dep-graph -Cpanic=unwind // build-pass (FIXME(62277): could be check-pass?) diff --git a/src/test/incremental/commandline-args.rs b/src/test/incremental/commandline-args.rs index 08a0232f661f..e5b84267b290 100644 --- a/src/test/incremental/commandline-args.rs +++ b/src/test/incremental/commandline-args.rs @@ -1,7 +1,6 @@ // Test that changing a tracked commandline argument invalidates // the cache while changing an untracked one doesn't. -// ignore-asmjs wasm2js does not support source maps yet // revisions:rpass1 rpass2 rpass3 // compile-flags: -Z query-dep-graph diff --git a/src/test/incremental/remapped_paths_cc/main.rs b/src/test/incremental/remapped_paths_cc/main.rs index b01f02444eae..12411a928799 100644 --- a/src/test/incremental/remapped_paths_cc/main.rs +++ b/src/test/incremental/remapped_paths_cc/main.rs @@ -2,7 +2,6 @@ // compile-flags: -Z query-dep-graph -g // aux-build:extern_crate.rs -// ignore-asmjs wasm2js does not support source maps yet // This test case makes sure that we detect if paths emitted into debuginfo // are changed, even when the change happens in an external crate. diff --git a/src/test/incremental/span_hash_stable/main.rs b/src/test/incremental/span_hash_stable/main.rs index 367416430f86..f1d7de145593 100644 --- a/src/test/incremental/span_hash_stable/main.rs +++ b/src/test/incremental/span_hash_stable/main.rs @@ -3,7 +3,6 @@ // the spans and this test makes sure that we handle them correctly by hashing // file:line:column instead of raw byte offset. -// ignore-asmjs wasm2js does not support source maps yet // revisions:rpass1 rpass2 // compile-flags: -g -Z query-dep-graph diff --git a/src/test/incremental/spans_in_type_debuginfo.rs b/src/test/incremental/spans_in_type_debuginfo.rs index f5cae15a4bc7..8ed469db6e63 100644 --- a/src/test/incremental/spans_in_type_debuginfo.rs +++ b/src/test/incremental/spans_in_type_debuginfo.rs @@ -1,7 +1,6 @@ // Test that moving a type definition within a source file does not affect // re-compilation. -// ignore-asmjs wasm2js does not support source maps yet // revisions:rpass1 rpass2 // compile-flags: -Z query-dep-graph -g diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs index e6fdc7cb3a0f..87c97ba06c46 100644 --- a/src/test/incremental/spans_significant_w_debuginfo.rs +++ b/src/test/incremental/spans_significant_w_debuginfo.rs @@ -3,7 +3,6 @@ // revisions:rpass1 rpass2 -// ignore-asmjs wasm2js does not support source maps yet // compile-flags: -g -Z query-dep-graph #![feature(rustc_attrs)] diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs index 4b66c07b0934..8dc6b73edf6d 100644 --- a/src/test/mir-opt/box_expr.rs +++ b/src/test/mir-opt/box_expr.rs @@ -1,4 +1,4 @@ -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(box_syntax)] diff --git a/src/test/mir-opt/generator-storage-dead-unwind.rs b/src/test/mir-opt/generator-storage-dead-unwind.rs index b595c100039d..109304d6d22c 100644 --- a/src/test/mir-opt/generator-storage-dead-unwind.rs +++ b/src/test/mir-opt/generator-storage-dead-unwind.rs @@ -1,4 +1,4 @@ -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // Test that we generate StorageDead on unwind paths for generators. // diff --git a/src/test/mir-opt/issue-41110.rs b/src/test/mir-opt/issue-41110.rs index 8824496fdb07..e73390f52b5d 100644 --- a/src/test/mir-opt/issue-41110.rs +++ b/src/test/mir-opt/issue-41110.rs @@ -1,4 +1,4 @@ -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // check that we don't emit multiple drop flags when they are not needed. diff --git a/src/test/mir-opt/issue-62289.rs b/src/test/mir-opt/issue-62289.rs index 93250fd48d82..a3b517e9bca8 100644 --- a/src/test/mir-opt/issue-62289.rs +++ b/src/test/mir-opt/issue-62289.rs @@ -1,7 +1,7 @@ // check that we don't forget to drop the Box if we early return before // initializing it // ignore-tidy-linelength -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(box_syntax)] diff --git a/src/test/mir-opt/no-spurious-drop-after-call.rs b/src/test/mir-opt/no-spurious-drop-after-call.rs index 370cd593b02b..782bc31186ca 100644 --- a/src/test/mir-opt/no-spurious-drop-after-call.rs +++ b/src/test/mir-opt/no-spurious-drop-after-call.rs @@ -1,4 +1,4 @@ -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // Test that after the call to `std::mem::drop` we do not generate a // MIR drop of the argument. (We used to have a `DROP(_2)` in the code diff --git a/src/test/mir-opt/packed-struct-drop-aligned.rs b/src/test/mir-opt/packed-struct-drop-aligned.rs index eaa1fbd69ecc..da73cc96348f 100644 --- a/src/test/mir-opt/packed-struct-drop-aligned.rs +++ b/src/test/mir-opt/packed-struct-drop-aligned.rs @@ -1,4 +1,4 @@ -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default fn main() { let mut x = Packed(Aligned(Droppy(0))); diff --git a/src/test/mir-opt/remove_fake_borrows.rs b/src/test/mir-opt/remove_fake_borrows.rs index 71beaa736639..3245d38b2580 100644 --- a/src/test/mir-opt/remove_fake_borrows.rs +++ b/src/test/mir-opt/remove_fake_borrows.rs @@ -1,6 +1,6 @@ // Test that the fake borrows for matches are removed after borrow checking. -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare fn match_guard(x: Option<&&i32>, c: bool) -> i32 { match x { diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index a0bdfb3ab8ba..db36a1fab5f2 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -1,4 +1,4 @@ -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // ignore-tidy-linelength // compile-flags: -Z mir-emit-retag -Z mir-opt-level=0 -Z span_free_formats diff --git a/src/test/run-make/wasm-custom-section/Makefile b/src/test/run-make/wasm-custom-section/Makefile index 2f48b852566e..7c64dc58bf79 100644 --- a/src/test/run-make/wasm-custom-section/Makefile +++ b/src/test/run-make/wasm-custom-section/Makefile @@ -1,6 +1,6 @@ -include ../../run-make-fulldeps/tools.mk -# only-wasm32-bare +# only-wasm32 all: $(RUSTC) foo.rs --target wasm32-unknown-unknown diff --git a/src/test/run-make/wasm-custom-sections-opt/Makefile b/src/test/run-make/wasm-custom-sections-opt/Makefile index 76698c0aae3b..fec7643d20c5 100644 --- a/src/test/run-make/wasm-custom-sections-opt/Makefile +++ b/src/test/run-make/wasm-custom-sections-opt/Makefile @@ -1,6 +1,6 @@ -include ../../run-make-fulldeps/tools.mk -# only-wasm32-bare +# only-wasm32 all: $(RUSTC) foo.rs -O --target wasm32-unknown-unknown diff --git a/src/test/run-make/wasm-export-all-symbols/Makefile b/src/test/run-make/wasm-export-all-symbols/Makefile index 7e47ba4850e3..15403d8d4109 100644 --- a/src/test/run-make/wasm-export-all-symbols/Makefile +++ b/src/test/run-make/wasm-export-all-symbols/Makefile @@ -1,6 +1,6 @@ -include ../../run-make-fulldeps/tools.mk -# only-wasm32-bare +# only-wasm32 all: $(RUSTC) bar.rs --target wasm32-unknown-unknown diff --git a/src/test/run-make/wasm-import-module/Makefile b/src/test/run-make/wasm-import-module/Makefile index fe63e66f242b..255d8f1ef0e6 100644 --- a/src/test/run-make/wasm-import-module/Makefile +++ b/src/test/run-make/wasm-import-module/Makefile @@ -1,6 +1,6 @@ -include ../../run-make-fulldeps/tools.mk - # only-wasm32-bare + # only-wasm32 all: $(RUSTC) foo.rs --target wasm32-unknown-unknown diff --git a/src/test/run-make/wasm-panic-small/Makefile b/src/test/run-make/wasm-panic-small/Makefile index 68397e4bc6e1..b9141f93d538 100644 --- a/src/test/run-make/wasm-panic-small/Makefile +++ b/src/test/run-make/wasm-panic-small/Makefile @@ -1,6 +1,6 @@ -include ../../run-make-fulldeps/tools.mk -# only-wasm32-bare +# only-wasm32 all: $(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg a diff --git a/src/test/run-make/wasm-symbols-not-exported/Makefile b/src/test/run-make/wasm-symbols-not-exported/Makefile index 62bd0f0872eb..b17e04b77177 100644 --- a/src/test/run-make/wasm-symbols-not-exported/Makefile +++ b/src/test/run-make/wasm-symbols-not-exported/Makefile @@ -1,6 +1,6 @@ -include ../../run-make-fulldeps/tools.mk -# only-wasm32-bare +# only-wasm32 all: $(RUSTC) foo.rs --target wasm32-unknown-unknown diff --git a/src/test/run-make/wasm-symbols-not-imported/Makefile b/src/test/run-make/wasm-symbols-not-imported/Makefile index 7a923375c181..b8f64e06f31e 100644 --- a/src/test/run-make/wasm-symbols-not-imported/Makefile +++ b/src/test/run-make/wasm-symbols-not-imported/Makefile @@ -1,6 +1,6 @@ -include ../../run-make-fulldeps/tools.mk -# only-wasm32-bare +# only-wasm32 all: $(RUSTC) foo.rs --target wasm32-unknown-unknown diff --git a/src/test/ui/abi/statics/static-mut-foreign.rs b/src/test/ui/abi/statics/static-mut-foreign.rs index b30e8f00e403..5d6fa416b989 100644 --- a/src/test/ui/abi/statics/static-mut-foreign.rs +++ b/src/test/ui/abi/statics/static-mut-foreign.rs @@ -5,10 +5,6 @@ // ignore-wasm32-bare no libc to test ffi with -// FIXME: This will work on emscripten once libc is updated to include -// rust-lang/libc/#1478 -// ignore-emscripten libc type mismatch - #![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/async-await/async-fn-size-moved-locals.rs b/src/test/ui/async-await/async-fn-size-moved-locals.rs index b63d5408a714..3ffcbb58595e 100644 --- a/src/test/ui/async-await/async-fn-size-moved-locals.rs +++ b/src/test/ui/async-await/async-fn-size-moved-locals.rs @@ -7,7 +7,7 @@ // // See issue #59123 for a full explanation. -// ignore-emscripten (sizes don't match) +// ignore-wasm32-bare (sizes don't match) // run-pass // edition:2018 diff --git a/src/test/ui/async-await/issue-60709.rs b/src/test/ui/async-await/issue-60709.rs index 61f6ed1b7b2c..9ee419c4a56f 100644 --- a/src/test/ui/async-await/issue-60709.rs +++ b/src/test/ui/async-await/issue-60709.rs @@ -3,7 +3,6 @@ // compile-flags: -Copt-level=z -Cdebuginfo=2 --edition=2018 // run-pass -// ignore-asmjs wasm2js does not support source maps yet use std::future::Future; use std::task::Poll; diff --git a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs index 4e0a238c5d48..ea4a9e5afa50 100644 --- a/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs +++ b/src/test/ui/binding/fn-arg-incomplete-pattern-drop-order.rs @@ -2,7 +2,7 @@ // Check that partially moved from function parameters are dropped after the // named bindings that move from them. -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default use std::{panic, cell::RefCell}; diff --git a/src/test/ui/binding/match-arm-statics.rs b/src/test/ui/binding/match-arm-statics.rs index e6d17def1477..5f7e357eeb2a 100644 --- a/src/test/ui/binding/match-arm-statics.rs +++ b/src/test/ui/binding/match-arm-statics.rs @@ -1,7 +1,6 @@ // run-pass #![allow(dead_code)] // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet #[derive(PartialEq, Eq)] struct NewBool(bool); diff --git a/src/test/ui/builtin-clone-unwind.rs b/src/test/ui/builtin-clone-unwind.rs index 1fd91440a788..339bcfa1060a 100644 --- a/src/test/ui/builtin-clone-unwind.rs +++ b/src/test/ui/builtin-clone-unwind.rs @@ -2,7 +2,7 @@ #![allow(unused_variables)] #![allow(unused_imports)] -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // Test that builtin implementations of `Clone` cleanup everything // in case of unwinding. diff --git a/src/test/ui/catch-unwind-bang.rs b/src/test/ui/catch-unwind-bang.rs index c2c21bca7ef7..f181991713b2 100644 --- a/src/test/ui/catch-unwind-bang.rs +++ b/src/test/ui/catch-unwind-bang.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default fn worker() -> ! { panic!() diff --git a/src/test/ui/consts/const-int-saturating-arith.rs b/src/test/ui/consts/const-int-saturating-arith.rs index d0a3eccd1776..394d6c17f5ad 100644 --- a/src/test/ui/consts/const-int-saturating-arith.rs +++ b/src/test/ui/consts/const-int-saturating-arith.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-emscripten no i128 support #![feature(const_saturating_int_methods)] const INT_U32_NO: u32 = (42 as u32).saturating_add(2); diff --git a/src/test/ui/debuginfo-lto.rs b/src/test/ui/debuginfo-lto.rs index 43f75b0344be..e4beee9e737b 100644 --- a/src/test/ui/debuginfo-lto.rs +++ b/src/test/ui/debuginfo-lto.rs @@ -7,7 +7,6 @@ // aux-build:debuginfo-lto-aux.rs // compile-flags: -C lto -g // no-prefer-dynamic -// ignore-asmjs wasm2js does not support source maps yet extern crate debuginfo_lto_aux; diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index bec86d6465ae..91063edf0f6c 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -5,7 +5,7 @@ // run-pass // edition:2018 -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(slice_patterns)] #![allow(unused)] diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 7fd3f420a6d5..8516bc3d9642 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -2,7 +2,7 @@ #![allow(unused_assignments)] #![allow(unused_variables)] -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait, untagged_unions)] #![feature(slice_patterns)] diff --git a/src/test/ui/extern/extern-const.fixed b/src/test/ui/extern/extern-const.fixed index 9d96b4f63fb6..0eec9fb3ee64 100644 --- a/src/test/ui/extern/extern-const.fixed +++ b/src/test/ui/extern/extern-const.fixed @@ -5,8 +5,7 @@ // compile. To sidestep this by using one that *is* defined. // run-rustfix -// ignore-wasm32-bare no external library to link to. -// ignore-asmjs wasm2js does not support source maps yet +// ignore-wasm32 no external library to link to. // compile-flags: -g #![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/extern/extern-const.rs b/src/test/ui/extern/extern-const.rs index 7cef5b3497b5..ca5d7ddf27e3 100644 --- a/src/test/ui/extern/extern-const.rs +++ b/src/test/ui/extern/extern-const.rs @@ -5,8 +5,7 @@ // compile. To sidestep this by using one that *is* defined. // run-rustfix -// ignore-wasm32-bare no external library to link to. -// ignore-asmjs wasm2js does not support source maps yet +// ignore-wasm32 no external library to link to. // compile-flags: -g #![feature(rustc_private)] extern crate libc; diff --git a/src/test/ui/extern/extern-const.stderr b/src/test/ui/extern/extern-const.stderr index 258202b6903d..77406be2095c 100644 --- a/src/test/ui/extern/extern-const.stderr +++ b/src/test/ui/extern/extern-const.stderr @@ -1,5 +1,5 @@ error: extern items cannot be `const` - --> $DIR/extern-const.rs:16:5 + --> $DIR/extern-const.rs:15:5 | LL | const rust_dbg_static_mut: libc::c_int; | ^^^^^ help: try using a static value: `static` diff --git a/src/test/ui/generator/issue-58888.rs b/src/test/ui/generator/issue-58888.rs index d42d09d401e8..43b37a9afc2c 100644 --- a/src/test/ui/generator/issue-58888.rs +++ b/src/test/ui/generator/issue-58888.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/panic-drops.rs b/src/test/ui/generator/panic-drops.rs index b1a5cc67e86b..5ac97585f4b5 100644 --- a/src/test/ui/generator/panic-drops.rs +++ b/src/test/ui/generator/panic-drops.rs @@ -1,6 +1,6 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled as panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/panic-safe.rs b/src/test/ui/generator/panic-safe.rs index 06c026180190..5f6778674dce 100644 --- a/src/test/ui/generator/panic-safe.rs +++ b/src/test/ui/generator/panic-safe.rs @@ -1,6 +1,6 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/resume-after-return.rs b/src/test/ui/generator/resume-after-return.rs index ab18be58155d..71a68ff684af 100644 --- a/src/test/ui/generator/resume-after-return.rs +++ b/src/test/ui/generator/resume-after-return.rs @@ -1,6 +1,6 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(generators, generator_trait)] diff --git a/src/test/ui/generator/size-moved-locals.rs b/src/test/ui/generator/size-moved-locals.rs index 2864fbb2f3c8..01db971434bb 100644 --- a/src/test/ui/generator/size-moved-locals.rs +++ b/src/test/ui/generator/size-moved-locals.rs @@ -11,7 +11,6 @@ // edition:2018 // ignore-wasm32 issue #62807 -// ignore-asmjs issue #62807 #![feature(generators, generator_trait)] diff --git a/src/test/ui/intrinsics/intrinsics-integer.rs b/src/test/ui/intrinsics/intrinsics-integer.rs index bac6c8d872b4..0154f0499502 100644 --- a/src/test/ui/intrinsics/intrinsics-integer.rs +++ b/src/test/ui/intrinsics/intrinsics-integer.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-emscripten no i128 support #![feature(intrinsics)] diff --git a/src/test/ui/issues/issue-14875.rs b/src/test/ui/issues/issue-14875.rs index 29e974ad83d1..a2fd79624582 100644 --- a/src/test/ui/issues/issue-14875.rs +++ b/src/test/ui/issues/issue-14875.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare always compiled as panic=abort right now // Check that values are not leaked when a dtor panics (#14875) diff --git a/src/test/ui/issues/issue-23477.rs b/src/test/ui/issues/issue-23477.rs index 988ebe03ccf6..1ce05ba390d7 100644 --- a/src/test/ui/issues/issue-23477.rs +++ b/src/test/ui/issues/issue-23477.rs @@ -1,5 +1,4 @@ // build-pass -// ignore-asmjs wasm2js does not support source maps yet // compile-flags: -g pub struct Dst { diff --git a/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs b/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs index f08bcdfe6d16..773792c7a3f1 100644 --- a/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs +++ b/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs @@ -1,7 +1,6 @@ // run-pass // aux-build:issue-24687-lib.rs // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet extern crate issue_24687_lib as d; diff --git a/src/test/ui/issues/issue-24945-repeat-dash-opts.rs b/src/test/ui/issues/issue-24945-repeat-dash-opts.rs index 0f92fc2f7f31..cf3834952c6a 100644 --- a/src/test/ui/issues/issue-24945-repeat-dash-opts.rs +++ b/src/test/ui/issues/issue-24945-repeat-dash-opts.rs @@ -3,7 +3,6 @@ // as options to the compiler. // compile-flags:-g -g -O -O -// ignore-asmjs wasm2js does not support source maps yet fn main() { assert_eq!(1, 1); diff --git a/src/test/ui/issues/issue-26484.rs b/src/test/ui/issues/issue-26484.rs index 2a8750d3e431..3b40b3dd8f07 100644 --- a/src/test/ui/issues/issue-26484.rs +++ b/src/test/ui/issues/issue-26484.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet fn helper bool>(_f: F) { print!(""); diff --git a/src/test/ui/issues/issue-29948.rs b/src/test/ui/issues/issue-29948.rs index 5237a2f67bdd..8ede8143ea65 100644 --- a/src/test/ui/issues/issue-29948.rs +++ b/src/test/ui/issues/issue-29948.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default use std::panic; diff --git a/src/test/ui/issues/issue-33096.rs b/src/test/ui/issues/issue-33096.rs index 2501e1430b3d..f0b472e2fe82 100644 --- a/src/test/ui/issues/issue-33096.rs +++ b/src/test/ui/issues/issue-33096.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet use std::ops::Deref; diff --git a/src/test/ui/issues/issue-33992.rs b/src/test/ui/issues/issue-33992.rs index a6b137ba6459..94fccff9fc65 100644 --- a/src/test/ui/issues/issue-33992.rs +++ b/src/test/ui/issues/issue-33992.rs @@ -1,7 +1,7 @@ // run-pass // ignore-windows // ignore-macos -// ignore-emscripten common linkage not implemented right now +// ignore-wasm32-bare common linkage not implemented right now #![feature(linkage)] diff --git a/src/test/ui/issues/issue-34569.rs b/src/test/ui/issues/issue-34569.rs index 88dcdd411380..1f68560509e8 100644 --- a/src/test/ui/issues/issue-34569.rs +++ b/src/test/ui/issues/issue-34569.rs @@ -1,6 +1,5 @@ // run-pass // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet // In this test we just want to make sure that the code below does not lead to // a debuginfo verification assertion during compilation. This was caused by the diff --git a/src/test/ui/issues/issue-36856.rs b/src/test/ui/issues/issue-36856.rs index 5657ba69f944..f2dfaf3dd367 100644 --- a/src/test/ui/issues/issue-36856.rs +++ b/src/test/ui/issues/issue-36856.rs @@ -2,7 +2,6 @@ // Regression test for #36856. // compile-flags:-g -// ignore-asmjs wasm2js does not support source maps yet fn g() -> bool { false diff --git a/src/test/ui/issues/issue-42210.rs b/src/test/ui/issues/issue-42210.rs index 01a5d563639b..318e3099f98b 100644 --- a/src/test/ui/issues/issue-42210.rs +++ b/src/test/ui/issues/issue-42210.rs @@ -2,7 +2,6 @@ // Regression test for #42210. // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet trait Foo { fn foo() { } diff --git a/src/test/ui/issues/issue-43853.rs b/src/test/ui/issues/issue-43853.rs index 2a932db05af2..47c3ab59aa2e 100644 --- a/src/test/ui/issues/issue-43853.rs +++ b/src/test/ui/issues/issue-43853.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default use std::panic; diff --git a/src/test/ui/issues/issue-45731.rs b/src/test/ui/issues/issue-45731.rs index 5c5ac59873a3..d20c07276a8c 100644 --- a/src/test/ui/issues/issue-45731.rs +++ b/src/test/ui/issues/issue-45731.rs @@ -1,7 +1,6 @@ // run-pass #![allow(unused_variables)] // compile-flags:--test -g -// ignore-asmjs wasm2js does not support source maps yet #[cfg(target_os = "macos")] #[test] diff --git a/src/test/ui/issues/issue-46519.rs b/src/test/ui/issues/issue-46519.rs index 40c3117f01ce..461ea2498b0d 100644 --- a/src/test/ui/issues/issue-46519.rs +++ b/src/test/ui/issues/issue-46519.rs @@ -1,8 +1,6 @@ // run-pass // compile-flags:--test -O -// ignore-emscripten compiled with panic=abort by default - #[test] #[should_panic(expected = "creating inhabited type")] fn test() { diff --git a/src/test/ui/issues/issue-48508.rs b/src/test/ui/issues/issue-48508.rs index b7aa64228763..385192b882ba 100644 --- a/src/test/ui/issues/issue-48508.rs +++ b/src/test/ui/issues/issue-48508.rs @@ -8,7 +8,6 @@ // compile-flags:-g // ignore-pretty issue #37195 -// ignore-asmjs wasm2js does not support source maps yet #![feature(non_ascii_idents)] diff --git a/src/test/ui/issues/issue-49579.rs b/src/test/ui/issues/issue-49579.rs index 767e06c4e90c..79cc107d4fec 100644 --- a/src/test/ui/issues/issue-49579.rs +++ b/src/test/ui/issues/issue-49579.rs @@ -1,4 +1,5 @@ // build-pass (FIXME(62277): could be check-pass?) +// ignore-emscripten no i128 support fn fibs(n: u32) -> impl Iterator { (0 .. n) diff --git a/src/test/ui/issues/issue-58463.rs b/src/test/ui/issues/issue-58463.rs index af93f76221d4..8ab845366b7b 100644 --- a/src/test/ui/issues/issue-58463.rs +++ b/src/test/ui/issues/issue-58463.rs @@ -1,7 +1,5 @@ // run-pass // compile-flags:-C debuginfo=2 -// ignore-asmjs wasm2js does not support source maps yet - fn foo() -> impl Copy { foo } diff --git a/src/test/ui/iterators/iter-count-overflow-debug.rs b/src/test/ui/iterators/iter-count-overflow-debug.rs index fdd285dcad2a..d66120357508 100644 --- a/src/test/ui/iterators/iter-count-overflow-debug.rs +++ b/src/test/ui/iterators/iter-count-overflow-debug.rs @@ -1,6 +1,6 @@ // run-pass // only-32bit too impatient for 2⁶⁴ items -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes -C opt-level=3 use std::panic; diff --git a/src/test/ui/iterators/iter-position-overflow-debug.rs b/src/test/ui/iterators/iter-position-overflow-debug.rs index b578999af8e9..f1eded31702c 100644 --- a/src/test/ui/iterators/iter-position-overflow-debug.rs +++ b/src/test/ui/iterators/iter-position-overflow-debug.rs @@ -1,6 +1,6 @@ // run-pass // only-32bit too impatient for 2⁶⁴ items -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes -C opt-level=3 use std::panic; diff --git a/src/test/ui/iterators/iter-step-overflow-debug.rs b/src/test/ui/iterators/iter-step-overflow-debug.rs index 3872a03b6825..5d67c7cbb425 100644 --- a/src/test/ui/iterators/iter-step-overflow-debug.rs +++ b/src/test/ui/iterators/iter-step-overflow-debug.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes use std::panic; diff --git a/src/test/ui/iterators/iter-sum-overflow-debug.rs b/src/test/ui/iterators/iter-sum-overflow-debug.rs index 4a9e8cdb72e7..ee4ab4d24c6a 100644 --- a/src/test/ui/iterators/iter-sum-overflow-debug.rs +++ b/src/test/ui/iterators/iter-sum-overflow-debug.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C debug_assertions=yes use std::panic; diff --git a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs index 6bd1425e3246..429f8e0bc964 100644 --- a/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs +++ b/src/test/ui/iterators/iter-sum-overflow-overflow-checks.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: -C overflow-checks use std::panic; diff --git a/src/test/ui/macros/macro-comma-behavior-rpass.rs b/src/test/ui/macros/macro-comma-behavior-rpass.rs index 1c791bb1ca3d..9f1a31d1ae27 100644 --- a/src/test/ui/macros/macro-comma-behavior-rpass.rs +++ b/src/test/ui/macros/macro-comma-behavior-rpass.rs @@ -13,8 +13,6 @@ // compile-flags: --test -C debug_assertions=yes // revisions: std core -// ignore-emscripten compiled with panic=abort by default - #![cfg_attr(core, no_std)] #[cfg(std)] use std::fmt; diff --git a/src/test/ui/mir/mir_calls_to_shims.rs b/src/test/ui/mir/mir_calls_to_shims.rs index de8d958af45e..6f13d5612ce5 100644 --- a/src/test/ui/mir/mir_calls_to_shims.rs +++ b/src/test/ui/mir/mir_calls_to_shims.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![feature(fn_traits)] #![feature(never_type)] diff --git a/src/test/ui/mir/mir_drop_order.rs b/src/test/ui/mir/mir_drop_order.rs index 2bc5cf1c9763..2949437b1e4b 100644 --- a/src/test/ui/mir/mir_drop_order.rs +++ b/src/test/ui/mir/mir_drop_order.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default use std::cell::RefCell; use std::panic; diff --git a/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs b/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs index ced3c61ec162..d210abdf499d 100644 --- a/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs +++ b/src/test/ui/numbers-arithmetic/float-int-invalid-const-cast.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-emscripten no i128 support #![deny(const_err)] diff --git a/src/test/ui/numbers-arithmetic/i128.rs b/src/test/ui/numbers-arithmetic/i128.rs index ef558c0aa0c0..ea0ef95e4f1a 100644 --- a/src/test/ui/numbers-arithmetic/i128.rs +++ b/src/test/ui/numbers-arithmetic/i128.rs @@ -1,6 +1,9 @@ // run-pass #![allow(overflowing_literals)] +// ignore-emscripten i128 doesn't work + + #![feature(test)] extern crate test; diff --git a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs index c1959866e5c2..e9927304f23f 100644 --- a/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs +++ b/src/test/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs @@ -1,6 +1,6 @@ // run-pass // compile-flags: -C debug_assertions=yes -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // ignore-emscripten dies with an LLVM error use std::panic; diff --git a/src/test/ui/numbers-arithmetic/u128-as-f32.rs b/src/test/ui/numbers-arithmetic/u128-as-f32.rs index 2671a267f4a8..bef7deb62760 100644 --- a/src/test/ui/numbers-arithmetic/u128-as-f32.rs +++ b/src/test/ui/numbers-arithmetic/u128-as-f32.rs @@ -1,4 +1,5 @@ // run-pass +// ignore-emscripten u128 not supported #![feature(test)] #![deny(overflowing_literals)] diff --git a/src/test/ui/numbers-arithmetic/u128.rs b/src/test/ui/numbers-arithmetic/u128.rs index 0b2305c6e8b1..939407163237 100644 --- a/src/test/ui/numbers-arithmetic/u128.rs +++ b/src/test/ui/numbers-arithmetic/u128.rs @@ -1,4 +1,6 @@ // run-pass +// ignore-emscripten u128 not supported + #![feature(test)] diff --git a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs index 6dcb852a3669..5d72771c2dcf 100644 --- a/src/test/ui/panic-runtime/transitive-link-a-bunch.rs +++ b/src/test/ui/panic-runtime/transitive-link-a-bunch.rs @@ -4,7 +4,7 @@ // aux-build:wants-panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs // error-pattern: is not compiled with this crate's panic strategy `unwind` -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![no_std] #![no_main] diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort.rs b/src/test/ui/panic-runtime/want-unwind-got-abort.rs index e7811d40b5b9..4c25c09d6438 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort.rs @@ -1,7 +1,7 @@ // error-pattern:is incompatible with this crate's strategy of `unwind` // aux-build:panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![no_std] #![no_main] diff --git a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs index 44671796c01a..478af451e7f6 100644 --- a/src/test/ui/panic-runtime/want-unwind-got-abort2.rs +++ b/src/test/ui/panic-runtime/want-unwind-got-abort2.rs @@ -2,7 +2,7 @@ // aux-build:panic-runtime-abort.rs // aux-build:wants-panic-runtime-abort.rs // aux-build:panic-runtime-lang-items.rs -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![no_std] #![no_main] diff --git a/src/test/ui/panic-uninitialized-zeroed.rs b/src/test/ui/panic-uninitialized-zeroed.rs index 72b844d8b488..b0d662956180 100644 --- a/src/test/ui/panic-uninitialized-zeroed.rs +++ b/src/test/ui/panic-uninitialized-zeroed.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare always compiled as panic=abort right now and this requires unwinding // This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results // in a runtime panic. diff --git a/src/test/ui/proc-macro/expand-with-a-macro.rs b/src/test/ui/proc-macro/expand-with-a-macro.rs index 690a76ef3e0a..418178d0f0ea 100644 --- a/src/test/ui/proc-macro/expand-with-a-macro.rs +++ b/src/test/ui/proc-macro/expand-with-a-macro.rs @@ -1,7 +1,7 @@ // run-pass // aux-build:expand-with-a-macro.rs -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![deny(warnings)] diff --git a/src/test/ui/reachable-unnameable-items.rs b/src/test/ui/reachable-unnameable-items.rs index 26c51efea1e1..f1e53a0d8b42 100644 --- a/src/test/ui/reachable-unnameable-items.rs +++ b/src/test/ui/reachable-unnameable-items.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // aux-build:reachable-unnameable-items.rs extern crate reachable_unnameable_items; diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs index c8e8b9dcfc6a..39825c4f9a93 100644 --- a/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs +++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-in-test.rs @@ -1,8 +1,6 @@ // compile-flags: --test // run-pass -// ignore-emscripten compiled with panic=abort by default - #![feature(test)] extern crate test; diff --git a/src/test/ui/rfcs/rfc1857-drop-order.rs b/src/test/ui/rfcs/rfc1857-drop-order.rs index b10b6ec11b53..7923aa7c0e22 100644 --- a/src/test/ui/rfcs/rfc1857-drop-order.rs +++ b/src/test/ui/rfcs/rfc1857-drop-order.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default #![allow(dead_code, unreachable_code)] diff --git a/src/test/ui/sepcomp/sepcomp-lib-lto.rs b/src/test/ui/sepcomp/sepcomp-lib-lto.rs index 51a572899f81..164ae79c254f 100644 --- a/src/test/ui/sepcomp/sepcomp-lib-lto.rs +++ b/src/test/ui/sepcomp/sepcomp-lib-lto.rs @@ -4,7 +4,6 @@ // aux-build:sepcomp_lib.rs // compile-flags: -C lto -g -// ignore-asmjs wasm2js does not support source maps yet // no-prefer-dynamic extern crate sepcomp_lib; diff --git a/src/test/ui/test-attrs/test-allow-fail-attr.rs b/src/test/ui/test-attrs/test-allow-fail-attr.rs index 55b743ab7c7e..1a478460efc6 100644 --- a/src/test/ui/test-attrs/test-allow-fail-attr.rs +++ b/src/test/ui/test-attrs/test-allow-fail-attr.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: --test #![feature(allow_fail)] diff --git a/src/test/ui/test-attrs/test-should-fail-good-message.rs b/src/test/ui/test-attrs/test-should-fail-good-message.rs index 2284953fbbe9..9fa759f9eb48 100644 --- a/src/test/ui/test-attrs/test-should-fail-good-message.rs +++ b/src/test/ui/test-attrs/test-should-fail-good-message.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32-bare compiled with panic=abort by default // compile-flags: --test #[test] #[should_panic(expected = "foo")] diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs b/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs index 5d1e00d2d353..f86499e2e3f8 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs +++ b/src/test/ui/unboxed-closures/unboxed-closures-unique-type-id.rs @@ -10,7 +10,6 @@ // This is a regression test for issue #17021. // // compile-flags: -g -// ignore-asmjs wasm2js does not support source maps yet use std::ptr; diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 030948850658..df56448dd225 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -141,10 +141,7 @@ impl EarlyProps { if config.target == "wasm32-unknown-unknown" && config.parse_check_run_results(ln) { props.ignore = Ignore::Ignore; } - // FIXME: Re-enable run-fail once panics are handled correctly - if config.target.contains("emscripten") && config.mode == common::RunFail { - props.ignore = Ignore::Ignore; - } + } if (config.mode == common::DebugInfoGdb || config.mode == common::DebugInfoGdbLldb) && From 5880ce396832fd94efb1fc90f2682f209712ba24 Mon Sep 17 00:00:00 2001 From: ben Date: Sun, 6 Oct 2019 19:56:05 +1300 Subject: [PATCH 102/545] Fix const arguments not displaying in types mismatch diagnostic. --- src/librustc/infer/error_reporting/mod.rs | 19 ++++++++++++++++++- .../slice-const-param-mismatch.stderr | 12 ++++++------ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index d31b527a55b6..f1192c7ce10a 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -935,6 +935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .filter(|(a, b)| a == b) .count(); let len = sub1.len() - common_default_params; + let consts_offset = len - sub1.consts().count(); // Only draw `<...>` if there're lifetime/type arguments. if len > 0 { @@ -981,7 +982,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // ^ elided type as this type argument was the same in both sides let type_arguments = sub1.types().zip(sub2.types()); let regions_len = sub1.regions().count(); - for (i, (ta1, ta2)) in type_arguments.take(len).enumerate() { + let num_display_types = consts_offset - regions_len; + for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() { let i = i + regions_len; if ta1 == ta2 { values.0.push_normal("_"); @@ -994,6 +996,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.push_comma(&mut values.0, &mut values.1, len, i); } + // Do the same for const arguments, if they are equal, do not highlight and + // elide them from the output. + let const_arguments = sub1.consts().zip(sub2.consts()); + for (i, (ca1, ca2)) in const_arguments.enumerate() { + let i = i + consts_offset; + if ca1 == ca2 { + values.0.push_normal("_"); + values.1.push_normal("_"); + } else { + values.0.push_highlighted(ca1.to_string()); + values.1.push_highlighted(ca2.to_string()); + } + self.push_comma(&mut values.0, &mut values.1, len, i); + } + // Close the type argument bracket. // Only draw `<...>` if there're lifetime/type arguments. if len > 0 { diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.stderr index 72369ab24ebf..380a70d664e0 100644 --- a/src/test/ui/const-generics/slice-const-param-mismatch.stderr +++ b/src/test/ui/const-generics/slice-const-param-mismatch.stderr @@ -12,8 +12,8 @@ error[E0308]: mismatched types LL | let _: ConstString<"Hello"> = ConstString::<"World">; | ^^^^^^^^^^^^^^^^^^^^^^ expected `"Hello"`, found `"World"` | - = note: expected type `ConstString<>` - found type `ConstString<>` + = note: expected type `ConstString<"Hello">` + found type `ConstString<"World">` error[E0308]: mismatched types --> $DIR/slice-const-param-mismatch.rs:11:33 @@ -21,8 +21,8 @@ error[E0308]: mismatched types LL | let _: ConstString<"ℇ㇈↦"> = ConstString::<"ℇ㇈↥">; | ^^^^^^^^^^^^^^^^^^^^^ expected `"ℇ㇈↦"`, found `"ℇ㇈↥"` | - = note: expected type `ConstString<>` - found type `ConstString<>` + = note: expected type `ConstString<"ℇ㇈↦">` + found type `ConstString<"ℇ㇈↥">` error[E0308]: mismatched types --> $DIR/slice-const-param-mismatch.rs:13:33 @@ -30,8 +30,8 @@ error[E0308]: mismatched types LL | let _: ConstBytes = ConstBytes::; | ^^^^^^^^^^^^^^^^^^^^ expected `b"AAA"`, found `b"BBB"` | - = note: expected type `ConstBytes<>` - found type `ConstBytes<>` + = note: expected type `ConstBytes` + found type `ConstBytes` error: aborting due to 3 previous errors From c08711134508483e9b39beba16e31b057618cbf2 Mon Sep 17 00:00:00 2001 From: Avi Dessauer Date: Sun, 6 Oct 2019 03:42:53 -0400 Subject: [PATCH 103/545] Use shorthand initialization in rustdoc --- src/librustdoc/clean/mod.rs | 14 +++++++------- src/librustdoc/lib.rs | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8f35ca01f79d..212a09ee6e63 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -198,7 +198,7 @@ pub fn krate(mut cx: &mut DocContext<'_>) -> Crate { Item { source: Span::empty(), name: Some(kw.clone()), - attrs: attrs, + attrs, visibility: Public, stability: get_stability(cx, def_id), deprecation: get_deprecation(cx, def_id), @@ -1570,7 +1570,7 @@ impl Clean for hir::GenericParam { did: cx.tcx.hir().local_def_id(self.hir_id), bounds: self.bounds.clean(cx), default: default.clean(cx), - synthetic: synthetic, + synthetic, }) } hir::GenericParamKind::Const { ref ty } => { @@ -2213,7 +2213,7 @@ impl Clean for doctree::Trait<'_> { let is_spotlight = attrs.has_doc_flag(sym::spotlight); Item { name: Some(self.name.clean(cx)), - attrs: attrs, + attrs, source: self.whence.clean(cx), def_id: cx.tcx.hir().local_def_id(self.id), visibility: self.vis.clean(cx), @@ -2844,7 +2844,7 @@ impl Clean for hir::Ty { } else { Some(l.clean(cx)) }; - BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx), + BorrowedRef {lifetime, mutability: m.mutbl.clean(cx), type_: box m.ty.clean(cx)} } TyKind::Slice(ref ty) => Slice(box ty.clean(cx)), @@ -3102,9 +3102,9 @@ impl<'tcx> Clean for Ty<'tcx> { let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], InternalSubsts::empty()); ResolvedPath { - path: path, + path, param_names: None, - did: did, + did, is_generic: false, } } @@ -4274,7 +4274,7 @@ fn resolve_type(cx: &DocContext<'_>, _ => false, }; let did = register_res(&*cx, path.res); - ResolvedPath { path: path, param_names: None, did: did, is_generic: is_generic } + ResolvedPath { path, param_names: None, did, is_generic } } pub fn register_res(cx: &DocContext<'_>, res: Res) -> DefId { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 539bf5dfe28e..00eb8f164fce 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -487,8 +487,8 @@ where R: 'static + Send, krate.version = crate_version; f(Output { - krate: krate, - renderinfo: renderinfo, + krate, + renderinfo, renderopts, }) }); From 8a164acf5879aec3389180f7102ea32dce5eb07a Mon Sep 17 00:00:00 2001 From: wangxiangqing Date: Sun, 6 Oct 2019 12:03:53 +0800 Subject: [PATCH 104/545] Suggest dereferencing boolean reference when used in 'if' or 'while' Change-Id: I0c5c4d767be2647e6f017ae7bf83558c56dbca97 --- src/test/ui/if/if-no-match-bindings.stderr | 44 +++++++++++++---- .../disallowed-positions.stderr | 48 ++++++++++++++++++- 2 files changed, 80 insertions(+), 12 deletions(-) diff --git a/src/test/ui/if/if-no-match-bindings.stderr b/src/test/ui/if/if-no-match-bindings.stderr index cbf52476ae37..694b59897c5a 100644 --- a/src/test/ui/if/if-no-match-bindings.stderr +++ b/src/test/ui/if/if-no-match-bindings.stderr @@ -2,7 +2,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:18:8 | LL | if b_ref() {} - | ^^^^^^^ expected bool, found &bool + | ^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*b_ref()` | = note: expected type `bool` found type `&bool` @@ -11,7 +14,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:19:8 | LL | if b_mut_ref() {} - | ^^^^^^^^^^^ expected bool, found &mut bool + | ^^^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*b_mut_ref()` | = note: expected type `bool` found type `&mut bool` @@ -20,7 +26,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:20:8 | LL | if &true {} - | ^^^^^ expected bool, found &bool + | ^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*&true` | = note: expected type `bool` found type `&bool` @@ -29,7 +38,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:21:8 | LL | if &mut true {} - | ^^^^^^^^^ expected bool, found &mut bool + | ^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*&mut true` | = note: expected type `bool` found type `&mut bool` @@ -38,7 +50,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:24:11 | LL | while b_ref() {} - | ^^^^^^^ expected bool, found &bool + | ^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*b_ref()` | = note: expected type `bool` found type `&bool` @@ -47,7 +62,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:25:11 | LL | while b_mut_ref() {} - | ^^^^^^^^^^^ expected bool, found &mut bool + | ^^^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*b_mut_ref()` | = note: expected type `bool` found type `&mut bool` @@ -55,8 +73,11 @@ LL | while b_mut_ref() {} error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:26:11 | -LL | while &true {} - | ^^^^^ expected bool, found &bool +26 | while &true {} + | ^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*&true` | = note: expected type `bool` found type `&bool` @@ -64,8 +85,11 @@ LL | while &true {} error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:27:11 | -LL | while &mut true {} - | ^^^^^^^^^ expected bool, found &mut bool +27 | while &mut true {} + | ^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*&mut true` | = note: expected type `bool` found type `&mut bool` 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 4edc00efc7e7..ab1b405e5c21 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 @@ -513,11 +513,52 @@ warning: the feature `let_chains` is incomplete and may cause the compiler to cr LL | #![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test. | ^^^^^^^^^^ +warning: unnecessary parentheses around `if` condition + --> $DIR/disallowed-positions.rs:51:8 + | +LL | if (true || let 0 = 0) {} + | ^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + | + = note: `#[warn(unused_parens)]` on by default + +warning: unnecessary parentheses around `while` condition + --> $DIR/disallowed-positions.rs:115:11 + | +LL | while (true || let 0 = 0) {} + | ^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + +wrning: unnecessary parentheses around `let` head expression + --> $DIR/disallowed-positions.rs:160:41 + | +LL | if let Range { start: _, end: _ } = (true..true || false) { } + | ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + +warning: unnecessary parentheses around `let` head expression + --> $DIR/disallowed-positions.rs:162:41 + | +LL | if let Range { start: _, end: _ } = (true..true && false) { } + | ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + +warning: unnecessary parentheses around `let` head expression + --> $DIR/disallowed-positions.rs:164:44 + | +LL | while let Range { start: _, end: _ } = (true..true || false) { } + | ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + +warning: unnecessary parentheses around `let` head expression + --> $DIR/disallowed-positions.rs:166:44 + | +LL | while let Range { start: _, end: _ } = (true..true && false) { } + | ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses + error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:32:8 | LL | if &let 0 = 0 {} - | ^^^^^^^^^^ expected bool, found &bool + | ^^^^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*&let 0 = 0` | = note: expected type `bool` found type `&bool` @@ -702,7 +743,10 @@ error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:96:11 | LL | while &let 0 = 0 {} - | ^^^^^^^^^^ expected bool, found &bool + | ^^^^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*&let 0 = 0` | = note: expected type `bool` found type `&bool` From bbb69d14552b7258ba0b1d56d6558bd32b647b9a Mon Sep 17 00:00:00 2001 From: wangxiangqing Date: Sun, 6 Oct 2019 12:03:53 +0800 Subject: [PATCH 105/545] Suggest dereferencing boolean reference when used in 'if' or 'while' Change-Id: I0c5c4d767be2647e6f017ae7bf83558c56dbca97 --- src/test/ui/if/if-no-match-bindings.stderr | 4 +- .../disallowed-positions.stderr | 38 ------------------- 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/src/test/ui/if/if-no-match-bindings.stderr b/src/test/ui/if/if-no-match-bindings.stderr index 694b59897c5a..53b7aafc430a 100644 --- a/src/test/ui/if/if-no-match-bindings.stderr +++ b/src/test/ui/if/if-no-match-bindings.stderr @@ -73,7 +73,7 @@ LL | while b_mut_ref() {} error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:26:11 | -26 | while &true {} +LL | while &true {} | ^^^^^ | | | expected bool, found &bool @@ -85,7 +85,7 @@ error[E0308]: mismatched types error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:27:11 | -27 | while &mut true {} +LL | while &mut true {} | ^^^^^^^^^ | | | expected bool, found &mut bool 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 ab1b405e5c21..619f9c85b24d 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 @@ -513,44 +513,6 @@ warning: the feature `let_chains` is incomplete and may cause the compiler to cr LL | #![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test. | ^^^^^^^^^^ -warning: unnecessary parentheses around `if` condition - --> $DIR/disallowed-positions.rs:51:8 - | -LL | if (true || let 0 = 0) {} - | ^^^^^^^^^^^^^^^^^^^ help: remove these parentheses - | - = note: `#[warn(unused_parens)]` on by default - -warning: unnecessary parentheses around `while` condition - --> $DIR/disallowed-positions.rs:115:11 - | -LL | while (true || let 0 = 0) {} - | ^^^^^^^^^^^^^^^^^^^ help: remove these parentheses - -wrning: unnecessary parentheses around `let` head expression - --> $DIR/disallowed-positions.rs:160:41 - | -LL | if let Range { start: _, end: _ } = (true..true || false) { } - | ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses - -warning: unnecessary parentheses around `let` head expression - --> $DIR/disallowed-positions.rs:162:41 - | -LL | if let Range { start: _, end: _ } = (true..true && false) { } - | ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses - -warning: unnecessary parentheses around `let` head expression - --> $DIR/disallowed-positions.rs:164:44 - | -LL | while let Range { start: _, end: _ } = (true..true || false) { } - | ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses - -warning: unnecessary parentheses around `let` head expression - --> $DIR/disallowed-positions.rs:166:44 - | -LL | while let Range { start: _, end: _ } = (true..true && false) { } - | ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses - error[E0308]: mismatched types --> $DIR/disallowed-positions.rs:32:8 | From 65a7611b63ede78537be37e435b6adb43abc0bae Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 6 Oct 2019 14:18:41 +0200 Subject: [PATCH 106/545] sort error codes in librustc_passes --- src/librustc_passes/error_codes.rs | 325 ++++++++++++++--------------- 1 file changed, 162 insertions(+), 163 deletions(-) diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index 1c61eb35497d..82cbcf458b07 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -53,6 +53,67 @@ extern { ``` "##, +// This shouldn't really ever trigger since the repeated value error comes first +E0136: r##" +A binary can only have one entry point, and by default that entry point is the +function `main()`. If there are multiple such functions, please rename one. +"##, + +E0137: r##" +More than one function was declared with the `#[main]` attribute. + +Erroneous code example: + +```compile_fail,E0137 +#![feature(main)] + +#[main] +fn foo() {} + +#[main] +fn f() {} // error: multiple functions with a `#[main]` attribute +``` + +This error indicates that the compiler found multiple functions with the +`#[main]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(main)] + +#[main] +fn f() {} // ok! +``` +"##, + +E0138: r##" +More than one function was declared with the `#[start]` attribute. + +Erroneous code example: + +```compile_fail,E0138 +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize {} + +#[start] +fn f(argc: isize, argv: *const *const u8) -> isize {} +// error: multiple 'start' functions +``` + +This error indicates that the compiler found multiple functions with the +`#[start]` attribute. This is an error because there must be a unique entry +point into a Rust program. Example: + +``` +#![feature(start)] + +#[start] +fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! +``` +"##, + E0197: r##" Inherent implementations (one that do not implement a trait but provide methods associated with a type) are always safe because they are not @@ -198,20 +259,30 @@ impl Foo for Bar { ``` "##, +E0512: r##" +Transmute with two differently sized types was attempted. Erroneous code +example: -E0590: r##" -`break` or `continue` must include a label when used in the condition of a -`while` loop. +```compile_fail,E0512 +fn takes_u8(_: u8) {} -Example of erroneous code: - -```compile_fail -while break {} +fn main() { + unsafe { takes_u8(::std::mem::transmute(0u16)); } + // error: cannot transmute between types of different sizes, + // or dependently-sized types +} ``` -To fix this, add a label specifying which loop is being broken out of: +Please use types with same size or use the expected type directly. Example: + ``` -'foo: while break 'foo {} +fn takes_u8(_: u8) {} + +fn main() { + unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok! + // or: + unsafe { takes_u8(0u8); } // ok! +} ``` "##, @@ -249,153 +320,22 @@ let result = loop { // ok! ``` "##, -E0642: r##" -Trait methods currently cannot take patterns as arguments. +E0590: r##" +`break` or `continue` must include a label when used in the condition of a +`while` loop. Example of erroneous code: -```compile_fail,E0642 -trait Foo { - fn foo((x, y): (i32, i32)); // error: patterns aren't allowed - // in trait methods -} +```compile_fail +while break {} ``` -You can instead use a single name for the argument: - +To fix this, add a label specifying which loop is being broken out of: ``` -trait Foo { - fn foo(x_and_y: (i32, i32)); // ok! -} +'foo: while break 'foo {} ``` "##, -E0695: r##" -A `break` statement without a label appeared inside a labeled block. - -Example of erroneous code: - -```compile_fail,E0695 -# #![feature(label_break_value)] -loop { - 'a: { - break; - } -} -``` - -Make sure to always label the `break`: - -``` -# #![feature(label_break_value)] -'l: loop { - 'a: { - break 'l; - } -} -``` - -Or if you want to `break` the labeled block: - -``` -# #![feature(label_break_value)] -loop { - 'a: { - break 'a; - } - break; -} -``` -"##, - -E0670: r##" -Rust 2015 does not permit the use of `async fn`. - -Example of erroneous code: - -```compile_fail,E0670 -async fn foo() {} -``` - -Switch to the Rust 2018 edition to use `async fn`. -"##, - -// This shouldn't really ever trigger since the repeated value error comes first -E0136: r##" -A binary can only have one entry point, and by default that entry point is the -function `main()`. If there are multiple such functions, please rename one. -"##, - -E0137: r##" -More than one function was declared with the `#[main]` attribute. - -Erroneous code example: - -```compile_fail,E0137 -#![feature(main)] - -#[main] -fn foo() {} - -#[main] -fn f() {} // error: multiple functions with a `#[main]` attribute -``` - -This error indicates that the compiler found multiple functions with the -`#[main]` attribute. This is an error because there must be a unique entry -point into a Rust program. Example: - -``` -#![feature(main)] - -#[main] -fn f() {} // ok! -``` -"##, - -E0138: r##" -More than one function was declared with the `#[start]` attribute. - -Erroneous code example: - -```compile_fail,E0138 -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize {} - -#[start] -fn f(argc: isize, argv: *const *const u8) -> isize {} -// error: multiple 'start' functions -``` - -This error indicates that the compiler found multiple functions with the -`#[start]` attribute. This is an error because there must be a unique entry -point into a Rust program. Example: - -``` -#![feature(start)] - -#[start] -fn foo(argc: isize, argv: *const *const u8) -> isize { 0 } // ok! -``` -"##, - -E0601: r##" -No `main` function was found in a binary crate. To fix this error, add a -`main` function. For example: - -``` -fn main() { - // Your program will start here. - println!("Hello world!"); -} -``` - -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/ -"##, - E0591: r##" Per [RFC 401][rfc401], if you have a function declaration `foo`: @@ -474,31 +414,90 @@ makes a difference in practice.) [rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md "##, -E0512: r##" -Transmute with two differently sized types was attempted. Erroneous code -example: - -```compile_fail,E0512 -fn takes_u8(_: u8) {} +E0601: r##" +No `main` function was found in a binary crate. To fix this error, add a +`main` function. For example: +``` fn main() { - unsafe { takes_u8(::std::mem::transmute(0u16)); } - // error: cannot transmute between types of different sizes, - // or dependently-sized types + // Your program will start here. + println!("Hello world!"); } ``` -Please use types with same size or use the expected type directly. Example: +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/ +"##, -``` -fn takes_u8(_: u8) {} +E0642: r##" +Trait methods currently cannot take patterns as arguments. -fn main() { - unsafe { takes_u8(::std::mem::transmute(0i8)); } // ok! - // or: - unsafe { takes_u8(0u8); } // ok! +Example of erroneous code: + +```compile_fail,E0642 +trait Foo { + fn foo((x, y): (i32, i32)); // error: patterns aren't allowed + // in trait methods } ``` + +You can instead use a single name for the argument: + +``` +trait Foo { + fn foo(x_and_y: (i32, i32)); // ok! +} +``` +"##, + +E0695: r##" +A `break` statement without a label appeared inside a labeled block. + +Example of erroneous code: + +```compile_fail,E0695 +# #![feature(label_break_value)] +loop { + 'a: { + break; + } +} +``` + +Make sure to always label the `break`: + +``` +# #![feature(label_break_value)] +'l: loop { + 'a: { + break 'l; + } +} +``` + +Or if you want to `break` the labeled block: + +``` +# #![feature(label_break_value)] +loop { + 'a: { + break 'a; + } + break; +} +``` +"##, + +E0670: r##" +Rust 2015 does not permit the use of `async fn`. + +Example of erroneous code: + +```compile_fail,E0670 +async fn foo() {} +``` + +Switch to the Rust 2018 edition to use `async fn`. "##, ; From 4c32d475a8bd2c68f82120af9182c41730a81a82 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 6 Oct 2019 08:38:23 -0400 Subject: [PATCH 107/545] Remove loaded_from_cache map from DepGraph It's now unused, even with -Zquery-dep-graph --- src/librustc/dep_graph/graph.rs | 23 ----------------------- src/librustc/ty/query/plumbing.rs | 8 -------- 2 files changed, 31 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 0c56fc7914b4..08c456547cec 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -75,9 +75,6 @@ struct DepGraphData { previous_work_products: FxHashMap, dep_node_debug: Lock>, - - // Used for testing, only populated when -Zquery-dep-graph is specified. - loaded_from_cache: Lock>, } pub fn hash_result(hcx: &mut StableHashingContext<'_>, result: &R) -> Option @@ -104,7 +101,6 @@ impl DepGraph { emitting_diagnostics_cond_var: Condvar::new(), previous: prev_graph, colors: DepNodeColorMap::new(prev_graph_node_count), - loaded_from_cache: Default::default(), })), } } @@ -874,25 +870,6 @@ impl DepGraph { } } } - - pub fn mark_loaded_from_cache(&self, dep_node_index: DepNodeIndex, state: bool) { - debug!("mark_loaded_from_cache({:?}, {})", - self.data.as_ref().unwrap().current.borrow().data[dep_node_index].node, - state); - - self.data - .as_ref() - .unwrap() - .loaded_from_cache - .borrow_mut() - .insert(dep_node_index, state); - } - - pub fn was_loaded_from_cache(&self, dep_node: &DepNode) -> Option { - let data = self.data.as_ref().unwrap(); - let dep_node_index = data.current.borrow().node_to_node_index[dep_node]; - data.loaded_from_cache.borrow().get(&dep_node_index).cloned() - } } /// A "work product" is an intermediate result that we save into the diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 955f1447c55b..7cab8fe60ee6 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -489,10 +489,6 @@ impl<'tcx> TyCtxt<'tcx> { self.incremental_verify_ich::(&result, dep_node, dep_node_index); } - if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) { - self.dep_graph.mark_loaded_from_cache(dep_node_index, true); - } - result } @@ -570,10 +566,6 @@ impl<'tcx> TyCtxt<'tcx> { drop(prof_timer); profq_msg!(self, ProfileQueriesMsg::ProviderEnd); - if unlikely!(self.sess.opts.debugging_opts.query_dep_graph) { - self.dep_graph.mark_loaded_from_cache(dep_node_index, false); - } - if unlikely!(!diagnostics.is_empty()) { if dep_node.kind != crate::dep_graph::DepKind::Null { self.queries.on_disk_cache From c5e0d6e4d43f228687c75ab7406f64b318752d7b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 6 Oct 2019 15:23:33 +0200 Subject: [PATCH 108/545] Add long error explanation for E0566 --- src/librustc/error_codes.rs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 66c51000066b..9a5e1ea6f333 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1700,6 +1700,30 @@ To understand better how closures work in Rust, read: https://doc.rust-lang.org/book/ch13-01-closures.html "##, +E0566: r##" +Conflicting representation hints have been used on a same item. + +Erroneous code example: + +```compile_fail,E0566 +# #![deny(warnings)] +# fn main() { +#[repr(u32, u64)] // error! +enum Repr { A } +# } +``` + +In most cases (if not all), using just one representation hint is more than +enough. If you want to have a representation hint depending on the current +architecture, use `cfg_attr`. Example: + +``` +#[cfg_attr(linux, repr(u32))] +#[cfg_attr(not(linux), repr(u64))] +enum Repr { A } +``` +"##, + E0580: r##" The `main` function was incorrectly declared. @@ -2097,7 +2121,6 @@ rejected in your own crates. E0490, // a value of type `..` is borrowed for too long E0495, // cannot infer an appropriate lifetime due to conflicting // requirements - E0566, // conflicting representation hints E0623, // lifetime mismatch where both parameters are anonymous regions E0628, // generators cannot have explicit parameters E0631, // type mismatch in closure arguments From dd2356fe7d8500a2b555a8b43761625e17223860 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 6 Oct 2019 21:57:23 +0800 Subject: [PATCH 109/545] add testcase for generator move suggestion --- .../async-borrowck-escaping-block-error.rs | 9 ++++++++ ...async-borrowck-escaping-block-error.stderr | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.rs create mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.stderr diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs new file mode 100644 index 000000000000..49f59e414931 --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs @@ -0,0 +1,9 @@ +// edition:2018 +#![feature(async_closure,async_await)] +fn foo() -> Box> { + let x = 0u32; + Box::new(async { x } ) + //~^ ERROR E0373 +} + +fn main() {} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr new file mode 100644 index 000000000000..5771ccbcf9d1 --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -0,0 +1,22 @@ +error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function + --> $DIR/async-borrowck-escaping-block-error.rs:5:20 + | +LL | Box::new(async { x } ) + | ^^-^^ + | | | + | | `x` is borrowed here + | may outlive borrowed value `x` + | +note: generator is returned here + --> $DIR/async-borrowck-escaping-block-error.rs:3:13 + | +LL | fn foo() -> Box> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword + | +LL | Box::new(async move { x } ) + | ^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0373`. From 57cb8819ee78f2debf24d2e123c78796204db8c9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 6 Oct 2019 17:02:01 +0200 Subject: [PATCH 110/545] Update ui tests --- src/librustc/error_codes.rs | 7 ++----- src/test/ui/conflicting-repr-hints.stderr | 1 + src/test/ui/feature-gates/feature-gate-repr-simd.stderr | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 9a5e1ea6f333..502172db91c9 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1705,12 +1705,9 @@ Conflicting representation hints have been used on a same item. Erroneous code example: -```compile_fail,E0566 -# #![deny(warnings)] -# fn main() { -#[repr(u32, u64)] // error! +``` +#[repr(u32, u64)] // warning! enum Repr { A } -# } ``` In most cases (if not all), using just one representation hint is more than diff --git a/src/test/ui/conflicting-repr-hints.stderr b/src/test/ui/conflicting-repr-hints.stderr index 6b15b7ebbe9e..832f5c3ac2bb 100644 --- a/src/test/ui/conflicting-repr-hints.stderr +++ b/src/test/ui/conflicting-repr-hints.stderr @@ -66,3 +66,4 @@ LL | | } error: aborting due to 8 previous errors +For more information about this error, try `rustc --explain E0566`. diff --git a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr index dfaa85bc5f01..02c8400e03e8 100644 --- a/src/test/ui/feature-gates/feature-gate-repr-simd.stderr +++ b/src/test/ui/feature-gates/feature-gate-repr-simd.stderr @@ -26,4 +26,5 @@ LL | #[repr(simd)] error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0658`. +Some errors have detailed explanations: E0566, E0658. +For more information about an error, try `rustc --explain E0566`. From b7091e4f5275fd9e48af8083addcb8b577493656 Mon Sep 17 00:00:00 2001 From: Andrew Banchich Date: Mon, 23 Sep 2019 23:20:55 -0400 Subject: [PATCH 111/545] rewrite documentation for unimplemented! --- src/libcore/macros.rs | 47 +++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/libcore/macros.rs b/src/libcore/macros.rs index 384bc8749988..22331b51bc61 100644 --- a/src/libcore/macros.rs +++ b/src/libcore/macros.rs @@ -519,15 +519,17 @@ macro_rules! unreachable { }); } -/// Indicates unfinished code. +/// Indicates unfinished code by panicking with a message of "not yet implemented". /// -/// This can be useful if you are prototyping and are just looking to have your -/// code type-check, or if you're implementing a trait that requires multiple -/// methods, and you're only planning on using one of them. +/// This allows the your code to type-check, which is useful if you are prototyping or +/// implementing a trait that requires multiple methods which you don't plan of using all of. /// /// # Panics /// -/// This will always [panic!](macro.panic.html) +/// This will always [panic!](macro.panic.html) because `unimplemented!` is just a +/// shorthand for `panic!` with a fixed, specific message. +/// +/// Like `panic!`, this macro has a second form for displaying custom values. /// /// # Examples /// @@ -535,38 +537,53 @@ macro_rules! unreachable { /// /// ``` /// trait Foo { -/// fn bar(&self); +/// fn bar(&self) -> u8; /// fn baz(&self); +/// fn qux(&self) -> Result; /// } /// ``` /// -/// We want to implement `Foo` on one of our types, but we also want to work on -/// just `bar()` first. In order for our code to compile, we need to implement -/// `baz()`, so we can use `unimplemented!`: +/// We want to implement `Foo` for 'MyStruct', but so far we only know how to +/// implement the `bar()` function. `baz()` and `qux()` will still need to be defined +/// in our implementation of `Foo`, but we can use `unimplemented!` in their definitions +/// to allow our code to compile. +/// +/// In the meantime, we want to have our program stop running once these +/// unimplemented functions are reached. /// /// ``` /// # trait Foo { -/// # fn bar(&self); +/// # fn bar(&self) -> u8; /// # fn baz(&self); +/// # fn qux(&self) -> Result; /// # } /// struct MyStruct; /// /// impl Foo for MyStruct { -/// fn bar(&self) { -/// // implementation goes here +/// fn bar(&self) -> u8 { +/// 1 + 1 /// } /// /// fn baz(&self) { -/// // let's not worry about implementing baz() for now +/// // We aren't sure how to even start writing baz yet, +/// // so we have no logic here at all. +/// // This will display "thread 'main' panicked at 'not yet implemented'". /// unimplemented!(); /// } +/// +/// fn qux(&self) -> Result { +/// let n = self.bar(); +/// // We have some logic here, +/// // so we can use unimplemented! to display what we have so far. +/// // This will display: +/// // "thread 'main' panicked at 'not yet implemented: we need to divide by 2'". +/// unimplemented!("we need to divide by {}", n); +/// } /// } /// /// fn main() { /// let s = MyStruct; /// s.bar(); -/// -/// // we aren't even using baz() yet, so this is fine. /// } /// ``` #[macro_export] From 4cc707cb7846c2a136daa42ea3498c5a92903189 Mon Sep 17 00:00:00 2001 From: Denis Lisov Date: Mon, 7 Oct 2019 00:29:47 +0300 Subject: [PATCH 112/545] use precalculated dominators in explain_borrow This looks like the only place calculating dominators from the MIR body every time instead of using the ones stored on the `MirBorrowckCtxt`. For example, in rust-lang/rust#65131 a big generated function with a number of borrowck errors takes a few hours(!) recalculating the dominators while explaining the errors. I don't know enough about this part of rustc codebase to know for sure that this change is correct, but no tests seem to fail as a result of this change in local testing. --- src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index ff4243df6e9b..e6a33f8e6adf 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -457,7 +457,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// True if an edge `source -> target` is a backedge -- in other words, if the target /// dominates the source. fn is_back_edge(&self, source: Location, target: Location) -> bool { - target.dominates(source, &self.body.dominators()) + target.dominates(source, &self.dominators) } /// Determine how the borrow was later used. From 8baf7bf33d060ca6661c03a47d30ecfc2210743a Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Sun, 6 Oct 2019 14:40:08 -0700 Subject: [PATCH 113/545] Update reference - 771c5d10cf944bf7d221f5d6cb7abd2a06c400e4 Add macros in extern blocks and new proc-macro support. - 8caabd62ef5fbe99e6be6aa9e76f55bbb8433d95 Update for "modern" `meta` matcher. - 1b44947d36ccf7eba2b3bd245769eff68abf6d4d Update await desugaring after rust-lang/rust#64292 --- src/doc/reference | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/reference b/src/doc/reference index 320d232b206e..5b9d2fcefadf 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 320d232b206edecb67489316f71a14e31dbc6c08 +Subproject commit 5b9d2fcefadfc32fceafacfc0dd9441d9b57dd94 From 23d3ff1b9756c768c4412dcd1d80cff0617fd5c5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Sun, 6 Oct 2019 23:45:25 +0200 Subject: [PATCH 114/545] Fix zero-size uninitialized boxes Requesting a zero-size allocation is not allowed, return a dangling pointer instead. CC https://github.com/rust-lang/rust/issues/63291#issuecomment-538692745 --- src/liballoc/boxed.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 9b5d9431ae20..2693a64e13ba 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -141,6 +141,9 @@ impl Box { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { + if mem::size_of::() == 0 { + return Box(NonNull::dangling().into()) + } let layout = alloc::Layout::new::>(); let ptr = unsafe { Global.alloc(layout) @@ -181,10 +184,17 @@ impl Box<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - let layout = alloc::Layout::array::>(len).unwrap(); - let ptr = unsafe { alloc::alloc(layout) }; - let unique = Unique::new(ptr).unwrap_or_else(|| alloc::handle_alloc_error(layout)); - let slice = unsafe { slice::from_raw_parts_mut(unique.cast().as_ptr(), len) }; + let ptr = if mem::size_of::() == 0 || len == 0 { + NonNull::dangling() + } else { + let layout = alloc::Layout::array::>(len).unwrap(); + unsafe { + Global.alloc(layout) + .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) + .cast() + } + }; + let slice = unsafe { slice::from_raw_parts_mut(ptr.as_ptr(), len) }; Box(Unique::from(slice)) } } From 50932ea1dae96a15e8f457e4e038d0e5218d2cad Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Sun, 6 Oct 2019 23:58:07 +0200 Subject: [PATCH 115/545] add more info in debug traces for gcu merging --- src/librustc_mir/monomorphize/partitioning.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index c193911247e2..61868b24c0b8 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -494,6 +494,9 @@ fn merge_codegen_units<'tcx>( for (k, v) in smallest.items_mut().drain() { second_smallest.items_mut().insert(k, v); } + debug!("CodegenUnit {} merged in to CodegenUnit {}", + smallest.name(), + second_smallest.name()); } let cgu_name_builder = &mut CodegenUnitNameBuilder::new(tcx); @@ -774,7 +777,7 @@ where if cfg!(debug_assertions) { debug!("{}", label); for cgu in cgus { - debug!("CodegenUnit {}:", cgu.name()); + debug!("CodegenUnit {} estimated size {} :", cgu.name(), cgu.size_estimate()); for (mono_item, linkage) in cgu.items() { let symbol_name = mono_item.symbol_name(tcx).name.as_str(); @@ -782,10 +785,11 @@ where let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..]) .unwrap_or(""); - debug!(" - {} [{:?}] [{}]", + debug!(" - {} [{:?}] [{}] estimated size {}", mono_item.to_string(tcx, true), linkage, - symbol_hash); + symbol_hash, + mono_item.size_estimate(tcx)); } debug!(""); From 90c456e7320d3b4c7c25f4fe16753070b6b68223 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2019 14:32:26 +1000 Subject: [PATCH 116/545] Remove `force!`. --- src/librustc/ty/query/plumbing.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 955f1447c55b..8958c10479d0 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1218,10 +1218,6 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { } }; - macro_rules! force { - ($query:ident, $key:expr) => { force_ex!(tcx, $query, $key) } - }; - 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. @@ -1240,7 +1236,7 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { bug!("force_from_dep_node: encountered {:?}", dep_node) } - DepKind::Analysis => { force!(analysis, krate!()); } + DepKind::Analysis => { force_ex!(tcx, analysis, krate!()); } ); true From 8f707c3a98367c43455797e781793baef4a3579b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2019 14:33:30 +1000 Subject: [PATCH 117/545] Remove `krate!`. --- src/librustc/ty/query/plumbing.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 8958c10479d0..e0ebb071ed2f 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1202,10 +1202,6 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { } }; - macro_rules! krate { - () => { (def_id!()).krate } - }; - macro_rules! force_ex { ($tcx:expr, $query:ident, $key:expr) => { { @@ -1236,7 +1232,7 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { bug!("force_from_dep_node: encountered {:?}", dep_node) } - DepKind::Analysis => { force_ex!(tcx, analysis, krate!()); } + DepKind::Analysis => { force_ex!(tcx, analysis, def_id!().krate); } ); true From 1183d60cd5427a8369fb406d8bbac7fcc7a21fc1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Oct 2019 14:39:36 +1000 Subject: [PATCH 118/545] Remove `def_id!`. --- src/librustc/ty/query/plumbing.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index e0ebb071ed2f..2590f96f855a 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1191,17 +1191,6 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { return false } - macro_rules! def_id { - () => { - if let Some(def_id) = dep_node.extract_def_id(tcx) { - def_id - } else { - // Return from the whole function. - return false - } - } - }; - macro_rules! force_ex { ($tcx:expr, $query:ident, $key:expr) => { { @@ -1232,7 +1221,15 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { bug!("force_from_dep_node: encountered {:?}", dep_node) } - DepKind::Analysis => { force_ex!(tcx, analysis, def_id!().krate); } + 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 + }; + force_ex!(tcx, analysis, def_id.krate); + } ); true From 9267d9fe5b1f99f98da83a90e84de706cf8cc150 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Oct 2019 11:59:28 +1100 Subject: [PATCH 119/545] Remove `force_ex!`. --- src/librustc/ty/query/plumbing.rs | 18 +++++------------- src/librustc_macros/src/query.rs | 6 +++++- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 2590f96f855a..2a51e01ac848 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1191,18 +1191,6 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { return false } - macro_rules! force_ex { - ($tcx:expr, $query:ident, $key:expr) => { - { - $tcx.force_query::>( - $key, - DUMMY_SP, - *dep_node - ); - } - } - }; - 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. @@ -1228,7 +1216,11 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { // Return from the whole function. return false }; - force_ex!(tcx, analysis, def_id.krate); + tcx.force_query::>( + def_id.krate, + DUMMY_SP, + *dep_node + ); } ); diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 9a68dd0f5e3c..139e1b554cf9 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -495,7 +495,11 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { dep_node_force_stream.extend(quote! { DepKind::#name => { if let Some(key) = RecoverKey::recover($tcx, $dep_node) { - force_ex!($tcx, #name, key); + $tcx.force_query::>( + key, + DUMMY_SP, + *$dep_node + ); } else { return false; } From e0fe4be4657493fb1cd292911df0d9470d8c38e3 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 1 Oct 2019 12:11:38 +0200 Subject: [PATCH 120/545] syntax: cleanup associated const parsing. --- src/libsyntax/parse/parser/item.rs | 71 ++++++++++++++++-------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 2ac0352764fa..6a832d5f3014 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -4,7 +4,7 @@ use crate::maybe_whole; use crate::ptr::P; use crate::ast::{ self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle, - Item, ItemKind, ImplItem, TraitItem, TraitItemKind, + Item, ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind, PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness, Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, MethodSig, Block, @@ -727,16 +727,7 @@ impl<'a> Parser<'a> { }; (name, kind, generics) } else if self.is_const_item() { - // This parses the grammar: - // ImplItemConst = "const" Ident ":" Ty "=" Expr ";" - self.expect_keyword(kw::Const)?; - let name = self.parse_ident()?; - self.expect(&token::Colon)?; - let typ = self.parse_ty()?; - self.expect(&token::Eq)?; - let expr = self.parse_expr()?; - self.expect(&token::Semi)?; - (name, ast::ImplItemKind::Const(typ, expr), Generics::default()) + self.parse_impl_const()? } else { let (name, inner_attrs, generics, kind) = self.parse_impl_method(&vis, at_end)?; attrs.extend(inner_attrs); @@ -785,12 +776,25 @@ impl<'a> Parser<'a> { !self.is_keyword_ahead(1, &[kw::Fn, kw::Unsafe]) } + /// This parses the grammar: + /// ImplItemConst = "const" Ident ":" Ty "=" Expr ";" + fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { + self.expect_keyword(kw::Const)?; + let name = self.parse_ident()?; + self.expect(&token::Colon)?; + let typ = self.parse_ty()?; + self.expect(&token::Eq)?; + let expr = self.parse_expr()?; + self.expect(&token::Semi)?; + Ok((name, ImplItemKind::Const(typ, expr), Generics::default())) + } + /// Parses a method or a macro invocation in a trait impl. fn parse_impl_method( &mut self, vis: &Visibility, at_end: &mut bool - ) -> PResult<'a, (Ident, Vec, Generics, ast::ImplItemKind)> { + ) -> PResult<'a, (Ident, Vec, Generics, ImplItemKind)> { // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? { // method macro @@ -935,30 +939,20 @@ impl<'a> Parser<'a> { Ok(item) } - fn parse_trait_item_(&mut self, - at_end: &mut bool, - mut attrs: Vec) -> PResult<'a, TraitItem> { + fn parse_trait_item_( + &mut self, + at_end: &mut bool, + mut attrs: Vec, + ) -> PResult<'a, TraitItem> { let lo = self.token.span; self.eat_bad_pub(); let (name, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_trait_item_assoc_ty()? } else if self.is_const_item() { - self.expect_keyword(kw::Const)?; - let ident = self.parse_ident()?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; - let default = if self.eat(&token::Eq) { - let expr = self.parse_expr()?; - self.expect(&token::Semi)?; - Some(expr) - } else { - self.expect(&token::Semi)?; - None - }; - (ident, TraitItemKind::Const(ty, default), Generics::default()) + self.parse_trait_item_const()? } else if let Some(mac) = self.parse_assoc_macro_invoc("trait", None, &mut false)? { // trait item macro. - (Ident::invalid(), ast::TraitItemKind::Macro(mac), Generics::default()) + (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default()) } else { // This is somewhat dubious; We don't want to allow // argument names to be left off if there is a definition... @@ -966,7 +960,7 @@ impl<'a> Parser<'a> { // We don't allow argument names to be left off in edition 2018. let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?; let body = self.parse_trait_method_body(at_end, &mut attrs)?; - (ident, ast::TraitItemKind::Method(sig, body), generics) + (ident, TraitItemKind::Method(sig, body), generics) }; Ok(TraitItem { @@ -980,6 +974,20 @@ impl<'a> Parser<'a> { }) } + fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { + self.expect_keyword(kw::Const)?; + let ident = self.parse_ident()?; + self.expect(&token::Colon)?; + let ty = self.parse_ty()?; + let default = if self.eat(&token::Eq) { + Some(self.parse_expr()?) + } else { + None + }; + self.expect(&token::Semi)?; + Ok((ident, TraitItemKind::Const(ty, default), Generics::default())) + } + /// Parse the "body" of a method in a trait item definition. /// This can either be `;` when there's no body, /// or e.g. a block when the method is a provided one. @@ -1020,8 +1028,7 @@ impl<'a> Parser<'a> { /// Parses the following grammar: /// /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] - fn parse_trait_item_assoc_ty(&mut self) - -> PResult<'a, (Ident, TraitItemKind, Generics)> { + fn parse_trait_item_assoc_ty(&mut self) -> PResult<'a, (Ident, TraitItemKind, Generics)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; From 3bdbfbe8b9c78bcec9019e7452a2a9396ecc861e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 1 Oct 2019 12:40:56 +0200 Subject: [PATCH 121/545] syntax: de-dups in item parsing. --- src/libsyntax/parse/parser/item.rs | 94 ++++++++++++++---------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 6a832d5f3014..95137f93b881 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -98,7 +98,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; - let visibility = self.parse_visibility(false)?; + let vis = self.parse_visibility(false)?; if self.eat_keyword(kw::Use) { // USE ITEM @@ -106,15 +106,14 @@ impl<'a> Parser<'a> { self.expect(&token::Semi)?; let span = lo.to(self.prev_span); - let item = - self.mk_item(span, Ident::invalid(), item_, visibility, attrs); + let item = self.mk_item(span, Ident::invalid(), item_, vis, attrs); return Ok(Some(item)); } if self.eat_keyword(kw::Extern) { let extern_sp = self.prev_span; if self.eat_keyword(kw::Crate) { - return Ok(Some(self.parse_item_extern_crate(lo, visibility, attrs)?)); + return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); } let opt_abi = self.parse_opt_abi()?; @@ -128,10 +127,10 @@ impl<'a> Parser<'a> { constness: respan(fn_span, Constness::NotConst), abi: opt_abi.unwrap_or(Abi::C), }; - return self.parse_item_fn(lo, visibility, attrs, header); + return self.parse_item_fn(lo, vis, attrs, header); } else if self.check(&token::OpenDelim(token::Brace)) { return Ok(Some( - self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs, extern_sp)?, + self.parse_item_foreign_mod(lo, opt_abi, vis, attrs, extern_sp)?, )); } @@ -142,10 +141,8 @@ impl<'a> Parser<'a> { self.bump(); // STATIC ITEM let m = self.parse_mutability(); - let (ident, item_, extra_attrs) = self.parse_item_const(Some(m))?; - let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + let info = self.parse_item_const(Some(m)); + return self.mk_item_with_info(attrs, lo, vis, info); } if self.eat_keyword(kw::Const) { let const_span = self.prev_span; @@ -168,7 +165,7 @@ impl<'a> Parser<'a> { constness: respan(const_span, Constness::Const), abi, }; - return self.parse_item_fn(lo, visibility, attrs, header); + return self.parse_item_fn(lo, vis, attrs, header); } // CONST ITEM @@ -184,10 +181,8 @@ impl<'a> Parser<'a> { ) .emit(); } - let (ident, item_, extra_attrs) = self.parse_item_const(None)?; - let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + let info = self.parse_item_const(None); + return self.mk_item_with_info(attrs, lo, vis, info); } // Parses `async unsafe? fn`. @@ -212,7 +207,7 @@ impl<'a> Parser<'a> { constness: respan(fn_span, Constness::NotConst), abi: Abi::Rust, }; - return self.parse_item_fn(lo, visibility, attrs, header); + return self.parse_item_fn(lo, vis, attrs, header); } } if self.check_keyword(kw::Unsafe) && @@ -227,10 +222,8 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Trait)?; IsAuto::Yes }; - let (ident, item_, extra_attrs) = self.parse_item_trait(is_auto, Unsafety::Unsafe)?; - let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + let info = self.parse_item_trait(is_auto, Unsafety::Unsafe); + return self.mk_item_with_info(attrs, lo, vis, info); } if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && @@ -241,10 +234,8 @@ impl<'a> Parser<'a> { let defaultness = self.parse_defaultness(); let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Impl)?; - let (ident, item_, extra_attrs) = self.parse_item_impl(unsafety, defaultness)?; - let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + let info = self.parse_item_impl(unsafety, defaultness); + return self.mk_item_with_info(attrs, lo, vis, info); } if self.check_keyword(kw::Fn) { // FUNCTION ITEM @@ -256,7 +247,7 @@ impl<'a> Parser<'a> { constness: respan(fn_span, Constness::NotConst), abi: Abi::Rust, }; - return self.parse_item_fn(lo, visibility, attrs, header); + return self.parse_item_fn(lo, vis, attrs, header); } if self.check_keyword(kw::Unsafe) && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) { @@ -273,14 +264,12 @@ impl<'a> Parser<'a> { constness: respan(fn_span, Constness::NotConst), abi, }; - return self.parse_item_fn(lo, visibility, attrs, header); + return self.parse_item_fn(lo, vis, attrs, header); } if self.eat_keyword(kw::Mod) { // MODULE ITEM - let (ident, item_, extra_attrs) = self.parse_item_mod(&attrs[..])?; - let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + let info = self.parse_item_mod(&attrs[..]); + return self.mk_item_with_info(attrs, lo, vis, info); } if let Some(type_) = self.eat_type() { let (ident, alias, generics) = type_?; @@ -290,14 +279,12 @@ impl<'a> Parser<'a> { AliasKind::OpaqueTy(bounds) => ItemKind::OpaqueTy(bounds, generics), }; let span = lo.to(self.prev_span); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + return Ok(Some(self.mk_item(span, ident, item_, vis, attrs))); } if self.eat_keyword(kw::Enum) { // ENUM ITEM - let (ident, item_, extra_attrs) = self.parse_item_enum()?; - let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + let info = self.parse_item_enum(); + return self.mk_item_with_info(attrs, lo, vis, info); } if self.check_keyword(kw::Trait) || (self.check_keyword(kw::Auto) @@ -311,33 +298,27 @@ impl<'a> Parser<'a> { IsAuto::Yes }; // TRAIT ITEM - let (ident, item_, extra_attrs) = self.parse_item_trait(is_auto, Unsafety::Normal)?; - let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + let info = self.parse_item_trait(is_auto, Unsafety::Normal); + return self.mk_item_with_info(attrs, lo, vis, info); } if self.eat_keyword(kw::Struct) { // STRUCT ITEM - let (ident, item_, extra_attrs) = self.parse_item_struct()?; - let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + let info = self.parse_item_struct(); + return self.mk_item_with_info(attrs, lo, vis, info); } if self.is_union_item() { // UNION ITEM self.bump(); - let (ident, item_, extra_attrs) = self.parse_item_union()?; - let span = lo.to(self.prev_span); - let attrs = maybe_append(attrs, extra_attrs); - return Ok(Some(self.mk_item(span, ident, item_, visibility, attrs))); + 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, &visibility, lo)? { + if let Some(macro_def) = self.eat_macro_def(&attrs, &vis, lo)? { 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 visibility.node.is_pub() && + if vis.node.is_pub() && self.check_ident() && self.look_ahead(1, |t| *t != token::Not) { @@ -428,7 +409,20 @@ impl<'a> Parser<'a> { return Err(err); } } - self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility) + self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) + } + + fn mk_item_with_info( + &self, + attrs: Vec, + lo: Span, + vis: Visibility, + info: PResult<'a, ItemInfo>, + ) -> PResult<'a, Option>> { + let (ident, item, extra_attrs) = info?; + let span = lo.to(self.prev_span); + let attrs = maybe_append(attrs, extra_attrs); + Ok(Some(self.mk_item(span, ident, item, vis, attrs))) } fn recover_first_param(&mut self) -> &'static str { From 090f3fd0c958e4ea8e7a6dfe33ae647d339c0544 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 1 Oct 2019 13:48:54 +0200 Subject: [PATCH 122/545] syntax: further item parsing cleanup --- src/libsyntax/parse/parser/item.rs | 61 ++++++++++++++++++------------ 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 95137f93b881..004c179b7c7f 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -141,14 +141,14 @@ impl<'a> Parser<'a> { self.bump(); // STATIC ITEM let m = self.parse_mutability(); - let info = self.parse_item_const(Some(m)); + let info = self.parse_item_const(Some(m))?; return self.mk_item_with_info(attrs, lo, vis, info); } + if self.eat_keyword(kw::Const) { let const_span = self.prev_span; if [kw::Fn, kw::Unsafe, kw::Extern].iter().any(|k| self.check_keyword(*k)) { // CONST FUNCTION ITEM - let unsafety = self.parse_unsafety(); if self.check_keyword(kw::Extern) { @@ -157,7 +157,7 @@ impl<'a> Parser<'a> { ); } let abi = self.parse_extern_abi()?; - self.bump(); // 'fn' + self.bump(); // `fn` let header = FnHeader { unsafety, @@ -181,7 +181,8 @@ impl<'a> Parser<'a> { ) .emit(); } - let info = self.parse_item_const(None); + + let info = self.parse_item_const(None)?; return self.mk_item_with_info(attrs, lo, vis, info); } @@ -210,6 +211,7 @@ impl<'a> Parser<'a> { return self.parse_item_fn(lo, vis, attrs, header); } } + if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) { @@ -222,21 +224,24 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Trait)?; IsAuto::Yes }; - let info = self.parse_item_trait(is_auto, Unsafety::Unsafe); + let info = self.parse_item_trait(is_auto, Unsafety::Unsafe)?; return self.mk_item_with_info(attrs, lo, vis, info); } + 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]) { + 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)?; - let info = self.parse_item_impl(unsafety, defaultness); + let info = self.parse_item_impl(unsafety, defaultness)?; return self.mk_item_with_info(attrs, lo, vis, info); } + if self.check_keyword(kw::Fn) { // FUNCTION ITEM self.bump(); @@ -249,8 +254,10 @@ impl<'a> Parser<'a> { }; return self.parse_item_fn(lo, vis, attrs, header); } + if self.check_keyword(kw::Unsafe) - && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) { + && self.look_ahead(1, |t| *t != token::OpenDelim(token::Brace)) + { // UNSAFE FUNCTION ITEM self.bump(); // `unsafe` // `{` is also expected after `unsafe`; in case of error, include it in the diagnostic. @@ -266,11 +273,13 @@ impl<'a> Parser<'a> { }; return self.parse_item_fn(lo, vis, attrs, header); } + if self.eat_keyword(kw::Mod) { // MODULE ITEM - let info = self.parse_item_mod(&attrs[..]); + let info = self.parse_item_mod(&attrs[..])?; return self.mk_item_with_info(attrs, lo, vis, info); } + if let Some(type_) = self.eat_type() { let (ident, alias, generics) = type_?; // TYPE ITEM @@ -281,37 +290,41 @@ impl<'a> Parser<'a> { let span = lo.to(self.prev_span); return Ok(Some(self.mk_item(span, ident, item_, vis, attrs))); } + if self.eat_keyword(kw::Enum) { // ENUM ITEM - let info = self.parse_item_enum(); + let info = self.parse_item_enum()?; return self.mk_item_with_info(attrs, lo, vis, info); } + if self.check_keyword(kw::Trait) || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait])) { - let is_auto = if self.eat_keyword(kw::Trait) { - IsAuto::No - } else { - self.expect_keyword(kw::Auto)?; - self.expect_keyword(kw::Trait)?; - IsAuto::Yes - }; // TRAIT ITEM - let info = self.parse_item_trait(is_auto, Unsafety::Normal); + let is_auto = if self.eat_keyword(kw::Auto) { + IsAuto::Yes + } else { + IsAuto::No + }; + self.expect_keyword(kw::Trait)?; + let info = self.parse_item_trait(is_auto, Unsafety::Normal)?; return self.mk_item_with_info(attrs, lo, vis, info); } + if self.eat_keyword(kw::Struct) { // STRUCT ITEM - let info = self.parse_item_struct(); + let info = self.parse_item_struct()?; return self.mk_item_with_info(attrs, lo, vis, info); } + if self.is_union_item() { // UNION ITEM self.bump(); - let info = self.parse_item_union(); + 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)); } @@ -417,9 +430,9 @@ impl<'a> Parser<'a> { attrs: Vec, lo: Span, vis: Visibility, - info: PResult<'a, ItemInfo>, + info: ItemInfo, ) -> PResult<'a, Option>> { - let (ident, item, extra_attrs) = info?; + let (ident, item, extra_attrs) = info; let span = lo.to(self.prev_span); let attrs = maybe_append(attrs, extra_attrs); Ok(Some(self.mk_item(span, ident, item, vis, attrs))) @@ -1195,10 +1208,8 @@ impl<'a> Parser<'a> { let allow_c_variadic = header.abi == Abi::C && header.unsafety == Unsafety::Unsafe; let (ident, decl, generics) = self.parse_fn_sig(allow_c_variadic)?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - let span = lo.to(self.prev_span); let kind = ItemKind::Fn(decl, header, generics, body); - let attrs = maybe_append(attrs, Some(inner_attrs)); - Ok(Some(self.mk_item(span, ident, kind, vis, attrs))) + self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs))) } /// Parse the "signature", including the identifier, parameters, and generics of a function. From 7f9638d5d4b0b0f4ad592c135e155cdef1ddfb72 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 1 Oct 2019 14:19:08 +0200 Subject: [PATCH 123/545] syntax: unify trait parsing a bit. --- src/libsyntax/parse/parser/item.rs | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 004c179b7c7f..17b23651e807 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -217,14 +217,7 @@ impl<'a> Parser<'a> { { // UNSAFE TRAIT ITEM self.bump(); // `unsafe` - let is_auto = if self.eat_keyword(kw::Trait) { - IsAuto::No - } else { - self.expect_keyword(kw::Auto)?; - self.expect_keyword(kw::Trait)?; - IsAuto::Yes - }; - let info = self.parse_item_trait(is_auto, Unsafety::Unsafe)?; + let info = self.parse_item_trait(Unsafety::Unsafe)?; return self.mk_item_with_info(attrs, lo, vis, info); } @@ -302,13 +295,7 @@ impl<'a> Parser<'a> { && self.is_keyword_ahead(1, &[kw::Trait])) { // TRAIT ITEM - let is_auto = if self.eat_keyword(kw::Auto) { - IsAuto::Yes - } else { - IsAuto::No - }; - self.expect_keyword(kw::Trait)?; - let info = self.parse_item_trait(is_auto, Unsafety::Normal)?; + let info = self.parse_item_trait(Unsafety::Normal)?; return self.mk_item_with_info(attrs, lo, vis, info); } @@ -860,8 +847,16 @@ impl<'a> Parser<'a> { Ok(FnHeader { constness, unsafety, asyncness, abi }) } - /// Parses `trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait(&mut self, is_auto: IsAuto, unsafety: Unsafety) -> PResult<'a, ItemInfo> { + /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. + fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> { + // Parse optional `auto` prefix. + let is_auto = if self.eat_keyword(kw::Auto) { + IsAuto::Yes + } else { + IsAuto::No + }; + + self.expect_keyword(kw::Trait)?; let ident = self.parse_ident()?; let mut tps = self.parse_generics()?; From a7ba754b6c021bc6244cde8c52d3d0b352082560 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 3 Oct 2019 03:39:46 +0200 Subject: [PATCH 124/545] syntax: unify and simplify fn signature parsing. --- src/libsyntax/parse/parser.rs | 96 +++++++++++---------------- src/libsyntax/parse/parser/item.rs | 55 +++++++-------- src/libsyntax/parse/parser/ty.rs | 14 ++-- src/test/ui/parser/issue-33413.rs | 1 + src/test/ui/parser/issue-33413.stderr | 14 +++- 5 files changed, 88 insertions(+), 92 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 93165b096490..4a457f5a43ca 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -11,7 +11,7 @@ mod stmt; mod generics; use crate::ast::{ - self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, FnDecl, Ident, + self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, Ident, IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility, VisibilityKind, Unsafety, }; @@ -56,6 +56,17 @@ crate enum BlockMode { Ignore, } +/// The parsing configuration used to parse a parameter list (see `parse_fn_params`). +struct ParamCfg { + /// Is `self` is allowed as the first parameter? + is_self_allowed: bool, + /// Is `...` allowed as the tail of the parameter list? + allow_c_variadic: bool, + /// `is_name_required` decides if, per-parameter, + /// the parameter must have a pattern or just a type. + is_name_required: fn(&token::Token) -> bool, +} + /// Like `maybe_whole_expr`, but for things other than expressions. #[macro_export] macro_rules! maybe_whole { @@ -1094,26 +1105,18 @@ impl<'a> Parser<'a> { res } - fn parse_fn_params( - &mut self, - named_params: bool, - allow_c_variadic: bool, - ) -> PResult<'a, Vec> { + /// Parses the parameter list of a function, including the `(` and `)` delimiters. + fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec> { let sp = self.token.span; - let do_not_enforce_named_params_for_c_variadic = |token: &token::Token| { - match token.kind { - token::DotDotDot => false, - _ => named_params, - } - }; + let is_trait_item = cfg.is_self_allowed; let mut c_variadic = false; + // Parse the arguments, starting out with `self` being possibly allowed... let (params, _) = self.parse_paren_comma_seq(|p| { - match p.parse_param_general( - false, - false, - allow_c_variadic, - do_not_enforce_named_params_for_c_variadic, - ) { + let param = p.parse_param_general(&cfg, is_trait_item); + // ...now that we've parsed the first argument, `self` is no longer allowed. + cfg.is_self_allowed = false; + + match param { Ok(param) => Ok( if let TyKind::CVarArgs = param.ty.kind { c_variadic = true; @@ -1144,7 +1147,10 @@ impl<'a> Parser<'a> { } })?; - let params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); + let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); + + // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. + self.deduplicate_recovered_params_names(&mut params); if c_variadic && params.len() <= 1 { self.span_err( @@ -1156,79 +1162,53 @@ impl<'a> Parser<'a> { Ok(params) } - /// Parses the parameter list and result type of a function that may have a `self` parameter. - fn parse_fn_decl_with_self( - &mut self, - is_name_required: impl Copy + Fn(&token::Token) -> bool, - ) -> PResult<'a, P> { - // Parse the arguments, starting out with `self` being allowed... - let mut is_self_allowed = true; - let (mut inputs, _): (Vec<_>, _) = self.parse_paren_comma_seq(|p| { - let res = p.parse_param_general(is_self_allowed, true, false, is_name_required); - // ...but now that we've parsed the first argument, `self` is no longer allowed. - is_self_allowed = false; - res - })?; - - // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. - self.deduplicate_recovered_params_names(&mut inputs); - - Ok(P(FnDecl { - inputs, - output: self.parse_ret_ty(true)?, - })) - } - /// Skips unexpected attributes and doc comments in this position and emits an appropriate /// error. /// This version of parse param doesn't necessarily require identifier names. - fn parse_param_general( - &mut self, - is_self_allowed: bool, - is_trait_item: bool, - allow_c_variadic: bool, - is_name_required: impl Fn(&token::Token) -> bool, - ) -> PResult<'a, Param> { + fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. if let Some(mut param) = self.parse_self_param()? { param.attrs = attrs.into(); - return if is_self_allowed { + return if cfg.is_self_allowed { Ok(param) } else { self.recover_bad_self_param(param, is_trait_item) }; } - let is_name_required = is_name_required(&self.token); + let is_name_required = match self.token.kind { + token::DotDotDot => false, + _ => (cfg.is_name_required)(&self.token), + }; let (pat, ty) = if is_name_required || self.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); let pat = self.parse_fn_param_pat()?; if let Err(mut err) = self.expect(&token::Colon) { - if let Some(ident) = self.parameter_without_type( + return if let Some(ident) = self.parameter_without_type( &mut err, pat, is_name_required, - is_self_allowed, + cfg.is_self_allowed, is_trait_item, ) { err.emit(); - return Ok(dummy_arg(ident)); + Ok(dummy_arg(ident)) } else { - return Err(err); - } + Err(err) + }; } self.eat_incorrect_doc_comment_for_param_type(); - (pat, self.parse_ty_common(true, true, allow_c_variadic)?) + (pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?) } else { debug!("parse_param_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); self.eat_incorrect_doc_comment_for_param_type(); - let mut ty = self.parse_ty_common(true, true, allow_c_variadic); + let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic); if ty.is_ok() && self.token != token::Comma && self.token != token::CloseDelim(token::Paren) { // This wasn't actually a type, but a pattern looking like a type, diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 17b23651e807..d2ea0829595c 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -1,4 +1,4 @@ -use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode}; +use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode, ParamCfg}; use crate::maybe_whole; use crate::ptr::P; @@ -805,14 +805,15 @@ impl<'a> Parser<'a> { /// of a method. The body is not parsed as that differs between `trait`s and `impl`s. fn parse_method_sig( &mut self, - is_name_required: impl Copy + Fn(&token::Token) -> bool, + is_name_required: fn(&token::Token) -> bool, ) -> PResult<'a, (Ident, MethodSig, Generics)> { let header = self.parse_fn_front_matter()?; - let (ident, mut generics) = self.parse_fn_header()?; - let decl = self.parse_fn_decl_with_self(is_name_required)?; - let sig = MethodSig { header, decl }; - generics.where_clause = self.parse_where_clause()?; - Ok((ident, sig, generics)) + let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { + is_self_allowed: true, + allow_c_variadic: false, + is_name_required, + })?; + Ok((ident, MethodSig { header, decl }, generics)) } /// Parses all the "front matter" for a `fn` declaration, up to @@ -1200,36 +1201,34 @@ impl<'a> Parser<'a> { attrs: Vec, header: FnHeader, ) -> PResult<'a, Option>> { - let allow_c_variadic = header.abi == Abi::C && header.unsafety == Unsafety::Unsafe; - let (ident, decl, generics) = self.parse_fn_sig(allow_c_variadic)?; + let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { + is_self_allowed: false, + allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe, + is_name_required: |_| true, + })?; let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; let kind = ItemKind::Fn(decl, header, generics, body); self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs))) } /// Parse the "signature", including the identifier, parameters, and generics of a function. - fn parse_fn_sig( - &mut self, - allow_c_variadic: bool, - ) -> PResult<'a, (Ident, P, Generics)> { - let (ident, mut generics) = self.parse_fn_header()?; - let decl = self.parse_fn_decl(allow_c_variadic)?; + fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P, Generics)> { + let ident = self.parse_ident()?; + let mut generics = self.parse_generics()?; + let decl = self.parse_fn_decl(cfg, true)?; generics.where_clause = self.parse_where_clause()?; Ok((ident, decl, generics)) } - /// Parses the name and optional generic types of a function header. - fn parse_fn_header(&mut self) -> PResult<'a, (Ident, Generics)> { - let id = self.parse_ident()?; - let generics = self.parse_generics()?; - Ok((id, generics)) - } - /// Parses the parameter list and result type of a function declaration. - fn parse_fn_decl(&mut self, allow_c_variadic: bool) -> PResult<'a, P> { + pub(super) fn parse_fn_decl( + &mut self, + cfg: ParamCfg, + ret_allow_plus: bool, + ) -> PResult<'a, P> { Ok(P(FnDecl { - inputs: self.parse_fn_params(true, allow_c_variadic)?, - output: self.parse_ret_ty(true)?, + inputs: self.parse_fn_params(cfg)?, + output: self.parse_ret_ty(ret_allow_plus)?, })) } @@ -1353,7 +1352,11 @@ impl<'a> Parser<'a> { extern_sp: Span, ) -> PResult<'a, ForeignItem> { self.expect_keyword(kw::Fn)?; - let (ident, decl, generics) = self.parse_fn_sig(true)?; + let (ident, decl, generics) = self.parse_fn_sig(super::ParamCfg { + is_self_allowed: false, + allow_c_variadic: true, + is_name_required: |_| true, + })?; let span = lo.to(self.token.span); self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?; Ok(ast::ForeignItem { diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index 41ee2a1599d7..c9446a880b0b 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -4,7 +4,7 @@ use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath}; use crate::ptr::P; use crate::ast::{self, Ty, TyKind, MutTy, BareFnTy, FunctionRetTy, GenericParam, Lifetime, Ident}; use crate::ast::{TraitBoundModifier, TraitObjectSyntax, GenericBound, GenericBounds, PolyTraitRef}; -use crate::ast::{Mutability, AnonConst, FnDecl, Mac}; +use crate::ast::{Mutability, AnonConst, Mac}; use crate::parse::token::{self, Token}; use crate::source_map::Span; use crate::symbol::{kw}; @@ -288,12 +288,12 @@ impl<'a> Parser<'a> { }; self.expect_keyword(kw::Fn)?; - let inputs = self.parse_fn_params(false, true)?; - let ret_ty = self.parse_ret_ty(false)?; - let decl = P(FnDecl { - inputs, - output: ret_ty, - }); + let cfg = super::ParamCfg { + is_self_allowed: false, + allow_c_variadic: true, + is_name_required: |_| false, + }; + let decl = self.parse_fn_decl(cfg, false)?; Ok(TyKind::BareFn(P(BareFnTy { abi, unsafety, diff --git a/src/test/ui/parser/issue-33413.rs b/src/test/ui/parser/issue-33413.rs index 22f80a8aae86..7291732cebe4 100644 --- a/src/test/ui/parser/issue-33413.rs +++ b/src/test/ui/parser/issue-33413.rs @@ -3,6 +3,7 @@ struct S; impl S { fn f(*, a: u8) -> u8 {} //~^ ERROR expected parameter name, found `*` + //~| ERROR mismatched types } fn main() {} diff --git a/src/test/ui/parser/issue-33413.stderr b/src/test/ui/parser/issue-33413.stderr index 9e1178e8ac1f..7e5c348e36ce 100644 --- a/src/test/ui/parser/issue-33413.stderr +++ b/src/test/ui/parser/issue-33413.stderr @@ -4,5 +4,17 @@ error: expected parameter name, found `*` LL | fn f(*, a: u8) -> u8 {} | ^ expected parameter name -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/issue-33413.rs:4:23 + | +LL | fn f(*, a: u8) -> u8 {} + | - ^^ expected u8, found () + | | + | implicitly returns `()` as its body has no tail or `return` expression + | + = note: expected type `u8` + found type `()` +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From e70ffed9cdb01ad9f2f27ef4f83de3ebb17f1270 Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Tue, 27 Aug 2019 22:42:44 +0800 Subject: [PATCH 125/545] Add feature gate for raw_dylib. --- src/librustc/middle/cstore.rs | 2 ++ src/librustc_codegen_ssa/back/link.rs | 16 +++++++++++++--- src/librustc_metadata/cstore_impl.rs | 6 +++++- src/librustc_metadata/native_libs.rs | 9 +++++++++ src/libsyntax/feature_gate/active.rs | 3 +++ src/libsyntax/feature_gate/builtin_attrs.rs | 8 +++++++- src/libsyntax_pos/symbol.rs | 2 ++ .../ui/feature-gates/feature-gate-raw-dylib-2.rs | 8 ++++++++ .../feature-gate-raw-dylib-2.stderr | 12 ++++++++++++ .../ui/feature-gates/feature-gate-raw-dylib.rs | 5 +++++ .../feature-gates/feature-gate-raw-dylib.stderr | 12 ++++++++++++ 11 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs create mode 100644 src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-raw-dylib.rs create mode 100644 src/test/ui/feature-gates/feature-gate-raw-dylib.stderr diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 510787998ad0..c45b3dfc3dc6 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -96,6 +96,8 @@ pub enum NativeLibraryKind { NativeStaticNobundle, /// macOS-specific NativeFramework, + /// windows dynamic library without import library + NativeRawDylib, /// default way to specify a dynamic library NativeUnknown, } diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 3b7ae5e33d5e..50d9c088a85e 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -323,6 +323,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session, NativeLibraryKind::NativeStatic => {} NativeLibraryKind::NativeStaticNobundle | NativeLibraryKind::NativeFramework | + NativeLibraryKind::NativeRawDylib | NativeLibraryKind::NativeUnknown => continue, } if let Some(name) = lib.name { @@ -883,7 +884,8 @@ pub fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLibrary Some(format!("-framework {}", name)) }, // These are included, no need to print them - NativeLibraryKind::NativeStatic => None, + NativeLibraryKind::NativeStatic | + NativeLibraryKind::NativeRawDylib => None, } }) .collect(); @@ -1293,7 +1295,11 @@ pub fn add_local_native_libraries(cmd: &mut dyn Linker, NativeLibraryKind::NativeUnknown => cmd.link_dylib(name), NativeLibraryKind::NativeFramework => cmd.link_framework(name), NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(name), - NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(name, &search_path) + NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(name, &search_path), + NativeLibraryKind::NativeRawDylib => { + // FIXME(#58713): Proper handling for raw dylibs. + bug!("raw_dylib feature not yet implemented"); + }, } } } @@ -1678,7 +1684,11 @@ pub fn add_upstream_native_libraries( // ignore statically included native libraries here as we've // already included them when we included the rust library // previously - NativeLibraryKind::NativeStatic => {} + NativeLibraryKind::NativeStatic => {}, + NativeLibraryKind::NativeRawDylib => { + // FIXME(#58713): Proper handling for raw dylibs. + bug!("raw_dylib feature not yet implemented"); + }, } } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 91532d84473a..cce0900bef3d 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -270,7 +270,11 @@ pub fn provide(providers: &mut Providers<'_>) { // resolve! Does this work? Unsure! That's what the issue is about *providers = Providers { is_dllimport_foreign_item: |tcx, id| { - tcx.native_library_kind(id) == Some(NativeLibraryKind::NativeUnknown) + match tcx.native_library_kind(id) { + Some(NativeLibraryKind::NativeUnknown) | + Some(NativeLibraryKind::NativeRawDylib) => true, + _ => false, + } }, is_statically_included_foreign_item: |tcx, id| { match tcx.native_library_kind(id) { diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index fe215d9c7999..df81bd4c09c7 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -73,6 +73,7 @@ impl ItemLikeVisitor<'tcx> for Collector<'tcx> { "static-nobundle" => cstore::NativeStaticNobundle, "dylib" => cstore::NativeUnknown, "framework" => cstore::NativeFramework, + "raw-dylib" => cstore::NativeRawDylib, k => { struct_span_err!(self.tcx.sess, item.span(), E0458, "unknown kind: `{}`", k) @@ -169,6 +170,14 @@ impl Collector<'tcx> { GateIssue::Language, "kind=\"static-nobundle\" is unstable"); } + if lib.kind == cstore::NativeRawDylib && + !self.tcx.features().raw_dylib { + feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, + sym::raw_dylib, + span.unwrap_or_else(|| syntax_pos::DUMMY_SP), + GateIssue::Language, + "kind=\"raw-dylib\" is feature gated"); + } self.libs.push(lib); } diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 20a77fa37cf6..195cd460ee36 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -522,6 +522,9 @@ declare_features! ( /// Allows the definition of `const extern fn` and `const unsafe extern fn`. (active, const_extern_fn, "1.40.0", Some(64926), None), + // Allows the use of raw-dylibs (RFC 2627). + (active, raw_dylib, "1.39.0", Some(58713), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index 80a80ff0a0d4..0dc2f24a67b0 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -276,7 +276,13 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `link_args` attribute is experimental and not portable across platforms, \ it is recommended to use `#[link(name = \"foo\")] instead", ), - + gated!( + link_ordinal, + Whitelisted, + template!(List: "ordinal"), + raw_dylib, + experimental!(link_ordinal) + ), // Plugins: ( sym::plugin_registrar, Normal, template!(Word), diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index cc95dcb3c448..c7230d5ca152 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -389,6 +389,7 @@ symbols! { link_cfg, link_llvm_intrinsics, link_name, + link_ordinal, link_section, LintPass, lint_reasons, @@ -531,6 +532,7 @@ symbols! { RangeInclusive, RangeTo, RangeToInclusive, + raw_dylib, raw_identifiers, Ready, reason, diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs new file mode 100644 index 000000000000..d6aac45d28ff --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs @@ -0,0 +1,8 @@ +#[link(name="foo")] +extern { +#[link_ordinal(42)] +//~^ ERROR: the `#[link_ordinal]` attribute is an experimental feature +fn foo(); +} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr new file mode 100644 index 000000000000..e4ff390819b5 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[link_ordinal]` attribute is an experimental feature + --> $DIR/feature-gate-raw-dylib-2.rs:3:1 + | +LL | #[link_ordinal(42)] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/58713 + = help: add `#![feature(raw_dylib)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib.rs new file mode 100644 index 000000000000..6977f53e56f4 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-raw-dylib.rs @@ -0,0 +1,5 @@ +#[link(name="foo", kind="raw-dylib")] +//~^ ERROR: kind="raw-dylib" is feature gated +extern {} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr b/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr new file mode 100644 index 000000000000..ad5cf4615ae0 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr @@ -0,0 +1,12 @@ +error[E0658]: kind="raw-dylib" is feature gated + --> $DIR/feature-gate-raw-dylib.rs:1:1 + | +LL | #[link(name="foo", kind="raw-dylib")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/58713 + = help: add `#![feature(raw_dylib)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 3462b58f21542b4e26e38419ab3a1b19a1609fdb Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Thu, 29 Aug 2019 01:54:25 +0800 Subject: [PATCH 126/545] Add support for parsing #[link_ordinal] attribute. --- src/librustc/hir/mod.rs | 6 ++++++ src/librustc_typeck/collect.rs | 38 ++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d5892794d649..30b050366887 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2669,6 +2669,11 @@ pub struct CodegenFnAttrs { /// probably isn't set when this is set, this is for foreign items while /// `#[export_name]` is for Rust-defined functions. pub link_name: Option, + /// The `#[link_ordinal = "..."]` attribute, indicating an ordinal an + /// imported function has in the dynamic library. Note that this must not + /// be set when `link_name` is set. This is for foreign items with the + /// "raw-dylib" kind. + pub link_ordinal: Option, /// The `#[target_feature(enable = "...")]` attribute and the enabled /// features (only enabled features are supported right now). pub target_features: Vec, @@ -2728,6 +2733,7 @@ impl CodegenFnAttrs { optimize: OptimizeAttr::None, export_name: None, link_name: None, + link_ordinal: None, target_features: vec![], linkage: None, link_section: None, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d973106058ea..aaebfa86daa6 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2641,6 +2641,35 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } } else if attr.check_name(sym::link_name) { codegen_fn_attrs.link_name = attr.value_str(); + } else if attr.check_name(sym::link_ordinal) { + use syntax::ast::{Lit, LitIntType, LitKind}; + let meta_item_list = attr.meta_item_list(); + let sole_meta_lit = if let Some(meta_item_list) = &meta_item_list { + if meta_item_list.len() == 1 { + meta_item_list.get(0).and_then(|item| item.literal()) + } else { + None + } + } else { + None + }; + if let Some(Lit { node: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = + sole_meta_lit + { + if *ordinal <= std::usize::MAX as u128 { + codegen_fn_attrs.link_ordinal = Some(*ordinal as usize); + } else { + let msg = format!( + "too large ordinal value in link_ordinal \ + value: `{}`", + &ordinal + ); + tcx.sess.span_err(attr.span, &msg); + } + } else { + let msg = "illegal ordinal format in link_ordinal"; + tcx.sess.span_err(attr.span, &msg); + } } } @@ -2742,6 +2771,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.export_name = Some(name); codegen_fn_attrs.link_name = Some(name); } + if codegen_fn_attrs.link_name.is_some() && codegen_fn_attrs.link_ordinal.is_some() { + if let Some(span) = inline_span { + tcx.sess.span_err( + span, + "cannot use `#[link_name]` with \ + `#[link_ordinal]`", + ); + } + } // Internal symbols to the standard library all have no_mangle semantics in // that they have defined symbol names present in the function name. This From eb492455f2b840d28a10a68702727a5227343634 Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Wed, 18 Sep 2019 22:40:08 +0800 Subject: [PATCH 127/545] Address review comments. --- src/librustc/middle/cstore.rs | 2 +- src/librustc_metadata/native_libs.rs | 2 +- src/librustc_typeck/collect.rs | 81 ++++++++++--------- src/libsyntax/feature_gate/active.rs | 1 + src/libsyntax/feature_gate/builtin_attrs.rs | 6 +- .../feature-gates/feature-gate-raw-dylib-2.rs | 8 -- .../feature-gate-raw-dylib-2.rs | 8 ++ .../feature-gate-raw-dylib-2.stderr | 6 +- .../feature-gate-raw-dylib.rs | 2 +- .../feature-gate-raw-dylib.stderr | 2 +- 10 files changed, 63 insertions(+), 55 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs rename src/test/ui/{feature-gates => rfc-2627-raw-dylib}/feature-gate-raw-dylib-2.stderr (77%) rename src/test/ui/{feature-gates => rfc-2627-raw-dylib}/feature-gate-raw-dylib.rs (57%) rename src/test/ui/{feature-gates => rfc-2627-raw-dylib}/feature-gate-raw-dylib.stderr (89%) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index c45b3dfc3dc6..065959ed09fd 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -96,7 +96,7 @@ pub enum NativeLibraryKind { NativeStaticNobundle, /// macOS-specific NativeFramework, - /// windows dynamic library without import library + /// Windows dynamic library without import library. NativeRawDylib, /// default way to specify a dynamic library NativeUnknown, diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index df81bd4c09c7..24ed8fcd8dd0 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -176,7 +176,7 @@ impl Collector<'tcx> { sym::raw_dylib, span.unwrap_or_else(|| syntax_pos::DUMMY_SP), GateIssue::Language, - "kind=\"raw-dylib\" is feature gated"); + "kind=\"raw-dylib\" is unstable"); } self.libs.push(lib); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index aaebfa86daa6..9aeeffa70a13 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2642,33 +2642,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.check_name(sym::link_name) { codegen_fn_attrs.link_name = attr.value_str(); } else if attr.check_name(sym::link_ordinal) { - use syntax::ast::{Lit, LitIntType, LitKind}; - let meta_item_list = attr.meta_item_list(); - let sole_meta_lit = if let Some(meta_item_list) = &meta_item_list { - if meta_item_list.len() == 1 { - meta_item_list.get(0).and_then(|item| item.literal()) - } else { - None - } - } else { - None - }; - if let Some(Lit { node: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = - sole_meta_lit - { - if *ordinal <= std::usize::MAX as u128 { - codegen_fn_attrs.link_ordinal = Some(*ordinal as usize); - } else { - let msg = format!( - "too large ordinal value in link_ordinal \ - value: `{}`", - &ordinal - ); - tcx.sess.span_err(attr.span, &msg); - } - } else { - let msg = "illegal ordinal format in link_ordinal"; - tcx.sess.span_err(attr.span, &msg); + if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) { + codegen_fn_attrs.link_ordinal = ordinal; } } } @@ -2747,6 +2722,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.inline == InlineAttr::Always { if let Some(span) = inline_span { @@ -2771,15 +2747,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.export_name = Some(name); codegen_fn_attrs.link_name = Some(name); } - if codegen_fn_attrs.link_name.is_some() && codegen_fn_attrs.link_ordinal.is_some() { - if let Some(span) = inline_span { - tcx.sess.span_err( - span, - "cannot use `#[link_name]` with \ - `#[link_ordinal]`", - ); - } - } + check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, inline_span); // Internal symbols to the standard library all have no_mangle semantics in // that they have defined symbol names present in the function name. This @@ -2790,3 +2758,44 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs } + +fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { + use syntax::ast::{Lit, LitIntType, LitKind}; + let meta_item_list = attr.meta_item_list(); + let meta_item_list: Option<&[ast::NestedMetaItem]> = meta_item_list.as_ref().map(Vec::as_ref); + let sole_meta_list = match meta_item_list { + Some([item]) => item.literal(), + _ => None, + }; + if let Some(Lit { node: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list { + if *ordinal <= std::usize::MAX as u128 { + Some(*ordinal as usize) + } else { + let msg = format!( + "too large ordinal value in link_ordinal value: `{}`", + &ordinal + ); + tcx.sess.span_err(attr.span, &msg); + None + } + } else { + tcx.sess.span_err(attr.span, "illegal ordinal format in link_ordinal"); + None + } +} + +fn check_link_name_xor_ordinal( + tcx: TyCtxt<'_>, + codegen_fn_attrs: &CodegenFnAttrs, + inline_span: Option, +) { + if codegen_fn_attrs.link_name.is_none() || codegen_fn_attrs.link_ordinal.is_none() { + return; + } + let msg = "cannot use `#[link_name]` with `#[link_ordinal]`"; + if let Some(span) = inline_span { + tcx.sess.span_err(span, msg); + } else { + tcx.sess.err(msg); + } +} diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 195cd460ee36..53bd34d96dd6 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -539,4 +539,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::const_generics, sym::or_patterns, sym::let_chains, + sym::raw_dylib, ]; diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index 0dc2f24a67b0..c12d0ce06ffe 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -277,12 +277,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ it is recommended to use `#[link(name = \"foo\")] instead", ), gated!( - link_ordinal, - Whitelisted, - template!(List: "ordinal"), - raw_dylib, + link_ordinal, Whitelisted, template!(List: "ordinal"), raw_dylib, experimental!(link_ordinal) ), + // Plugins: ( sym::plugin_registrar, Normal, template!(Word), diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs b/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs deleted file mode 100644 index d6aac45d28ff..000000000000 --- a/src/test/ui/feature-gates/feature-gate-raw-dylib-2.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[link(name="foo")] -extern { -#[link_ordinal(42)] -//~^ ERROR: the `#[link_ordinal]` attribute is an experimental feature -fn foo(); -} - -fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs new file mode 100644 index 000000000000..14345bad6e5b --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.rs @@ -0,0 +1,8 @@ +#[link(name="foo")] +extern { + #[link_ordinal(42)] + //~^ ERROR: the `#[link_ordinal]` attribute is an experimental feature + fn foo(); +} + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr similarity index 77% rename from src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr rename to src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr index e4ff390819b5..0869d7ad48a8 100644 --- a/src/test/ui/feature-gates/feature-gate-raw-dylib-2.stderr +++ b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib-2.stderr @@ -1,8 +1,8 @@ error[E0658]: the `#[link_ordinal]` attribute is an experimental feature - --> $DIR/feature-gate-raw-dylib-2.rs:3:1 + --> $DIR/feature-gate-raw-dylib-2.rs:3:5 | -LL | #[link_ordinal(42)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[link_ordinal(42)] + | ^^^^^^^^^^^^^^^^^^^ | = note: for more information, see https://github.com/rust-lang/rust/issues/58713 = help: add `#![feature(raw_dylib)]` to the crate attributes to enable diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib.rs b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs similarity index 57% rename from src/test/ui/feature-gates/feature-gate-raw-dylib.rs rename to src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs index 6977f53e56f4..f0f83e0426dd 100644 --- a/src/test/ui/feature-gates/feature-gate-raw-dylib.rs +++ b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.rs @@ -1,5 +1,5 @@ #[link(name="foo", kind="raw-dylib")] -//~^ ERROR: kind="raw-dylib" is feature gated +//~^ ERROR: kind="raw-dylib" is unstable extern {} fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr similarity index 89% rename from src/test/ui/feature-gates/feature-gate-raw-dylib.stderr rename to src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr index ad5cf4615ae0..0ca9de28be1a 100644 --- a/src/test/ui/feature-gates/feature-gate-raw-dylib.stderr +++ b/src/test/ui/rfc-2627-raw-dylib/feature-gate-raw-dylib.stderr @@ -1,4 +1,4 @@ -error[E0658]: kind="raw-dylib" is feature gated +error[E0658]: kind="raw-dylib" is unstable --> $DIR/feature-gate-raw-dylib.rs:1:1 | LL | #[link(name="foo", kind="raw-dylib")] From dda10f2a2afcdde60bb408d119609dfa00465f02 Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Fri, 20 Sep 2019 01:48:30 +0800 Subject: [PATCH 128/545] Add more tests, fix span issue, improve diagnostics. --- src/librustc_typeck/collect.rs | 14 ++++++++++---- .../link-ordinal-and-name.rs | 12 ++++++++++++ .../link-ordinal-and-name.stderr | 16 ++++++++++++++++ .../link-ordinal-invalid-format.rs | 11 +++++++++++ .../link-ordinal-invalid-format.stderr | 18 ++++++++++++++++++ .../link-ordinal-too-large.rs | 11 +++++++++++ .../link-ordinal-too-large.stderr | 18 ++++++++++++++++++ 7 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs create mode 100644 src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9aeeffa70a13..30b8af996195 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2560,6 +2560,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { let whitelist = tcx.target_features_whitelist(LOCAL_CRATE); let mut inline_span = None; + let mut link_ordinal_span = None; for attr in attrs.iter() { if attr.check_name(sym::cold) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD; @@ -2642,6 +2643,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.check_name(sym::link_name) { codegen_fn_attrs.link_name = attr.value_str(); } else if attr.check_name(sym::link_ordinal) { + link_ordinal_span = Some(attr.span); if let ordinal @ Some(_) = check_link_ordinal(tcx, attr) { codegen_fn_attrs.link_ordinal = ordinal; } @@ -2747,7 +2749,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.export_name = Some(name); codegen_fn_attrs.link_name = Some(name); } - check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, inline_span); + check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span); // Internal symbols to the standard library all have no_mangle semantics in // that they have defined symbol names present in the function name. This @@ -2772,14 +2774,18 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { Some(*ordinal as usize) } else { let msg = format!( - "too large ordinal value in link_ordinal value: `{}`", + "ordinal value in `link_ordinal` is too large: `{}`", &ordinal ); - tcx.sess.span_err(attr.span, &msg); + tcx.sess.struct_span_err(attr.span, &msg) + .note("the value may not exceed `std::usize::MAX`") + .emit(); None } } else { - tcx.sess.span_err(attr.span, "illegal ordinal format in link_ordinal"); + tcx.sess.struct_span_err(attr.span, "illegal ordinal format in `link_ordinal`") + .note("an unsuffixed integer value, e.g., `1`, is expected") + .emit(); None } } diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs new file mode 100644 index 000000000000..5769366fb45a --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs @@ -0,0 +1,12 @@ +#![feature(raw_dylib)] +//~^ WARN the feature `raw_dylib` is incomplete and may cause the compiler to crash + +#[link(name="foo")] +extern { + #[link_name="foo"] + #[link_ordinal(42)] + //~^ ERROR cannot use `#[link_name]` with `#[link_ordinal]` + fn foo(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr new file mode 100644 index 000000000000..303a1c02eb85 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr @@ -0,0 +1,16 @@ +warning: the feature `raw_dylib` is incomplete and may cause the compiler to crash + --> $DIR/link-ordinal-and-name.rs:1:12 + | +LL | #![feature(raw_dylib)] + | ^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: cannot use `#[link_name]` with `#[link_ordinal]` + --> $DIR/link-ordinal-and-name.rs:7:5 + | +LL | #[link_ordinal(42)] + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs new file mode 100644 index 000000000000..82fb1151c23d --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib)] +//~^ WARN the feature `raw_dylib` is incomplete and may cause the compiler to crash + +#[link(name="foo")] +extern { + #[link_ordinal("JustMonika")] + //~^ ERROR illegal ordinal format in `link_ordinal` + fn foo(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr new file mode 100644 index 000000000000..14556a7262b1 --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr @@ -0,0 +1,18 @@ +warning: the feature `raw_dylib` is incomplete and may cause the compiler to crash + --> $DIR/link-ordinal-invalid-format.rs:1:12 + | +LL | #![feature(raw_dylib)] + | ^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: illegal ordinal format in `link_ordinal` + --> $DIR/link-ordinal-invalid-format.rs:6:5 + | +LL | #[link_ordinal("JustMonika")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: an unsuffixed integer value, e.g., `1`, is expected + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs new file mode 100644 index 000000000000..69596ad04fff --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs @@ -0,0 +1,11 @@ +#![feature(raw_dylib)] +//~^ WARN the feature `raw_dylib` is incomplete and may cause the compiler to crash + +#[link(name="foo")] +extern { + #[link_ordinal(18446744073709551616)] + //~^ ERROR ordinal value in `link_ordinal` is too large: `18446744073709551616` + fn foo(); +} + +fn main() {} diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr new file mode 100644 index 000000000000..b3b22f9776df --- /dev/null +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr @@ -0,0 +1,18 @@ +warning: the feature `raw_dylib` is incomplete and may cause the compiler to crash + --> $DIR/link-ordinal-too-large.rs:1:12 + | +LL | #![feature(raw_dylib)] + | ^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: ordinal value in `link_ordinal` is too large: `18446744073709551616` + --> $DIR/link-ordinal-too-large.rs:6:5 + | +LL | #[link_ordinal(18446744073709551616)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the value may not exceed `std::usize::MAX` + +error: aborting due to previous error + From 9c6582a2c0c5a527e3fc3ce581244d85b3b71761 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 7 Oct 2019 06:18:47 +0200 Subject: [PATCH 129/545] syntax: use `parse_extern_abi` more. --- src/libsyntax/parse/parser/ty.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index c9446a880b0b..018b5951e6e2 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -9,8 +9,6 @@ use crate::parse::token::{self, Token}; use crate::source_map::Span; use crate::symbol::{kw}; -use rustc_target::spec::abi::Abi; - use errors::{Applicability, pluralise}; /// Returns `true` if `IDENT t` can start a type -- `IDENT::a::b`, `IDENT`, @@ -281,12 +279,7 @@ impl<'a> Parser<'a> { */ let unsafety = self.parse_unsafety(); - let abi = if self.eat_keyword(kw::Extern) { - self.parse_opt_abi()?.unwrap_or(Abi::C) - } else { - Abi::Rust - }; - + let abi = self.parse_extern_abi()?; self.expect_keyword(kw::Fn)?; let cfg = super::ParamCfg { is_self_allowed: false, From 6b23c22ccad4044476b65fc8f3e32794f1884781 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 7 Oct 2019 06:31:02 +0200 Subject: [PATCH 130/545] syntax: refactor with new `fn parse_use_tree_glob_or_nested`. --- src/libsyntax/parse/parser/item.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index d2ea0829595c..3c60c88e2aa5 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -1077,21 +1077,13 @@ impl<'a> Parser<'a> { ); } - if self.eat(&token::BinOp(token::Star)) { - UseTreeKind::Glob - } else { - UseTreeKind::Nested(self.parse_use_tree_list()?) - } + self.parse_use_tree_glob_or_nested()? } else { // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;` prefix = self.parse_path(PathStyle::Mod)?; if self.eat(&token::ModSep) { - if self.eat(&token::BinOp(token::Star)) { - UseTreeKind::Glob - } else { - UseTreeKind::Nested(self.parse_use_tree_list()?) - } + self.parse_use_tree_glob_or_nested()? } else { UseTreeKind::Simple(self.parse_rename()?, DUMMY_NODE_ID, DUMMY_NODE_ID) } @@ -1100,6 +1092,15 @@ impl<'a> Parser<'a> { Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) }) } + /// Parses `*` or `{...}`. + fn parse_use_tree_glob_or_nested(&mut self) -> PResult<'a, UseTreeKind> { + Ok(if self.eat(&token::BinOp(token::Star)) { + UseTreeKind::Glob + } else { + UseTreeKind::Nested(self.parse_use_tree_list()?) + }) + } + /// Parses a `UseTreeKind::Nested(list)`. /// /// ``` From 2dab187024a80e46689149399249668765c512ea Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Mon, 7 Oct 2019 06:52:35 +0800 Subject: [PATCH 131/545] Fix compilation error after rebase. --- src/librustc_typeck/collect.rs | 2 +- src/libsyntax/feature_gate/active.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 30b8af996195..64eca1371447 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2769,7 +2769,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option { Some([item]) => item.literal(), _ => None, }; - if let Some(Lit { node: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list { + if let Some(Lit { kind: LitKind::Int(ordinal, LitIntType::Unsuffixed), .. }) = sole_meta_list { if *ordinal <= std::usize::MAX as u128 { Some(*ordinal as usize) } else { diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 53bd34d96dd6..19ef430318d3 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -523,7 +523,7 @@ declare_features! ( (active, const_extern_fn, "1.40.0", Some(64926), None), // Allows the use of raw-dylibs (RFC 2627). - (active, raw_dylib, "1.39.0", Some(58713), None), + (active, raw_dylib, "1.40.0", Some(58713), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates From 74eac929c270e896752fb826a3fed34aa0ef5725 Mon Sep 17 00:00:00 2001 From: ben Date: Mon, 7 Oct 2019 20:39:08 +1300 Subject: [PATCH 132/545] Test diagnostic output of type mismatches for types that have const generics arguments. --- .../types-mismatch-const-args.rs | 19 ++++++++++++ .../types-mismatch-const-args.stderr | 29 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/test/ui/const-generics/types-mismatch-const-args.rs create mode 100644 src/test/ui/const-generics/types-mismatch-const-args.stderr diff --git a/src/test/ui/const-generics/types-mismatch-const-args.rs b/src/test/ui/const-generics/types-mismatch-const-args.rs new file mode 100644 index 000000000000..b25b7331017e --- /dev/null +++ b/src/test/ui/const-generics/types-mismatch-const-args.rs @@ -0,0 +1,19 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +// tests the diagnostic output of type mismatches for types that have const generics arguments. + +use std::marker::PhantomData; + +struct A<'a, T, const X: u32, const Y: u32> { + data: PhantomData<&'a T> +} + +fn a<'a, 'b>() { + let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData }; + //~^ ERROR mismatched types + let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + //~^ ERROR mismatched types +} + +pub fn main() {} diff --git a/src/test/ui/const-generics/types-mismatch-const-args.stderr b/src/test/ui/const-generics/types-mismatch-const-args.stderr new file mode 100644 index 000000000000..805a3067d3b6 --- /dev/null +++ b/src/test/ui/const-generics/types-mismatch-const-args.stderr @@ -0,0 +1,29 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/types-mismatch-const-args.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:13:41 + | +LL | let _: A<'a, u32, {2u32}, {3u32}> = A::<'a, u32, {4u32}, {3u32}> { data: PhantomData }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2u32`, found `4u32` + | + = note: expected type `A<'_, _, 2u32, _>` + found type `A<'_, _, 4u32, _>` + +error[E0308]: mismatched types + --> $DIR/types-mismatch-const-args.rs:15:41 + | +LL | let _: A<'a, u16, {2u32}, {3u32}> = A::<'b, u32, {2u32}, {3u32}> { data: PhantomData }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected u16, found u32 + | + = note: expected type `A<'a, u16, _, _>` + found type `A<'b, u32, _, _>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 00bf29bded074ee20460f620cad04205a33df499 Mon Sep 17 00:00:00 2001 From: Felix S Klock II Date: Mon, 7 Oct 2019 10:19:38 +0200 Subject: [PATCH 133/545] Update src/test/ui/nll/issue-63154-normalize.rs review feedback Co-Authored-By: Mazdak Farrokhzad --- src/test/ui/nll/issue-63154-normalize.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/nll/issue-63154-normalize.rs b/src/test/ui/nll/issue-63154-normalize.rs index 2c18dc5d8e09..484c12879d33 100644 --- a/src/test/ui/nll/issue-63154-normalize.rs +++ b/src/test/ui/nll/issue-63154-normalize.rs @@ -1,6 +1,6 @@ // Regression test for rust-lang/rust#63154 // -// Before, we would ICE after faiing to normalize the destination type +// Before, we would ICE after failing to normalize the destination type // when checking call destinations and also when checking MIR // assignment statements. From 2a624c2039305db18db899eaa5883e86a0e0eb9a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 5 Oct 2019 18:43:07 +0200 Subject: [PATCH 134/545] Add new test to heck if all error codes have tests --- src/tools/tidy/src/error_codes_check.rs | 137 ++++++++++++++++++++++++ src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/main.rs | 1 + 3 files changed, 139 insertions(+) create mode 100644 src/tools/tidy/src/error_codes_check.rs diff --git a/src/tools/tidy/src/error_codes_check.rs b/src/tools/tidy/src/error_codes_check.rs new file mode 100644 index 000000000000..159baff184d1 --- /dev/null +++ b/src/tools/tidy/src/error_codes_check.rs @@ -0,0 +1,137 @@ +//! Checks that all error codes have at least one test to prevent having error +//! codes that are silently not thrown by the compiler anymore. + +use std::collections::HashMap; +use std::ffi::OsStr; +use std::path::Path; + +// A few of those error codes can't be tested but all the others can and *should* be tested! +const WHITELIST: &[&str] = &[ + "E0183", + "E0227", + "E0279", + "E0280", + "E0311", + "E0313", + "E0314", + "E0315", + "E0377", + "E0456", + "E0461", + "E0462", + "E0464", + "E0465", + "E0472", + "E0473", + "E0474", + "E0475", + "E0476", + "E0479", + "E0480", + "E0481", + "E0482", + "E0483", + "E0484", + "E0485", + "E0486", + "E0487", + "E0488", + "E0489", + "E0514", + "E0519", + "E0523", + "E0526", + "E0554", + "E0570", + "E0629", + "E0630", + "E0640", + "E0717", + "E0727", + "E0729", +]; + +fn extract_error_codes(f: &str, error_codes: &mut HashMap) { + let mut reached_no_explanation = false; + let mut last_error_code = None; + + for line in f.lines() { + let s = line.trim(); + if s.starts_with('E') && s.ends_with(": r##\"") { + if let Some(err_code) = s.splitn(2, ':').next() { + let err_code = err_code.to_owned(); + last_error_code = Some(err_code.clone()); + if !error_codes.contains_key(&err_code) { + error_codes.insert(err_code, false); + } + } + } else if s.starts_with("```") && s.contains("compile_fail") && s.contains('E') { + if let Some(err_code) = s.splitn(2, 'E').skip(1).next() { + if let Some(err_code) = err_code.splitn(2, ',').next() { + let nb = error_codes.entry(format!("E{}", err_code)).or_insert(false); + *nb = true; + } + } + } else if s == ";" { + reached_no_explanation = true; + } else if reached_no_explanation && s.starts_with('E') { + if let Some(err_code) = s.splitn(2, ',').next() { + let err_code = err_code.to_owned(); + if !error_codes.contains_key(&err_code) { // this check should *never* fail! + error_codes.insert(err_code, false); + } + } + } else if s.starts_with("#### Note: this error code is no longer emitted by the compiler") { + if let Some(last) = last_error_code { + error_codes.get_mut(&last).map(|x| *x = true); + } + last_error_code = None; + } + } +} + +fn extract_error_codes_from_tests(f: &str, error_codes: &mut HashMap) { + for line in f.lines() { + let s = line.trim(); + if s.starts_with("error[E") || s.starts_with("warning[E") { + if let Some(err_code) = s.splitn(2, ']').next() { + if let Some(err_code) = err_code.splitn(2, '[').skip(1).next() { + let nb = error_codes.entry(err_code.to_owned()).or_insert(false); + *nb = true; + } + } + } + } +} + +pub fn check(path: &Path, bad: &mut bool) { + println!("Checking which error codes lack tests..."); + let mut error_codes: HashMap = HashMap::new(); + super::walk(path, + &mut |path| super::filter_dirs(path), + &mut |entry, contents| { + let file_name = entry.file_name(); + if file_name == "error_codes.rs" { + extract_error_codes(contents, &mut error_codes); + } else if entry.path().extension() == Some(OsStr::new("stderr")) { + extract_error_codes_from_tests(contents, &mut error_codes); + } + }); + println!("Found {} error codes", error_codes.len()); + + let mut errors = Vec::new(); + for (err_code, nb) in &error_codes { + if !*nb && !WHITELIST.contains(&err_code.as_str()) { + errors.push(format!("Error code {} needs to have at least one UI test!", err_code)); + } + } + errors.sort(); + for err in &errors { + eprintln!("{}", err); + } + println!("Found {} error codes with no tests", errors.len()); + if !errors.is_empty() { + *bad = true; + } + println!("Done!"); +} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 337f9c4d6dbe..eb93eb297479 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -41,6 +41,7 @@ pub mod extdeps; pub mod ui_tests; pub mod unit_tests; pub mod unstable_book; +pub mod error_codes_check; fn filter_dirs(path: &Path) -> bool { let skip = [ diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index a57238ad8148..e08c23c01fe2 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -35,6 +35,7 @@ fn main() { deps::check_whitelist(&path, &cargo, &mut bad); extdeps::check(&path, &mut bad); ui_tests::check(&path, &mut bad); + error_codes_check::check(&path, &mut bad); if bad { eprintln!("some tidy checks failed"); From 7a8415894febab8eb0e796b26a87458aa9b54345 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 5 Oct 2019 18:52:03 +0200 Subject: [PATCH 135/545] Fix/improve some error codes long explanation --- src/librustc/error_codes.rs | 18 +++++++++------- src/librustc_lint/error_codes.rs | 2 +- src/librustc_mir/error_codes.rs | 2 +- src/librustc_passes/error_codes.rs | 25 ++++++++++++++++++---- src/librustc_privacy/error_codes.rs | 23 +++++++++++++++------ src/librustc_typeck/error_codes.rs | 32 ++++++++++++++--------------- 6 files changed, 66 insertions(+), 36 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 66c51000066b..b6b3514ff4c9 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -466,7 +466,6 @@ fn main() { ``` "##, - E0139: r##" #### Note: this error code is no longer emitted by the compiler. @@ -1521,7 +1520,9 @@ where "##, E0496: r##" -A lifetime name is shadowing another lifetime name. Erroneous code example: +A lifetime name is shadowing another lifetime name. + +Erroneous code example: ```compile_fail,E0496 struct Foo<'a> { @@ -1553,8 +1554,11 @@ fn main() { "##, E0497: r##" -A stability attribute was used outside of the standard library. Erroneous code -example: +#### Note: this error code is no longer emitted by the compiler. + +A stability attribute was used outside of the standard library. + +Erroneous code example: ```compile_fail #[stable] // error: stability attributes may not be used outside of the @@ -2063,7 +2067,7 @@ rejected in your own crates. // E0272, // on_unimplemented #0 // E0273, // on_unimplemented #1 // E0274, // on_unimplemented #2 - E0278, // requirement is not satisfied +// E0278, // requirement is not satisfied E0279, // requirement is not satisfied E0280, // requirement is not satisfied // E0285, // overflow evaluation builtin bounds @@ -2106,10 +2110,10 @@ rejected in your own crates. E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders E0697, // closures cannot be static - E0707, // multiple elided lifetimes used in arguments of `async fn` +// E0707, // multiple elided lifetimes used in arguments of `async fn` E0708, // `async` non-`move` closures with parameters are not currently // supported - E0709, // multiple different lifetimes used in arguments of `async fn` +// E0709, // multiple different lifetimes used in arguments of `async fn` E0710, // an unknown tool name found in scoped lint E0711, // a feature has been declared with conflicting stability attributes // E0702, // replaced with a generic attribute input check diff --git a/src/librustc_lint/error_codes.rs b/src/librustc_lint/error_codes.rs index ea2e1d9ecc53..2edc8fadf456 100644 --- a/src/librustc_lint/error_codes.rs +++ b/src/librustc_lint/error_codes.rs @@ -1,4 +1,4 @@ syntax::register_diagnostics! { ; - E0721, // `await` keyword +// E0721, // `await` keyword } diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index fb1311de9a70..77853ff1fe80 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -953,7 +953,7 @@ https://doc.rust-lang.org/std/cell/ "##, E0388: r##" -E0388 was removed and is no longer issued. +#### Note: this error code is no longer emitted by the compiler. "##, E0389: r##" diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index 82cbcf458b07..0a21f56287da 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -1,12 +1,15 @@ syntax::register_diagnostics! { -/* E0014: r##" +#### Note: this error code is no longer emitted by the compiler. + Constants can only be initialized by a constant value or, in a future version of Rust, a call to a const function. This error indicates the use of a path (like a::b, or x) denoting something other than one of these -allowed items. Erroneous code xample: +allowed items. -```compile_fail +Erroneous code example: + +``` const FOO: i32 = { let x = 0; x }; // 'x' isn't a constant nor a function! ``` @@ -18,10 +21,10 @@ const FOO: i32 = { const X : i32 = 0; X }; const FOO2: i32 = { 0 }; // but brackets are useless here ``` "##, -*/ E0130: r##" You declared a pattern as an argument in a foreign function declaration. + Erroneous code example: ```compile_fail @@ -57,6 +60,20 @@ extern { E0136: r##" A binary can only have one entry point, and by default that entry point is the function `main()`. If there are multiple such functions, please rename one. + +Erroneous code example: + +```compile_fail,E0136 +fn main() { + // ... +} + +// ... + +fn main() { // error! + // ... +} +``` "##, E0137: r##" diff --git a/src/librustc_privacy/error_codes.rs b/src/librustc_privacy/error_codes.rs index 67066466f1d2..03afb547d3a2 100644 --- a/src/librustc_privacy/error_codes.rs +++ b/src/librustc_privacy/error_codes.rs @@ -1,8 +1,9 @@ syntax::register_diagnostics! { E0445: r##" -A private trait was used on a public type parameter bound. Erroneous code -examples: +A private trait was used on a public type parameter bound. + +Erroneous code examples: ```compile_fail,E0445 #![deny(private_in_public)] @@ -32,7 +33,9 @@ pub fn foo (t: T) {} // ok! "##, E0446: r##" -A private type was used in a public type signature. Erroneous code example: +A private type was used in a public type signature. + +Erroneous code example: ```compile_fail,E0446 #![deny(private_in_public)] @@ -65,7 +68,9 @@ mod Foo { E0447: r##" #### Note: this error code is no longer emitted by the compiler. -The `pub` keyword was used inside a function. Erroneous code example: +The `pub` keyword was used inside a function. + +Erroneous code example: ``` fn foo() { @@ -79,7 +84,11 @@ is invalid. "##, E0448: r##" -The `pub` keyword was used inside a public enum. Erroneous code example: +#### Note: this error code is no longer emitted by the compiler. + +The `pub` keyword was used inside a public enum. + +Erroneous code example: ```compile_fail pub enum Foo { @@ -106,7 +115,9 @@ pub enum Foo { "##, E0451: r##" -A struct constructor with private fields was invoked. Erroneous code example: +A struct constructor with private fields was invoked. + +Erroneous code example: ```compile_fail,E0451 mod Bar { diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 3a07171b12fb..8bd899ae4d5c 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -1873,13 +1873,14 @@ This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this differs from the behavior for `&T`, which is always `Copy`). "##, -/* E0205: r##" +#### Note: this error code is no longer emitted by the compiler. + An attempt to implement the `Copy` trait for an enum failed because one of the variants does not implement `Copy`. To fix this, you must implement `Copy` for the mentioned variant. Note that this may not be possible, as in the example of -```compile_fail,E0205 +```compile_fail,E0204 enum Foo { Bar(Vec), Baz, @@ -1892,7 +1893,7 @@ This fails because `Vec` does not implement `Copy` for any `T`. Here's another example that will fail: -```compile_fail,E0205 +```compile_fail,E0204 #[derive(Copy)] enum Foo<'a> { Bar(&'a mut bool), @@ -1903,7 +1904,6 @@ enum Foo<'a> { This fails because `&mut T` is not `Copy`, even when `T` is `Copy` (this differs from the behavior for `&T`, which is always `Copy`). "##, -*/ E0206: r##" You can only implement `Copy` for a struct or enum. Both of the following @@ -2126,8 +2126,9 @@ For information on the design of the orphan rules, see [RFC 1023]. [RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md "##, -/* E0211: r##" +#### Note: this error code is no longer emitted by the compiler. + You used a function or type which doesn't fit the requirements for where it was used. Erroneous code examples: @@ -2174,7 +2175,7 @@ extern "rust-intrinsic" { } ``` -The second case example is a bit particular : the main function must always +The second case example is a bit particular: the main function must always have this definition: ```compile_fail @@ -2206,7 +2207,6 @@ impl Foo { } ``` "##, - */ E0220: r##" You used an associated type which isn't defined in the trait. @@ -2727,14 +2727,9 @@ impl CoerceUnsized> for MyType [`CoerceUnsized`]: https://doc.rust-lang.org/std/ops/trait.CoerceUnsized.html "##, -/* -// Associated consts can now be accessed through generic type parameters, and -// this error is no longer emitted. -// -// FIXME: consider whether to leave it in the error index, or remove it entirely -// as associated consts is not stabilized yet. - E0329: r##" +#### Note: this error code is no longer emitted by the compiler. + An attempt was made to access an associated constant through either a generic type parameter or `Self`. This is not supported yet. An example causing this error is shown below: @@ -2765,12 +2760,15 @@ trait Foo { struct MyStruct; +impl Foo for MyStruct { + const BAR: f64 = 0f64; +} + fn get_bar_good() -> f64 { ::BAR } ``` "##, -*/ E0366: r##" An attempt was made to implement `Drop` on a concrete specialization of a @@ -4973,7 +4971,7 @@ and the pin is required to keep it in the same place in memory. // between structures with the same definition // E0558, // replaced with a generic attribute input check // E0563, // cannot determine a type for this `impl Trait` removed in 6383de15 - E0564, // only named lifetimes are allowed in `impl Trait`, +// E0564, // only named lifetimes are allowed in `impl Trait`, // but `{}` was found in the type `{}` E0587, // type has conflicting packed and align representation hints E0588, // packed type cannot transitively contain a `[repr(align)]` type @@ -4986,7 +4984,7 @@ and the pin is required to keep it in the same place in memory. E0634, // type has conflicting packed representaton hints E0640, // infer outlives requirements E0641, // cannot cast to/from a pointer with an unknown kind - E0645, // trait aliases not finished +// E0645, // trait aliases not finished E0719, // duplicate values for associated type binding E0722, // Malformed `#[optimize]` attribute E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions From 4bf7eea8971f08789a53346e3aecefd8e3193d4f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Oct 2019 13:58:46 +0200 Subject: [PATCH 136/545] Add long error explanation for E0561 --- src/librustc_passes/error_codes.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index 82cbcf458b07..a3c46f7a6fc9 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -286,6 +286,34 @@ fn main() { ``` "##, +E0561: r##" +A non-ident or non-wildcard pattern has been used as a parameter of a function +pointer type. + +Erroneous code example: + +```compile_fail,E0561 +type A1 = fn(mut param: u8); // error! +type A2 = fn(¶m: u32); // error! +``` + +When using an alias over a function type, you cannot e.g. denote a parameter as +being mutable. + +To fix the issue, remove patterns (`_` is allowed though). Example: + +``` +type A1 = fn(param: u8); // ok! +type A2 = fn(_: u32); // ok! +``` + +You can also omit the parameter name: + +``` +type A3 = fn(i16); // ok! +``` +"##, + E0571: r##" A `break` statement with an argument appeared in a non-`loop` loop. @@ -503,7 +531,6 @@ Switch to the Rust 2018 edition to use `async fn`. ; E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target - E0561, // patterns aren't allowed in function pointer types E0567, // auto traits can not have generic parameters E0568, // auto traits can not have super traits E0666, // nested `impl Trait` is illegal From 8dd00088c1955c2298ef7e8ea27b01c6ff83ad2c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 4 Oct 2019 13:58:56 +0200 Subject: [PATCH 137/545] Update ui tests --- src/test/ui/no-patterns-in-args-macro.stderr | 2 +- src/test/ui/no-patterns-in-args.stderr | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/ui/no-patterns-in-args-macro.stderr b/src/test/ui/no-patterns-in-args-macro.stderr index 680430a05ee8..f21df68d5a2c 100644 --- a/src/test/ui/no-patterns-in-args-macro.stderr +++ b/src/test/ui/no-patterns-in-args-macro.stderr @@ -18,5 +18,5 @@ LL | m!((bad, pat)); error: aborting due to 3 previous errors -Some errors have detailed explanations: E0130, E0642. +Some errors have detailed explanations: E0130, E0561, E0642. For more information about an error, try `rustc --explain E0130`. diff --git a/src/test/ui/no-patterns-in-args.stderr b/src/test/ui/no-patterns-in-args.stderr index b65e0ecd253e..1c2ce8664678 100644 --- a/src/test/ui/no-patterns-in-args.stderr +++ b/src/test/ui/no-patterns-in-args.stderr @@ -30,4 +30,5 @@ LL | type A2 = fn(&arg: u8); error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0130`. +Some errors have detailed explanations: E0130, E0561. +For more information about an error, try `rustc --explain E0130`. From 25d04f83e306a5be0a24807252fe21df9d3d4703 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 7 Oct 2019 10:57:44 -0400 Subject: [PATCH 138/545] make type-flags exhaustive Didn't find any bugs here, but you really don't want these to fall out of sync. --- src/librustc/ty/flags.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index b513ef5a9667..16fb7dca61ef 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -250,7 +250,9 @@ impl FlagComputation { ConstValue::Placeholder(_) => { self.add_flags(TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_CT_PLACEHOLDER); } - _ => {}, + ConstValue::Scalar(_) => { } + ConstValue::Slice { data: _, start: _, end: _ } => { } + ConstValue::ByRef { alloc: _, offset: _ } => { } } } From 0b58d9d1248198471cf641b70032ac4fab0e206a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 7 Oct 2019 10:58:14 -0400 Subject: [PATCH 139/545] correct bug in the "has escaping regions" visitor Existing code could overlook types/substitutions that are embedded in (e.g.) an unevaluated constant. --- src/librustc/ty/fold.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index f6a5092d30d4..5192075c26e9 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -911,13 +911,15 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor { } fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> bool { - if let ty::Const { - val: ConstValue::Infer(ty::InferConst::Canonical(debruijn, _)), - .. - } = *ct { - debruijn >= self.outer_index - } else { - false + // we don't have a `visit_infer_const` callback, so we have to + // hook in here to catch this case (annoying...), but + // otherwise we do want to remember to visit the rest of the + // const, as it has types/regions embedded in a lot of other + // places. + match ct.val { + ConstValue::Infer(ty::InferConst::Canonical(debruijn, _)) + if debruijn >= self.outer_index => true, + _ => ct.super_visit_with(self), } } } From bec090253534b651388e90ec39a7b996fdf48600 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 7 Oct 2019 10:59:13 -0400 Subject: [PATCH 140/545] avoid ICE when extracting closure-kind-ty from a canonicalized value In such a case, the `Infer` is converted to a `Bound` --- src/librustc/ty/sty.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 3f09bf749edc..10935863d531 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2199,7 +2199,9 @@ impl<'tcx> TyS<'tcx> { _ => bug!("cannot convert type `{:?}` to a closure kind", self), }, - Infer(_) => None, + // "Bound" types appear in canonical queries when the + // closure type is not yet known + Bound(..) | Infer(_) => None, Error => Some(ty::ClosureKind::Fn), From 1dba4b0117533d076b7c750b77b37655f72c530a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 7 Oct 2019 10:59:46 -0400 Subject: [PATCH 141/545] fix ICE from debug output by using `kind_ty` in dumping closure Also, make `-Zverbose` dump all info about constants. --- src/librustc/ty/print/pretty.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index ad4be788dae4..aa093329a51b 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -689,7 +689,7 @@ pub trait PrettyPrinter<'tcx>: if self.tcx().sess.verbose() { p!(write( " closure_kind_ty={:?} closure_sig_ty={:?}", - substs.as_closure().kind(did, self.tcx()), + substs.as_closure().kind_ty(did, self.tcx()), substs.as_closure().sig_ty(did, self.tcx()) )); } @@ -698,7 +698,9 @@ pub trait PrettyPrinter<'tcx>: }, ty::Array(ty, sz) => { p!(write("["), print(ty), write("; ")); - if let ConstValue::Unevaluated(..) = sz.val { + if self.tcx().sess.verbose() { + p!(write("{:?}", sz)); + } else if let ConstValue::Unevaluated(..) = sz.val { // do not try to evalute 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. @@ -855,6 +857,11 @@ pub trait PrettyPrinter<'tcx>: ) -> Result { define_scoped_cx!(self); + if self.tcx().sess.verbose() { + p!(write("Const({:?}: {:?})", ct.val, ct.ty)); + return Ok(self); + } + let u8 = self.tcx().types.u8; if let ty::FnDef(did, substs) = ct.ty.kind { p!(print_value_path(did, substs)); From 08c0e841a7a9af0f2466fc75383c629e656825a3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 7 Oct 2019 11:00:09 -0400 Subject: [PATCH 142/545] add `debug!` to evaluate_obligation --- src/librustc_traits/evaluate_obligation.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index 30a1814d0f83..dc7eeead30cb 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -17,10 +17,12 @@ fn evaluate_obligation<'tcx>( tcx: TyCtxt<'tcx>, canonical_goal: CanonicalPredicateGoal<'tcx>, ) -> Result { + debug!("evaluate_obligation(canonical_goal={:#?})", canonical_goal); tcx.infer_ctxt().enter_with_canonical( DUMMY_SP, &canonical_goal, |ref infcx, goal, _canonical_inference_vars| { + debug!("evaluate_obligation: goal={:#?}", goal); let ParamEnvAnd { param_env, value: predicate, From 543449d4fdf7bb7fd4a12c2fea96dafbe26eea90 Mon Sep 17 00:00:00 2001 From: Ayose Date: Sat, 20 Jul 2019 00:55:58 +0000 Subject: [PATCH 143/545] [RFC 2091] Add #[track_caller] attribute. - The attribute is behind a feature gate. - Error if both #[naked] and #[track_caller] are applied to the same function. - Error if #[track_caller] is applied to a non-function item. - Error if ABI is not "rust" - Error if #[track_caller] is applied to a trait function. Error codes and descriptions are pending. --- .../src/language-features/track-caller.md | 5 +++ src/librustc/error_codes.rs | 10 ++++++ src/librustc/hir/check_attr.rs | 34 +++++++++++++++++++ src/librustc/hir/mod.rs | 4 ++- src/librustc_typeck/check/wfcheck.rs | 12 +++++++ src/librustc_typeck/collect.rs | 10 ++++++ src/librustc_typeck/error_codes.rs | 11 ++++++ src/libsyntax/feature_gate/active.rs | 3 ++ src/libsyntax/feature_gate/builtin_attrs.rs | 4 +++ src/libsyntax_pos/symbol.rs | 1 + .../feature-gate-track_caller.rs | 6 ++++ .../feature-gate-track_caller.stderr | 12 +++++++ .../rfc-2091-track-caller/error-odd-syntax.rs | 7 ++++ .../error-odd-syntax.stderr | 8 +++++ .../error-with-invalid-abi.rs | 7 ++++ .../error-with-invalid-abi.stderr | 9 +++++ .../rfc-2091-track-caller/error-with-naked.rs | 8 +++++ .../error-with-naked.stderr | 9 +++++ .../error-with-trait-fns.rs | 13 +++++++ .../error-with-trait-fns.stderr | 9 +++++ .../ui/rfc-2091-track-caller/only-for-fns.rs | 7 ++++ .../rfc-2091-track-caller/only-for-fns.stderr | 11 ++++++ 22 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 src/doc/unstable-book/src/language-features/track-caller.md create mode 100644 src/test/ui/feature-gates/feature-gate-track_caller.rs create mode 100644 src/test/ui/feature-gates/feature-gate-track_caller.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-naked.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-naked.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/only-for-fns.rs create mode 100644 src/test/ui/rfc-2091-track-caller/only-for-fns.stderr diff --git a/src/doc/unstable-book/src/language-features/track-caller.md b/src/doc/unstable-book/src/language-features/track-caller.md new file mode 100644 index 000000000000..afc11a2b9492 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/track-caller.md @@ -0,0 +1,5 @@ +# `track_caller` + +The tracking issue for this feature is: [#47809](https://github.com/rust-lang/rust/issues/47809). + +------------------------ diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 502172db91c9..959a06c2e32f 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1640,6 +1640,16 @@ each method; it is not possible to annotate the entire impl with an `#[inline]` attribute. "##, +E0900: r##" +TODO: change error number +TODO: track_caller: invalid syntax +"##, + +E0901: r##" +TODO: change error number +TODO: track_caller: no naked functions +"##, + E0522: r##" The lang attribute is intended for marking special items that are built-in to Rust itself. This includes special traits (like `Copy` and `Sized`) that affect diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index d5e956555bdf..31a09645d169 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -94,6 +94,7 @@ impl CheckAttrVisitor<'tcx> { /// Checks any attribute. fn check_attributes(&self, item: &hir::Item, target: Target) { let mut is_valid = true; + let mut track_caller_span = None; for attr in &item.attrs { is_valid &= if attr.check_name(sym::inline) { self.check_inline(attr, &item.span, target) @@ -103,6 +104,9 @@ impl CheckAttrVisitor<'tcx> { self.check_marker(attr, item, target) } else if attr.check_name(sym::target_feature) { self.check_target_feature(attr, item, target) + } else if attr.check_name(sym::track_caller) { + track_caller_span = Some(attr.span); + self.check_track_caller(attr, &item, target) } else { true }; @@ -118,6 +122,19 @@ impl CheckAttrVisitor<'tcx> { self.check_repr(item, target); self.check_used(item, target); + + // Checks if `#[track_caller]` and `#[naked]` are both used. + if let Some(span) = track_caller_span { + if item.attrs.iter().any(|attr| attr.check_name(sym::naked)) { + struct_span_err!( + self.tcx.sess, + span, + E0901, + "cannot use `#[track_caller]` with `#[naked]`", + ) + .emit(); + } + } } /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid. @@ -135,6 +152,23 @@ impl CheckAttrVisitor<'tcx> { } } + /// Checks if a `#[target_feature]` can be applied. + fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool { + if target != Target::Fn { + struct_span_err!( + self.tcx.sess, + attr.span, + E0900, + "attribute should be applied to function" + ) + .span_label(item.span, "not a function") + .emit(); + false + } else { + true + } + } + /// Checks if the `#[non_exhaustive]` attribute on an `item` is valid. Returns `true` if valid. fn check_non_exhaustive( &self, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 30b050366887..f7240d6bf820 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2721,7 +2721,9 @@ bitflags! { const USED = 1 << 9; /// #[ffi_returns_twice], indicates that an extern function can return /// multiple times - const FFI_RETURNS_TWICE = 1 << 10; + const FFI_RETURNS_TWICE = 1 << 10; + /// #[track_caller]: allow access to the caller location + const TRACK_CALLER = 1 << 11; } } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e736a55a5f51..3c9010de5cb7 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -172,6 +172,18 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) { _ => None }; check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig); + + // Prohibits applying `#[track_caller]` to trait methods + for attr in &trait_item.attrs { + if attr.check_name(sym::track_caller) { + struct_span_err!( + tcx.sess, + attr.span, + E0903, + "`#[track_caller]` is not supported for trait items yet." + ).emit(); + } + } } pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 64eca1371447..0b98e4b781d7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2594,6 +2594,16 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; } 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 { + struct_span_err!( + tcx.sess, + attr.span, + E0902, + "rust ABI is required to use `#[track_caller]`" + ).emit(); + } + 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") { diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 3a07171b12fb..f698427c78ad 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4907,6 +4907,17 @@ fn foo_recursive(n: usize) -> Pin>> { The `Box<...>` ensures that the result is of known size, and the pin is required to keep it in the same place in memory. "##, + +E0902: r##" +TODO: change error number +TODO: track_caller: require Rust ABI to use track_caller +"##, + +E0903: r##" +TODO: change error number +TODO: track_caller: can't apply in traits +"##, + ; // E0035, merged into E0087/E0089 // E0036, merged into E0087/E0089 diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 19ef430318d3..312a9bf6e755 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -525,6 +525,9 @@ declare_features! ( // Allows the use of raw-dylibs (RFC 2627). (active, raw_dylib, "1.40.0", Some(58713), None), + /// Enable accurate caller location reporting during panic (RFC 2091). + (active, track_caller, "1.37.0", Some(47809), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index c12d0ce06ffe..d6a6450e471b 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -499,6 +499,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ cfg_fn!(no_debug) ) ), + gated!( + track_caller, Whitelisted, template!(Word), + "the `#[track_caller]` attribute is an experimental feature", + ), gated!( // Used in resolve: prelude_import, Whitelisted, template!(Word), diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index c7230d5ca152..2b005c3fc421 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -674,6 +674,7 @@ symbols! { tool_attributes, tool_lints, trace_macros, + track_caller, trait_alias, transmute, transparent, diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs new file mode 100644 index 000000000000..458df0b2b028 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-track_caller.rs @@ -0,0 +1,6 @@ + +#[track_caller] +fn f() {} +//~^^ ERROR the `#[track_caller]` attribute is an experimental feature + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr new file mode 100644 index 000000000000..9a058736e508 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-track_caller.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[track_caller]` attribute is an experimental feature + --> $DIR/feature-gate-track_caller.rs:2:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/47809 + = help: add `#![feature(track_caller)]` 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/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs new file mode 100644 index 000000000000..d6560231871c --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs @@ -0,0 +1,7 @@ +#![feature(track_caller)] + +#[track_caller(1)] +fn f() {} +//~^^ ERROR malformed `track_caller` attribute input + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr new file mode 100644 index 000000000000..8906fa59506a --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr @@ -0,0 +1,8 @@ +error: malformed `track_caller` attribute input + --> $DIR/error-odd-syntax.rs:3:1 + | +LL | #[track_caller(1)] + | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` + +error: aborting due to previous error + diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs new file mode 100644 index 000000000000..5c42a1b3faa2 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs @@ -0,0 +1,7 @@ +#![feature(track_caller)] + +#[track_caller] +extern "C" fn f() {} +//~^^ ERROR rust ABI is required to use `#[track_caller]` + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr new file mode 100644 index 000000000000..fc6f4d17dcc4 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr @@ -0,0 +1,9 @@ +error[E0902]: rust ABI is required to use `#[track_caller]` + --> $DIR/error-with-invalid-abi.rs:3:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0902`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs new file mode 100644 index 000000000000..dd9e5d041358 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs @@ -0,0 +1,8 @@ +#![feature(naked_functions, track_caller)] + +#[track_caller] +#[naked] +fn f() {} +//~^^^ ERROR cannot use `#[track_caller]` with `#[naked]` + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr new file mode 100644 index 000000000000..3566d288ed10 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -0,0 +1,9 @@ +error[E0901]: cannot use `#[track_caller]` with `#[naked]` + --> $DIR/error-with-naked.rs:3:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0901`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs new file mode 100644 index 000000000000..c00cf7367ce5 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs @@ -0,0 +1,13 @@ +#![feature(track_caller)] + +trait Trait { + #[track_caller] + fn unwrap(&self); + //~^^ ERROR: `#[track_caller]` is not supported for trait items yet. +} + +impl Trait for u64 { + fn unwrap(&self) {} +} + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr new file mode 100644 index 000000000000..bd3d4043a642 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr @@ -0,0 +1,9 @@ +error[E0903]: `#[track_caller]` is not supported for trait items yet. + --> $DIR/error-with-trait-fns.rs:4:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0903`. diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs new file mode 100644 index 000000000000..0fd59b4bf491 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs @@ -0,0 +1,7 @@ +#![feature(track_caller)] + +#[track_caller] +struct S; +//~^^ ERROR attribute should be applied to function + +fn main() {} 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 new file mode 100644 index 000000000000..9ddc99c02bf9 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -0,0 +1,11 @@ +error[E0900]: attribute should be applied to function + --> $DIR/only-for-fns.rs:3:1 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ +LL | struct S; + | --------- not a function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0900`. From 6c04c8eb8e361649fb541f918e373b23d2d7f772 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 18:24:10 -0700 Subject: [PATCH 144/545] track_caller run-pass test, lint cleanup, PR review. --- src/librustc/error_codes.rs | 8 +++--- src/librustc/hir/check_attr.rs | 28 ++++++++----------- src/librustc_typeck/error_codes.rs | 8 +++--- src/libsyntax/feature_gate/active.rs | 2 +- src/libsyntax/feature_gate/builtin_attrs.rs | 5 +--- .../feature-gate-track_caller.rs | 1 - .../feature-gate-track_caller.stderr | 2 +- src/test/ui/rfc-2091-track-caller/pass.rs | 9 ++++++ 8 files changed, 31 insertions(+), 32 deletions(-) create mode 100644 src/test/ui/rfc-2091-track-caller/pass.rs diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 959a06c2e32f..b2671e48be68 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1641,13 +1641,13 @@ attribute. "##, E0900: r##" -TODO: change error number -TODO: track_caller: invalid syntax +FIXME(anp): change error number +FIXME(anp): track_caller: invalid syntax "##, E0901: r##" -TODO: change error number -TODO: track_caller: no naked functions +FIXME(anp): change error number +FIXME(anp): track_caller: no naked functions "##, E0522: r##" diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 31a09645d169..66415e26281b 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -11,7 +11,7 @@ use crate::ty::TyCtxt; use crate::ty::query::Providers; use std::fmt::{self, Display}; -use syntax::symbol::sym; +use syntax::{attr, symbol::sym}; use syntax_pos::Span; #[derive(Copy, Clone, PartialEq)] @@ -94,7 +94,6 @@ impl CheckAttrVisitor<'tcx> { /// Checks any attribute. fn check_attributes(&self, item: &hir::Item, target: Target) { let mut is_valid = true; - let mut track_caller_span = None; for attr in &item.attrs { is_valid &= if attr.check_name(sym::inline) { self.check_inline(attr, &item.span, target) @@ -105,7 +104,6 @@ impl CheckAttrVisitor<'tcx> { } else if attr.check_name(sym::target_feature) { self.check_target_feature(attr, item, target) } else if attr.check_name(sym::track_caller) { - track_caller_span = Some(attr.span); self.check_track_caller(attr, &item, target) } else { true @@ -122,19 +120,6 @@ impl CheckAttrVisitor<'tcx> { self.check_repr(item, target); self.check_used(item, target); - - // Checks if `#[track_caller]` and `#[naked]` are both used. - if let Some(span) = track_caller_span { - if item.attrs.iter().any(|attr| attr.check_name(sym::naked)) { - struct_span_err!( - self.tcx.sess, - span, - E0901, - "cannot use `#[track_caller]` with `#[naked]`", - ) - .emit(); - } - } } /// Checks if an `#[inline]` is applied to a function or a closure. Returns `true` if valid. @@ -152,7 +137,7 @@ impl CheckAttrVisitor<'tcx> { } } - /// Checks if a `#[target_feature]` can be applied. + /// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid. fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Target) -> bool { if target != Target::Fn { struct_span_err!( @@ -164,6 +149,15 @@ impl CheckAttrVisitor<'tcx> { .span_label(item.span, "not a function") .emit(); false + } else if attr::contains_name(&item.attrs, sym::naked) { + struct_span_err!( + self.tcx.sess, + attr.span, + E0901, + "cannot use `#[track_caller]` with `#[naked]`", + ) + .emit(); + false } else { true } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index f698427c78ad..1ebae19c7d90 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4909,13 +4909,13 @@ and the pin is required to keep it in the same place in memory. "##, E0902: r##" -TODO: change error number -TODO: track_caller: require Rust ABI to use track_caller +FIXME(anp): change error number +FIXME(anp): track_caller: require Rust ABI to use track_caller "##, E0903: r##" -TODO: change error number -TODO: track_caller: can't apply in traits +FIXME(anp): change error number +FIXME(anp): track_caller: can't apply in traits "##, ; diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 312a9bf6e755..c90b18fc3976 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -526,7 +526,7 @@ declare_features! ( (active, raw_dylib, "1.40.0", Some(58713), None), /// Enable accurate caller location reporting during panic (RFC 2091). - (active, track_caller, "1.37.0", Some(47809), None), + (active, track_caller, "1.39.0", Some(47809), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index d6a6450e471b..ae23cc5cb933 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -324,6 +324,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)), // ========================================================================== // Internal attributes: Stability, deprecation, and unsafe: @@ -499,10 +500,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ cfg_fn!(no_debug) ) ), - gated!( - track_caller, Whitelisted, template!(Word), - "the `#[track_caller]` attribute is an experimental feature", - ), gated!( // Used in resolve: prelude_import, Whitelisted, template!(Word), diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.rs b/src/test/ui/feature-gates/feature-gate-track_caller.rs index 458df0b2b028..5865cf0a4f75 100644 --- a/src/test/ui/feature-gates/feature-gate-track_caller.rs +++ b/src/test/ui/feature-gates/feature-gate-track_caller.rs @@ -1,4 +1,3 @@ - #[track_caller] fn f() {} //~^^ ERROR the `#[track_caller]` attribute is an experimental feature diff --git a/src/test/ui/feature-gates/feature-gate-track_caller.stderr b/src/test/ui/feature-gates/feature-gate-track_caller.stderr index 9a058736e508..b890019ee4f3 100644 --- a/src/test/ui/feature-gates/feature-gate-track_caller.stderr +++ b/src/test/ui/feature-gates/feature-gate-track_caller.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[track_caller]` attribute is an experimental feature - --> $DIR/feature-gate-track_caller.rs:2:1 + --> $DIR/feature-gate-track_caller.rs:1:1 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs new file mode 100644 index 000000000000..eef83b3d68f9 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/pass.rs @@ -0,0 +1,9 @@ +// run-pass +#![feature(track_caller)] + +#[track_caller] +fn f() {} + +fn main() { + f(); +} From 43d4b70417bb24f08584902e2f91e4eb0c703768 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 21:32:59 -0700 Subject: [PATCH 145/545] track_caller feature gate starts in 1.40.0. Co-Authored-By: Mazdak Farrokhzad --- src/libsyntax/feature_gate/active.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index c90b18fc3976..6c0d76de751b 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -526,7 +526,7 @@ declare_features! ( (active, raw_dylib, "1.40.0", Some(58713), None), /// Enable accurate caller location reporting during panic (RFC 2091). - (active, track_caller, "1.39.0", Some(47809), None), + (active, track_caller, "1.40.0", Some(47809), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates From d931afe47061cb27dfdb44727b0a6707868ea326 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 22:09:18 -0700 Subject: [PATCH 146/545] Mark #![feature(track_caller)] as incomplete. --- src/libsyntax/feature_gate/active.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libsyntax/feature_gate/active.rs b/src/libsyntax/feature_gate/active.rs index 6c0d76de751b..94f0995566f5 100644 --- a/src/libsyntax/feature_gate/active.rs +++ b/src/libsyntax/feature_gate/active.rs @@ -543,4 +543,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::or_patterns, sym::let_chains, sym::raw_dylib, + sym::track_caller, ]; From 9900211ea07a419289037b77eda218030dc32db3 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 22:35:58 -0700 Subject: [PATCH 147/545] track_caller error numbers and text. --- src/librustc/error_codes.rs | 20 +++++++++---------- src/librustc/hir/check_attr.rs | 4 ++-- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- src/librustc_typeck/error_codes.rs | 16 +++++++++------ .../error-with-invalid-abi.stderr | 4 ++-- .../error-with-naked.stderr | 4 ++-- .../error-with-trait-fns.stderr | 4 ++-- .../rfc-2091-track-caller/only-for-fns.stderr | 4 ++-- 9 files changed, 32 insertions(+), 28 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index b2671e48be68..6be1b6a54fb3 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1640,16 +1640,6 @@ each method; it is not possible to annotate the entire impl with an `#[inline]` attribute. "##, -E0900: r##" -FIXME(anp): change error number -FIXME(anp): track_caller: invalid syntax -"##, - -E0901: r##" -FIXME(anp): change error number -FIXME(anp): track_caller: no naked functions -"##, - E0522: r##" The lang attribute is intended for marking special items that are built-in to Rust itself. This includes special traits (like `Copy` and `Sized`) that affect @@ -2085,6 +2075,15 @@ These attributes are meant to only be used by the standard library and are rejected in your own crates. "##, +E0736: r##" +#[track_caller] and #[naked] cannot be applied to the same function. + +This is primarily due to ABI incompatibilities between the two attributes. +See [RFC 2091] for details on this and other limitations. + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md +"##, + ; // E0006, // merged with E0005 // E0101, // replaced with E0282 @@ -2146,4 +2145,5 @@ rejected in your own crates. E0726, // non-explicit (not `'_`) elided lifetime in unsupported position E0727, // `async` generators are not yet supported E0728, // `await` must be in an `async` function or block + E0735, // invalid track_caller application/syntax } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 66415e26281b..35c7ffbf14ef 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -143,7 +143,7 @@ impl CheckAttrVisitor<'tcx> { struct_span_err!( self.tcx.sess, attr.span, - E0900, + E0735, "attribute should be applied to function" ) .span_label(item.span, "not a function") @@ -153,7 +153,7 @@ impl CheckAttrVisitor<'tcx> { struct_span_err!( self.tcx.sess, attr.span, - E0901, + E0736, "cannot use `#[track_caller]` with `#[naked]`", ) .emit(); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 3c9010de5cb7..b8d1da2bbed8 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -179,7 +179,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) { struct_span_err!( tcx.sess, attr.span, - E0903, + E0738, "`#[track_caller]` is not supported for trait items yet." ).emit(); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0b98e4b781d7..7f34aa354c9e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2599,7 +2599,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { struct_span_err!( tcx.sess, attr.span, - E0902, + E0737, "rust ABI is required to use `#[track_caller]`" ).emit(); } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 1ebae19c7d90..be1e34661fd1 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4908,14 +4908,18 @@ The `Box<...>` ensures that the result is of known size, and the pin is required to keep it in the same place in memory. "##, -E0902: r##" -FIXME(anp): change error number -FIXME(anp): track_caller: require Rust ABI to use track_caller +E0737: r##" +#[track_caller] requires functions to have the "Rust" ABI for passing caller +location. See [RFC 2091] for details on this and other restrictions. + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, -E0903: r##" -FIXME(anp): change error number -FIXME(anp): track_caller: can't apply in traits +E0738: r##" +#[track_caller] cannot be applied to trait methods. See [RFC 2091] +for details on this and other restrictions. + +[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/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr index fc6f4d17dcc4..e39e4bee5cf9 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr @@ -1,4 +1,4 @@ -error[E0902]: rust ABI is required to use `#[track_caller]` +error[E0737]: rust ABI is required to use `#[track_caller]` --> $DIR/error-with-invalid-abi.rs:3:1 | LL | #[track_caller] @@ -6,4 +6,4 @@ LL | #[track_caller] error: aborting due to previous error -For more information about this error, try `rustc --explain E0902`. +For more information about this error, try `rustc --explain E0737`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr index 3566d288ed10..2f5003cfdb7a 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -1,4 +1,4 @@ -error[E0901]: cannot use `#[track_caller]` with `#[naked]` +error[E0736]: cannot use `#[track_caller]` with `#[naked]` --> $DIR/error-with-naked.rs:3:1 | LL | #[track_caller] @@ -6,4 +6,4 @@ LL | #[track_caller] error: aborting due to previous error -For more information about this error, try `rustc --explain E0901`. +For more information about this error, try `rustc --explain E0736`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr index bd3d4043a642..e3f3135cd736 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr @@ -1,4 +1,4 @@ -error[E0903]: `#[track_caller]` is not supported for trait items yet. +error[E0738]: `#[track_caller]` is not supported for trait items yet. --> $DIR/error-with-trait-fns.rs:4:5 | LL | #[track_caller] @@ -6,4 +6,4 @@ LL | #[track_caller] error: aborting due to previous error -For more information about this error, try `rustc --explain E0903`. +For more information about this error, try `rustc --explain E0738`. 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 9ddc99c02bf9..ac5ba0bfbaac 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 @@ -1,4 +1,4 @@ -error[E0900]: attribute should be applied to function +error[E0735]: attribute should be applied to function --> $DIR/only-for-fns.rs:3:1 | LL | #[track_caller] @@ -8,4 +8,4 @@ LL | struct S; error: aborting due to previous error -For more information about this error, try `rustc --explain E0900`. +For more information about this error, try `rustc --explain E0735`. From 53096c575d0e17449e3b86919b96aa0e66ca9c48 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 2 Oct 2019 23:01:52 -0700 Subject: [PATCH 148/545] track_caller tests account for incomplete feature warning. --- src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs | 2 +- .../ui/rfc-2091-track-caller/error-odd-syntax.stderr | 8 ++++++++ .../ui/rfc-2091-track-caller/error-with-invalid-abi.rs | 2 +- .../rfc-2091-track-caller/error-with-invalid-abi.stderr | 8 ++++++++ src/test/ui/rfc-2091-track-caller/error-with-naked.rs | 2 +- .../ui/rfc-2091-track-caller/error-with-naked.stderr | 8 ++++++++ .../ui/rfc-2091-track-caller/error-with-trait-fns.rs | 2 +- .../ui/rfc-2091-track-caller/error-with-trait-fns.stderr | 8 ++++++++ src/test/ui/rfc-2091-track-caller/only-for-fns.rs | 2 +- src/test/ui/rfc-2091-track-caller/only-for-fns.stderr | 9 ++++++++- src/test/ui/rfc-2091-track-caller/pass.rs | 2 +- src/test/ui/rfc-2091-track-caller/pass.stderr | 8 ++++++++ 12 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/rfc-2091-track-caller/pass.stderr diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs index d6560231871c..d400db8575e0 100644 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.rs @@ -1,4 +1,4 @@ -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller(1)] fn f() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr index 8906fa59506a..a53a8ee2bedc 100644 --- a/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-odd-syntax.stderr @@ -4,5 +4,13 @@ error: malformed `track_caller` attribute input LL | #[track_caller(1)] | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[track_caller]` +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-odd-syntax.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error: aborting due to previous error diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs index 5c42a1b3faa2..2994f3c06212 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.rs @@ -1,4 +1,4 @@ -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller] extern "C" fn f() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr index e39e4bee5cf9..a34acf3fc614 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-invalid-abi.stderr @@ -1,3 +1,11 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-invalid-abi.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error[E0737]: rust ABI is required to use `#[track_caller]` --> $DIR/error-with-invalid-abi.rs:3:1 | diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs index dd9e5d041358..bbbcec30e8d5 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.rs @@ -1,4 +1,4 @@ -#![feature(naked_functions, track_caller)] +#![feature(naked_functions, track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller] #[naked] diff --git a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr index 2f5003cfdb7a..93e6f7a4cd32 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-naked.stderr @@ -1,3 +1,11 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-naked.rs:1:29 + | +LL | #![feature(naked_functions, track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error[E0736]: cannot use `#[track_caller]` with `#[naked]` --> $DIR/error-with-naked.rs:3:1 | diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs index c00cf7367ce5..e42568076b9d 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs @@ -1,4 +1,4 @@ -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete trait Trait { #[track_caller] diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr index e3f3135cd736..c5c2f136a3a8 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr @@ -1,3 +1,11 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-trait-fns.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error[E0738]: `#[track_caller]` is not supported for trait items yet. --> $DIR/error-with-trait-fns.rs:4:5 | diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs index 0fd59b4bf491..01ebf13b521b 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.rs +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.rs @@ -1,4 +1,4 @@ -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller] struct S; 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 ac5ba0bfbaac..e2d3d57f0adf 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 @@ -1,3 +1,11 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/only-for-fns.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error[E0735]: attribute should be applied to function --> $DIR/only-for-fns.rs:3:1 | @@ -8,4 +16,3 @@ LL | struct S; error: aborting due to previous error -For more information about this error, try `rustc --explain E0735`. diff --git a/src/test/ui/rfc-2091-track-caller/pass.rs b/src/test/ui/rfc-2091-track-caller/pass.rs index eef83b3d68f9..f2c3f0dc59e0 100644 --- a/src/test/ui/rfc-2091-track-caller/pass.rs +++ b/src/test/ui/rfc-2091-track-caller/pass.rs @@ -1,5 +1,5 @@ // run-pass -#![feature(track_caller)] +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete #[track_caller] fn f() {} diff --git a/src/test/ui/rfc-2091-track-caller/pass.stderr b/src/test/ui/rfc-2091-track-caller/pass.stderr new file mode 100644 index 000000000000..b1fd23a6a9dd --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/pass.stderr @@ -0,0 +1,8 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/pass.rs:2:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + From 8992c30db41ceda8eb07c36080f2f1926013c2ac Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 3 Oct 2019 18:49:35 -0700 Subject: [PATCH 149/545] E0735 -> E0739 Prevents number collision with another approved PR. --- src/librustc/error_codes.rs | 2 +- src/librustc/hir/check_attr.rs | 2 +- src/test/ui/rfc-2091-track-caller/only-for-fns.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 6be1b6a54fb3..8bc472aa0284 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2145,5 +2145,5 @@ See [RFC 2091] for details on this and other limitations. E0726, // non-explicit (not `'_`) elided lifetime in unsupported position E0727, // `async` generators are not yet supported E0728, // `await` must be in an `async` function or block - E0735, // invalid track_caller application/syntax + E0739, // invalid track_caller application/syntax } diff --git a/src/librustc/hir/check_attr.rs b/src/librustc/hir/check_attr.rs index 35c7ffbf14ef..c37fec982b11 100644 --- a/src/librustc/hir/check_attr.rs +++ b/src/librustc/hir/check_attr.rs @@ -143,7 +143,7 @@ impl CheckAttrVisitor<'tcx> { struct_span_err!( self.tcx.sess, attr.span, - E0735, + E0739, "attribute should be applied to function" ) .span_label(item.span, "not a function") 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 e2d3d57f0adf..3301da7ff47b 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 @@ -6,7 +6,7 @@ LL | #![feature(track_caller)] | = note: `#[warn(incomplete_features)]` on by default -error[E0735]: attribute should be applied to function +error[E0739]: attribute should be applied to function --> $DIR/only-for-fns.rs:3:1 | LL | #[track_caller] From bdc4bd142b3a452d5e7456cf30e9fc67106ec01b Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Fri, 4 Oct 2019 14:19:05 -0700 Subject: [PATCH 150/545] E073[6-8] include failing code examples. --- src/librustc/error_codes.rs | 10 ++++++++ src/librustc_typeck/error_codes.rs | 37 ++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 8bc472aa0284..e3ef58a0f81f 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2078,6 +2078,16 @@ rejected in your own crates. E0736: r##" #[track_caller] and #[naked] cannot be applied to the same function. +Erroneous code example: + +```compile_fail,E0736 +#![feature(track_caller)] + +#[naked] +#[track_caller] +fn foo() {} +``` + This is primarily due to ABI incompatibilities between the two attributes. See [RFC 2091] for details on this and other limitations. diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index be1e34661fd1..1fb5b5926163 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4909,15 +4909,44 @@ and the pin is required to keep it in the same place in memory. "##, E0737: r##" -#[track_caller] requires functions to have the "Rust" ABI for passing caller -location. See [RFC 2091] for details on this and other restrictions. +#[track_caller] requires functions to have the "Rust" ABI for implicitly +receiving caller location. See [RFC 2091] for details on this and other +restrictions. + +Erroneous code example: + +```compile_fail,E0737 +#![feature(track_caller)] + +#[track_caller] +extern "C" fn foo() {} +``` [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, E0738: r##" -#[track_caller] cannot be applied to trait methods. See [RFC 2091] -for details on this and other restrictions. +#[track_caller] cannot be applied to trait methods. + +This is due to limitations in the compiler which are likely to be temporary. +See [RFC 2091] for details on this and other restrictions. + +Erroneous code example: + +```compile_fail,E0738 +#![feature(track_caller)] + +trait Foo { + fn bar(&self); +} + +struct Bar; + +impl Foo for Bar { + #[track_caller] + fn bar(&self) {} +} +``` [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, From 130be6d4b8015b32a3e68678dd75459b2a3de3ab Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Fri, 4 Oct 2019 15:55:39 -0700 Subject: [PATCH 151/545] Expand E0738 to cover different cases. --- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/error_codes.rs | 41 +++++++++++++++---- ...-trait-fns.rs => error-with-trait-decl.rs} | 2 +- .../error-with-trait-decl.stderr | 17 ++++++++ .../error-with-trait-default-impl.rs | 9 ++++ .../error-with-trait-default-impl.stderr | 17 ++++++++ .../error-with-trait-fn-impl.rs | 13 ++++++ ...stderr => error-with-trait-fn-impl.stderr} | 6 +-- 8 files changed, 94 insertions(+), 13 deletions(-) rename src/test/ui/rfc-2091-track-caller/{error-with-trait-fns.rs => error-with-trait-decl.rs} (72%) create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr create mode 100644 src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs rename src/test/ui/rfc-2091-track-caller/{error-with-trait-fns.stderr => error-with-trait-fn-impl.stderr} (71%) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b8d1da2bbed8..4f9c686bd39c 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -180,7 +180,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) { tcx.sess, attr.span, E0738, - "`#[track_caller]` is not supported for trait items yet." + "`#[track_caller]` is not supported in trait declarations." ).emit(); } } diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 1fb5b5926163..026aff7a9646 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4926,12 +4926,11 @@ extern "C" fn foo() {} "##, E0738: r##" -#[track_caller] cannot be applied to trait methods. +#[track_caller] cannot be used in traits yet. This is due to limitations in the +compiler which are likely to be temporary. See [RFC 2091] for details on this +and other restrictions. -This is due to limitations in the compiler which are likely to be temporary. -See [RFC 2091] for details on this and other restrictions. - -Erroneous code example: +Erroneous example with a trait method implementation: ```compile_fail,E0738 #![feature(track_caller)] @@ -4940,14 +4939,40 @@ trait Foo { fn bar(&self); } -struct Bar; - -impl Foo for Bar { +impl Foo for u64 { #[track_caller] fn bar(&self) {} } ``` +Erroneous example with a blanket trait method implementation: + +```compile_fail,E0738 +#![feature(track_caller)] + +trait Foo { + #[track_caller] + fn bar(&self) {} + fn baz(&self); +} +``` + +Erroneous example with a trait method declaration: + +```compile_fail,E0738 +#[!feature(track_caller)] + +trait Foo { + fn bar(&self) {} + + #[track_caller] + fn baz(&self); +} +``` + +Note that while the compiler may be able to support the attribute in traits in +the future, [RFC 2091] prohibits their implementation without a follow-up RFC. + [RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md "##, diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs similarity index 72% rename from src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs rename to src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs index e42568076b9d..72f690777da2 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs @@ -3,7 +3,7 @@ trait Trait { #[track_caller] fn unwrap(&self); - //~^^ ERROR: `#[track_caller]` is not supported for trait items yet. + //~^^ ERROR: `#[track_caller]` is not supported in traits yet. } impl Trait for u64 { diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr new file mode 100644 index 000000000000..fb3732b59708 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.stderr @@ -0,0 +1,17 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-trait-decl.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0738]: `#[track_caller]` is not supported in trait declarations. + --> $DIR/error-with-trait-decl.rs:4:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs new file mode 100644 index 000000000000..0f2020d6fb26 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.rs @@ -0,0 +1,9 @@ +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete + +trait Trait { + #[track_caller] + fn unwrap(&self) {} + //~^^ ERROR: `#[track_caller]` is not supported in trait declarations. +} + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr new file mode 100644 index 000000000000..f7faeba189b5 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr @@ -0,0 +1,17 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/error-with-trait-default-impl.rs:1:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0738]: `#[track_caller]` is not supported in traits yet. + --> $DIR/error-with-trait-default-impl.rs:4:5 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0738`. diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs new file mode 100644 index 000000000000..1378ebaa03ff --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.rs @@ -0,0 +1,13 @@ +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete + +trait Trait { + fn unwrap(&self); +} + +impl Trait for u64 { + #[track_caller] + fn unwrap(&self) {} + //~^^ ERROR: `#[track_caller]` is not supported in traits yet. +} + +fn main() {} diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr similarity index 71% rename from src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr rename to src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr index c5c2f136a3a8..1e6c2eeca473 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr @@ -1,13 +1,13 @@ warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/error-with-trait-fns.rs:1:12 + --> $DIR/error-with-trait-fn-impl.rs:1:12 | LL | #![feature(track_caller)] | ^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default -error[E0738]: `#[track_caller]` is not supported for trait items yet. - --> $DIR/error-with-trait-fns.rs:4:5 +error[E0738]: `#[track_caller]` is not supported in traits yet. + --> $DIR/error-with-trait-fn-impl.rs:4:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ From f70ed29fbd2b58dd1ebfcff878134fd3876a0dea Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 5 Oct 2019 08:12:48 -0700 Subject: [PATCH 152/545] Update expected error output. --- src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs | 2 +- .../rfc-2091-track-caller/error-with-trait-default-impl.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs index 72f690777da2..1cd45c8cdbc9 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-decl.rs @@ -3,7 +3,7 @@ trait Trait { #[track_caller] fn unwrap(&self); - //~^^ ERROR: `#[track_caller]` is not supported in traits yet. + //~^^ ERROR: `#[track_caller]` is not supported in trait declarations. } impl Trait for u64 { diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr index f7faeba189b5..c212a716c202 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-default-impl.stderr @@ -6,7 +6,7 @@ LL | #![feature(track_caller)] | = note: `#[warn(incomplete_features)]` on by default -error[E0738]: `#[track_caller]` is not supported in traits yet. +error[E0738]: `#[track_caller]` is not supported in trait declarations. --> $DIR/error-with-trait-default-impl.rs:4:5 | LL | #[track_caller] From 190212c6bf1588fb4349a16caa9c2796f9a795f4 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 5 Oct 2019 08:21:30 -0700 Subject: [PATCH 153/545] Prohibit #[track_caller] within trait impls as well as decls. --- src/librustc_typeck/check/wfcheck.rs | 27 ++++++++++++++++++- .../error-with-trait-fn-impl.stderr | 2 +- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 4f9c686bd39c..051bd671d445 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) { }; check_associated_item(tcx, trait_item.hir_id, trait_item.span, method_sig); - // Prohibits applying `#[track_caller]` to trait methods + // Prohibits applying `#[track_caller]` to trait decls for attr in &trait_item.attrs { if attr.check_name(sym::track_caller) { struct_span_err!( @@ -194,6 +194,31 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { hir::ImplItemKind::Method(ref sig, _) => Some(sig), _ => None }; + + // Prohibits applying `#[track_caller]` to trait impls + if method_sig.is_some() { + let track_caller_attr = impl_item.attrs.iter() + .find(|a| a.check_name(sym::track_caller)); + if let Some(tc_attr) = track_caller_attr { + let parent_hir_id = tcx.hir().get_parent_item(hir_id); + let containing_item = tcx.hir().expect_item(parent_hir_id); + let containing_impl_trait_ref = match &containing_item.kind { + hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr, + _ => bug!("parent of an ImplItem must be an Impl"), + }; + + // if the impl block this item is within is for a trait... + if containing_impl_trait_ref.is_some() { + struct_span_err!( + tcx.sess, + tc_attr.span, + E0738, + "`#[track_caller]` is not supported in traits yet." + ).emit(); + } + } + } + check_associated_item(tcx, impl_item.hir_id, impl_item.span, method_sig); } diff --git a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr index 1e6c2eeca473..2662fbff7a2c 100644 --- a/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr +++ b/src/test/ui/rfc-2091-track-caller/error-with-trait-fn-impl.stderr @@ -7,7 +7,7 @@ LL | #![feature(track_caller)] = note: `#[warn(incomplete_features)]` on by default error[E0738]: `#[track_caller]` is not supported in traits yet. - --> $DIR/error-with-trait-fn-impl.rs:4:5 + --> $DIR/error-with-trait-fn-impl.rs:8:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ From c49966bb1bc66cb14d66e2c116d187e781ee6776 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 5 Oct 2019 08:28:38 -0700 Subject: [PATCH 154/545] Clarify variable names when checking track_caller methods. --- src/librustc_typeck/check/wfcheck.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 051bd671d445..fa283904fe47 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -196,19 +196,18 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { }; // Prohibits applying `#[track_caller]` to trait impls - if method_sig.is_some() { + if method_sig.is_some() { let track_caller_attr = impl_item.attrs.iter() .find(|a| a.check_name(sym::track_caller)); if let Some(tc_attr) = track_caller_attr { let parent_hir_id = tcx.hir().get_parent_item(hir_id); let containing_item = tcx.hir().expect_item(parent_hir_id); - let containing_impl_trait_ref = match &containing_item.kind { - hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr, + let containing_impl_is_for_trait = match &containing_item.kind { + hir::ItemKind::Impl(_, _, _, _, tr, _, _) => tr.is_some(), _ => bug!("parent of an ImplItem must be an Impl"), }; - // if the impl block this item is within is for a trait... - if containing_impl_trait_ref.is_some() { + if containing_impl_is_for_trait { struct_span_err!( tcx.sess, tc_attr.span, From cca58d1321b6de3098884d4af7bbff57f0f65101 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Mon, 7 Oct 2019 08:04:26 -0700 Subject: [PATCH 155/545] Fix syntax typo in error message. --- src/librustc_typeck/error_codes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/error_codes.rs b/src/librustc_typeck/error_codes.rs index 026aff7a9646..0736d69a731e 100644 --- a/src/librustc_typeck/error_codes.rs +++ b/src/librustc_typeck/error_codes.rs @@ -4960,7 +4960,7 @@ trait Foo { Erroneous example with a trait method declaration: ```compile_fail,E0738 -#[!feature(track_caller)] +#![feature(track_caller)] trait Foo { fn bar(&self) {} From 28b0e1db5047bd9fe6bcae1caa5eaffe721b2b48 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Sep 2019 14:32:50 +0200 Subject: [PATCH 156/545] Add long error explanation for E0495 --- src/librustc/error_codes.rs | 43 +++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 502172db91c9..4cee132ecaed 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -1520,6 +1520,47 @@ where ``` "##, +E0495: r##" +A lifetime cannot be determined in the given situation. + +Erroneous code example: + +```compile_fail,E0495 +fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { + match (&t,) { // error! + ((u,),) => u, + } +} + +let y = Box::new((42,)); +let x = transmute_lifetime(&y); +``` + +In this code, you have two ways to solve this issue: + 1. Enforce that `'a` lives at least as long as `'b`. + 2. Use the same lifetime requirement for both input and output values. + +So for the first solution, you can do it by replacing `'a` with `'a: 'b`: + +``` +fn transmute_lifetime<'a: 'b, 'b, T>(t: &'a (T,)) -> &'b T { + match (&t,) { // ok! + ((u,),) => u, + } +} +``` + +In the second you can do it by simply removing `'b` so they both use `'a`: + +``` +fn transmute_lifetime<'a, T>(t: &'a (T,)) -> &'a T { + match (&t,) { // ok! + ((u,),) => u, + } +} +``` +"##, + E0496: r##" A lifetime name is shadowing another lifetime name. Erroneous code example: @@ -2116,8 +2157,6 @@ rejected in your own crates. E0488, // lifetime of variable does not enclose its declaration E0489, // type/lifetime parameter not in scope here E0490, // a value of type `..` is borrowed for too long - E0495, // cannot infer an appropriate lifetime due to conflicting - // requirements E0623, // lifetime mismatch where both parameters are anonymous regions E0628, // generators cannot have explicit parameters E0631, // type mismatch in closure arguments From 96efaad342a4db24c1ae6db526a563cf28c7c499 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 12 Sep 2019 15:00:44 +0200 Subject: [PATCH 157/545] update ui tests --- .../cache/project-fn-ret-contravariant.transmute.stderr | 1 + .../cache/project-fn-ret-invariant.transmute.stderr | 1 + src/test/ui/c-variadic/variadic-ffi-4.stderr | 3 ++- .../ui/error-codes/E0621-does-not-trigger-for-closures.stderr | 1 + src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr | 1 + src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr | 1 + src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr | 1 + src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr | 1 + src/test/ui/issues/issue-16683.stderr | 1 + src/test/ui/issues/issue-17758.stderr | 1 + src/test/ui/issues/issue-20831-debruijn.stderr | 3 ++- src/test/ui/issues/issue-52213.stderr | 1 + src/test/ui/issues/issue-55796.stderr | 1 + src/test/ui/nll/issue-55394.stderr | 1 + src/test/ui/nll/normalization-bounds-error.stderr | 1 + src/test/ui/nll/type-alias-free-regions.stderr | 1 + .../ui/nll/user-annotations/constant-in-expr-inherent-1.stderr | 1 + .../nll/user-annotations/constant-in-expr-trait-item-3.stderr | 1 + .../ui/object-lifetime/object-lifetime-default-elision.stderr | 1 + src/test/ui/regions/region-object-lifetime-2.stderr | 1 + src/test/ui/regions/region-object-lifetime-4.stderr | 1 + src/test/ui/regions/region-object-lifetime-in-coercion.stderr | 3 ++- src/test/ui/regions/regions-addr-of-self.stderr | 1 + src/test/ui/regions/regions-addr-of-upvar-self.stderr | 1 + .../regions-assoc-type-region-bound-in-trait-not-met.stderr | 1 + .../regions-assoc-type-static-bound-in-trait-not-met.stderr | 1 + src/test/ui/regions/regions-close-object-into-object-2.stderr | 1 + src/test/ui/regions/regions-close-object-into-object-4.stderr | 1 + .../regions/regions-close-over-type-parameter-multiple.stderr | 1 + src/test/ui/regions/regions-creating-enums4.stderr | 1 + src/test/ui/regions/regions-escape-method.stderr | 1 + src/test/ui/regions/regions-escape-via-trait-or-not.stderr | 1 + .../ui/regions/regions-free-region-ordering-incorrect.stderr | 1 + src/test/ui/regions/regions-infer-call-3.stderr | 1 + src/test/ui/regions/regions-nested-fns.stderr | 3 ++- .../ui/regions/regions-normalize-in-where-clause-list.stderr | 1 + src/test/ui/regions/regions-ret-borrowed-1.stderr | 1 + src/test/ui/regions/regions-ret-borrowed.stderr | 1 + .../ui/regions/regions-return-ref-to-upvar-issue-17403.stderr | 1 + src/test/ui/regions/regions-trait-object-subtyping.stderr | 2 +- src/test/ui/reject-specialized-drops-8142.stderr | 2 +- ...ait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr | 1 + src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr | 1 + src/test/ui/wf/wf-static-method.stderr | 2 +- 44 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr index 15bebce47dd6..4309373f123f 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr @@ -23,3 +23,4 @@ LL | bar(foo, x) error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index 62b4cb10911f..b8b1a979c363 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -19,3 +19,4 @@ LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr index b986d0c24350..3d552f88ba66 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr @@ -209,4 +209,5 @@ LL | | } error: aborting due to 8 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0495. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr index f50c64780118..feca7f10b706 100644 --- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr +++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.stderr @@ -27,3 +27,4 @@ LL | invoke(&x, |a, b| if a > b { a } else { b }); error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr index eb824def2468..af120fa977ca 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr @@ -19,3 +19,4 @@ LL | fn with_dyn_debug_static<'a>(x: Box) { error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr index b50a926c6379..c1ec536ef436 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr @@ -18,3 +18,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr index cd65bab2d466..a80ebaf8dd29 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr @@ -22,3 +22,4 @@ LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index 80f15b7c5847..4dee83d6eefe 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -32,3 +32,4 @@ LL | x error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-16683.stderr b/src/test/ui/issues/issue-16683.stderr index 771a2ddf240f..a047893a168a 100644 --- a/src/test/ui/issues/issue-16683.stderr +++ b/src/test/ui/issues/issue-16683.stderr @@ -27,3 +27,4 @@ LL | trait T<'a> { error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-17758.stderr b/src/test/ui/issues/issue-17758.stderr index 0ef3b98719d3..28a1be59840a 100644 --- a/src/test/ui/issues/issue-17758.stderr +++ b/src/test/ui/issues/issue-17758.stderr @@ -28,3 +28,4 @@ LL | trait Foo<'a> { error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index 64e3cdc64c11..dd895985c143 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -94,4 +94,5 @@ LL | impl<'a> Publisher<'a> for MyStruct<'a> { error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0495. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-52213.stderr b/src/test/ui/issues/issue-52213.stderr index b4df10efc5d8..8d74b8ecb881 100644 --- a/src/test/ui/issues/issue-52213.stderr +++ b/src/test/ui/issues/issue-52213.stderr @@ -25,3 +25,4 @@ LL | ((u,),) => u, error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr index 9e67e5e125f6..7cf597d3a98f 100644 --- a/src/test/ui/issues/issue-55796.stderr +++ b/src/test/ui/issues/issue-55796.stderr @@ -42,3 +42,4 @@ LL | Box::new(self.in_edges(u).map(|e| e.target())) error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr index ffb94ed7dd7c..e00e6f36f1af 100644 --- a/src/test/ui/nll/issue-55394.stderr +++ b/src/test/ui/nll/issue-55394.stderr @@ -27,3 +27,4 @@ LL | impl Foo<'_> { error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr index 951e73e7fd76..77a372d9cf55 100644 --- a/src/test/ui/nll/normalization-bounds-error.stderr +++ b/src/test/ui/nll/normalization-bounds-error.stderr @@ -20,3 +20,4 @@ LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr index 00d58d34362e..746517417520 100644 --- a/src/test/ui/nll/type-alias-free-regions.stderr +++ b/src/test/ui/nll/type-alias-free-regions.stderr @@ -50,3 +50,4 @@ LL | impl<'a> FromTuple<'a> for C<'a> { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr index 77e1339dc161..f5657f9e4ead 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr @@ -21,3 +21,4 @@ LL | >::C error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr index 77655fe091b6..f7db4038b8af 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr @@ -21,3 +21,4 @@ LL | T::C error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr index 2cdd6c5d890f..217e8504aa3c 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -50,3 +50,4 @@ LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/region-object-lifetime-2.stderr b/src/test/ui/regions/region-object-lifetime-2.stderr index 0c5e22ebae28..cc8d150d04cc 100644 --- a/src/test/ui/regions/region-object-lifetime-2.stderr +++ b/src/test/ui/regions/region-object-lifetime-2.stderr @@ -27,3 +27,4 @@ LL | x.borrowed() error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/region-object-lifetime-4.stderr b/src/test/ui/regions/region-object-lifetime-4.stderr index e737d27d5606..23fd4d03628d 100644 --- a/src/test/ui/regions/region-object-lifetime-4.stderr +++ b/src/test/ui/regions/region-object-lifetime-4.stderr @@ -27,3 +27,4 @@ LL | x.borrowed() error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 8209fa1840d0..3ccb8866ca44 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -48,4 +48,5 @@ LL | fn d<'a,'b>(v: &'a [u8]) -> Box { error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0621`. +Some errors have detailed explanations: E0495, E0621. +For more information about an error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-addr-of-self.stderr b/src/test/ui/regions/regions-addr-of-self.stderr index 2274e9341dbc..a0b8b6b51e5a 100644 --- a/src/test/ui/regions/regions-addr-of-self.stderr +++ b/src/test/ui/regions/regions-addr-of-self.stderr @@ -26,3 +26,4 @@ LL | let p: &'static mut usize = &mut self.cats_chased; error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.stderr index d02caeb44f1a..ac5e5e9aabc5 100644 --- a/src/test/ui/regions/regions-addr-of-upvar-self.stderr +++ b/src/test/ui/regions/regions-addr-of-upvar-self.stderr @@ -23,3 +23,4 @@ LL | let p: &'static mut usize = &mut self.food; error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr index 9732cd12ce15..d01e99110392 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr @@ -46,3 +46,4 @@ LL | impl<'a,'b> Foo<'b> for &'a i64 { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr index 2067bc3946c9..33a4ea01ce2e 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr @@ -21,3 +21,4 @@ LL | impl<'a> Foo for &'a i32 { error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index fa203debb3a1..7af608d2c801 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -21,3 +21,4 @@ LL | box B(&*v) as Box error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index f5e66f84a9ee..ef47db18d392 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -21,3 +21,4 @@ LL | box B(&*v) as Box error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr index 8b3dbc8b6490..6f7466a8b0ed 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr @@ -25,3 +25,4 @@ LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-escape-method.stderr b/src/test/ui/regions/regions-escape-method.stderr index d867448e1372..b93dd0d4c57c 100644 --- a/src/test/ui/regions/regions-escape-method.stderr +++ b/src/test/ui/regions/regions-escape-method.stderr @@ -25,3 +25,4 @@ LL | s.f(|p| p) error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr index c8a02683d100..a6b165e2d444 100644 --- a/src/test/ui/regions/regions-escape-via-trait-or-not.stderr +++ b/src/test/ui/regions/regions-escape-via-trait-or-not.stderr @@ -25,3 +25,4 @@ LL | with(|o| o) error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr index 5fad6de2a62a..676e96a038b4 100644 --- a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr @@ -30,3 +30,4 @@ LL | | } error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-infer-call-3.stderr b/src/test/ui/regions/regions-infer-call-3.stderr index 151c8307a14f..1d6dbdb2c7b5 100644 --- a/src/test/ui/regions/regions-infer-call-3.stderr +++ b/src/test/ui/regions/regions-infer-call-3.stderr @@ -27,3 +27,4 @@ LL | let z = with(|y| { select(x, y) }); error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr index 904dee6998c9..bc3c06d7ff3b 100644 --- a/src/test/ui/regions/regions-nested-fns.stderr +++ b/src/test/ui/regions/regions-nested-fns.stderr @@ -57,4 +57,5 @@ LL | fn nested<'x>(x: &'x isize) { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0312`. +Some errors have detailed explanations: E0312, E0495. +For more information about an error, try `rustc --explain E0312`. diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr index 912e11831627..c44edf1f03bc 100644 --- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr +++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -23,3 +23,4 @@ LL | fn bar<'a, 'b>() error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr index 403af2a9e6a4..72e47cea094c 100644 --- a/src/test/ui/regions/regions-ret-borrowed-1.stderr +++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr @@ -25,3 +25,4 @@ LL | with(|o| o) error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr index 5d1f26da6c78..ce0c429ccb24 100644 --- a/src/test/ui/regions/regions-ret-borrowed.stderr +++ b/src/test/ui/regions/regions-ret-borrowed.stderr @@ -25,3 +25,4 @@ LL | with(|o| o) error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr index 291b8367f7b7..be441bc48082 100644 --- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr +++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr @@ -27,3 +27,4 @@ LL | let y = f(); error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr index 6de92f13840b..d88be05cb87e 100644 --- a/src/test/ui/regions/regions-trait-object-subtyping.stderr +++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr @@ -61,5 +61,5 @@ LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dum error: aborting due to 3 previous errors -Some errors have detailed explanations: E0308, E0478. +Some errors have detailed explanations: E0308, E0478, E0495. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 08aca3bb14c2..16d27c9d961e 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -111,5 +111,5 @@ LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } error: aborting due to 8 previous errors -Some errors have detailed explanations: E0308, E0366, E0367. +Some errors have detailed explanations: E0308, E0366, E0367, E0495. For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr index fb417b82d15c..4c63d6097758 100644 --- a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr +++ b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr @@ -20,3 +20,4 @@ LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 92e5ac282e4d..d0475bf08c38 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -24,3 +24,4 @@ LL | Box::new(items.iter()) error: aborting due to previous error +For more information about this error, try `rustc --explain E0495`. diff --git a/src/test/ui/wf/wf-static-method.stderr b/src/test/ui/wf/wf-static-method.stderr index 3ec90f00448a..da4e8ebf9c05 100644 --- a/src/test/ui/wf/wf-static-method.stderr +++ b/src/test/ui/wf/wf-static-method.stderr @@ -105,5 +105,5 @@ LL | ::static_evil(b) error: aborting due to 5 previous errors -Some errors have detailed explanations: E0312, E0478. +Some errors have detailed explanations: E0312, E0478, E0495. For more information about an error, try `rustc --explain E0312`. From 9c15c66880edea27fc2c621b21822a43dd5bb527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Mon, 7 Oct 2019 20:33:13 +0200 Subject: [PATCH 158/545] Update Cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 8b0561d68f12..a429e8cc4614 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 8b0561d68f12eeb1d72e07ceef464ebf6032a1bc +Subproject commit a429e8cc4614a46a86322a0777a477e2baa83f1c From 45f7186de35f3e944ac8ed21105b924ba30d1aa4 Mon Sep 17 00:00:00 2001 From: BaoshanPang Date: Mon, 7 Oct 2019 11:52:30 -0700 Subject: [PATCH 159/545] use 'invalid argument' for vxWorks --- src/libstd/fs.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 8933f027a065..fc26dcb32114 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -3112,8 +3112,10 @@ mod tests { #[cfg(windows)] let invalid_options = 87; // ERROR_INVALID_PARAMETER - #[cfg(unix)] + #[cfg(all(unix, not(target_os = "vxworks")))] let invalid_options = "Invalid argument"; + #[cfg(target_os = "vxworks")] + let invalid_options = "invalid argument"; // Test various combinations of creation modes and access modes. // From 33c4125fbe6204b4aedeaef281f819aee660b9fc Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 10 Sep 2019 10:13:07 -0700 Subject: [PATCH 160/545] Rebase rustc-rayon on rayon-1.2 See also https://github.com/rust-lang/rustc-rayon/pull/3 --- Cargo.lock | 52 ++++++++++++++++++++----- src/librustc/Cargo.toml | 4 +- src/librustc_data_structures/Cargo.toml | 4 +- src/librustc_interface/Cargo.toml | 2 +- src/librustc_interface/util.rs | 8 ++-- src/librustdoc/Cargo.toml | 2 +- 6 files changed, 53 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0282dc9d6681..35fb4187ab60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -659,6 +659,16 @@ dependencies = [ "crossbeam-utils 0.6.5", ] +[[package]] +name = "crossbeam-deque" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" +dependencies = [ + "crossbeam-epoch 0.7.2", + "crossbeam-utils 0.6.5", +] + [[package]] name = "crossbeam-epoch" version = "0.3.1" @@ -3074,8 +3084,8 @@ dependencies = [ "num_cpus", "parking_lot 0.9.0", "polonius-engine", - "rustc-rayon", - "rustc-rayon-core", + "rustc-rayon 0.3.0", + "rustc-rayon-core 0.3.0", "rustc_apfloat", "rustc_data_structures", "rustc_errors", @@ -3123,8 +3133,8 @@ dependencies = [ "rustc-ap-graphviz", "rustc-ap-serialize", "rustc-hash", - "rustc-rayon", - "rustc-rayon-core", + "rustc-rayon 0.2.0", + "rustc-rayon-core 0.2.0", "smallvec", "stable_deref_trait", ] @@ -3263,7 +3273,18 @@ checksum = "0d2e07e19601f21c59aad953c2632172ba70cb27e685771514ea66e4062b3363" dependencies = [ "crossbeam-deque 0.2.0", "either", - "rustc-rayon-core", + "rustc-rayon-core 0.2.0", +] + +[[package]] +name = "rustc-rayon" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f32767f90d938f1b7199a174ef249ae1924f6e5bbdb9d112fea141e016f25b3a" +dependencies = [ + "crossbeam-deque 0.7.1", + "either", + "rustc-rayon-core 0.3.0", ] [[package]] @@ -3278,6 +3299,19 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "rustc-rayon-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2427831f0053ea3ea73559c8eabd893133a51b251d142bacee53c62a288cb3" +dependencies = [ + "crossbeam-deque 0.7.1", + "crossbeam-queue", + "crossbeam-utils 0.6.5", + "lazy_static 1.3.0", + "num_cpus", +] + [[package]] name = "rustc-serialize" version = "0.3.24" @@ -3398,8 +3432,8 @@ dependencies = [ "log", "parking_lot 0.9.0", "rustc-hash", - "rustc-rayon", - "rustc-rayon-core", + "rustc-rayon 0.3.0", + "rustc-rayon-core 0.3.0", "rustc_index", "serialize", "smallvec", @@ -3479,7 +3513,7 @@ dependencies = [ "log", "once_cell", "rustc", - "rustc-rayon", + "rustc-rayon 0.3.0", "rustc_codegen_ssa", "rustc_codegen_utils", "rustc_data_structures", @@ -3758,7 +3792,7 @@ version = "0.0.0" dependencies = [ "minifier", "pulldown-cmark 0.5.3", - "rustc-rayon", + "rustc-rayon 0.3.0", "tempfile", ] diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index a7c94d057dc4..9b3609eca3e6 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -18,8 +18,8 @@ jobserver = "0.1" num_cpus = "1.0" scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } -rustc-rayon = "0.2.0" -rustc-rayon-core = "0.2.0" +rustc-rayon = "0.3.0" +rustc-rayon-core = "0.3.0" polonius-engine = "0.10.0" rustc_apfloat = { path = "../librustc_apfloat" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index e020f2f8da94..065c8436ae06 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -20,8 +20,8 @@ graphviz = { path = "../libgraphviz" } cfg-if = "0.1.2" crossbeam-utils = { version = "0.6.5", features = ["nightly"] } stable_deref_trait = "1.0.0" -rayon = { version = "0.2.0", package = "rustc-rayon" } -rayon-core = { version = "0.2.0", package = "rustc-rayon-core" } +rayon = { version = "0.3.0", package = "rustc-rayon" } +rayon-core = { version = "0.3.0", package = "rustc-rayon-core" } rustc-hash = "1.0.1" smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } rustc_index = { path = "../librustc_index", package = "rustc_index" } diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index 780f7a7ffa9e..bed5febb72ed 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -11,7 +11,7 @@ doctest = false [dependencies] log = "0.4" -rayon = { version = "0.2.0", package = "rustc-rayon" } +rayon = { version = "0.3.0", package = "rustc-rayon" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index b05bad554f40..35c325c1aa45 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -202,7 +202,7 @@ pub fn spawn_thread_pool R + Send, R: Send>( stderr: &Option>>>, f: F, ) -> R { - use rayon::{ThreadPool, ThreadPoolBuilder}; + use rayon::{ThreadBuilder, ThreadPool, ThreadPoolBuilder}; let gcx_ptr = &Lock::new(0); @@ -225,20 +225,20 @@ pub fn spawn_thread_pool R + Send, R: Send>( // the thread local rustc uses. syntax_globals and syntax_pos_globals are // captured and set on the new threads. ty::tls::with_thread_locals sets up // thread local callbacks from libsyntax - let main_handler = move |worker: &mut dyn FnMut()| { + let main_handler = move |thread: ThreadBuilder| { syntax::GLOBALS.set(syntax_globals, || { syntax_pos::GLOBALS.set(syntax_pos_globals, || { if let Some(stderr) = stderr { io::set_panic(Some(box Sink(stderr.clone()))); } ty::tls::with_thread_locals(|| { - ty::tls::GCX_PTR.set(gcx_ptr, || worker()) + ty::tls::GCX_PTR.set(gcx_ptr, || thread.run()) }) }) }) }; - ThreadPool::scoped_pool(config, main_handler, with_pool).unwrap() + config.build_scoped(main_handler, with_pool).unwrap() }) }) }) diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 0eb8b73016d1..e3de7fe20493 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -11,5 +11,5 @@ path = "lib.rs" [dependencies] pulldown-cmark = { version = "0.5.3", default-features = false } minifier = "0.0.33" -rayon = { version = "0.2.0", package = "rustc-rayon" } +rayon = { version = "0.3.0", package = "rustc-rayon" } tempfile = "3" From fa2acbe0d6ddec9d192df201f21ecc04b523a5ee Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 12 Sep 2019 12:34:43 -0700 Subject: [PATCH 161/545] Name the threads in rayon's pool --- src/librustc_interface/util.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 35c325c1aa45..0c272f0c4563 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -207,6 +207,7 @@ pub fn spawn_thread_pool R + Send, R: Send>( let gcx_ptr = &Lock::new(0); let mut config = ThreadPoolBuilder::new() + .thread_name(|_| "rustc".to_string()) .acquire_thread_handler(jobserver::acquire_thread) .release_thread_handler(jobserver::release_thread) .num_threads(threads) From 98779ed0970606b93b43401709e3b6d7e44177bb Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 7 Oct 2019 13:43:10 -0700 Subject: [PATCH 162/545] add crossbeam-queue to the whitelist --- src/tools/tidy/src/deps.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1ed39f45d3e7..8e46ca6cd299 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -89,6 +89,7 @@ const WHITELIST: &[Crate<'_>] = &[ Crate("crc32fast"), Crate("crossbeam-deque"), Crate("crossbeam-epoch"), + Crate("crossbeam-queue"), Crate("crossbeam-utils"), Crate("datafrog"), Crate("dlmalloc"), From 29cd7eb6c9d9061d10af6207fd77705eeb4d6549 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 7 Oct 2019 13:44:30 -0700 Subject: [PATCH 163/545] Update other rayon uses to 1.2 too --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 35fb4187ab60..2c8aa41df824 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2801,22 +2801,22 @@ dependencies = [ [[package]] name = "rayon" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4b0186e22767d5b9738a05eab7c6ac90b15db17e5b5f9bd87976dd7d89a10a4" +checksum = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" dependencies = [ - "crossbeam-deque 0.6.3", + "crossbeam-deque 0.7.1", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebbe0df8435ac0c397d467b6cad6d25543d06e8a019ef3f6af3c384597515bd2" +checksum = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" dependencies = [ - "crossbeam-deque 0.6.3", + "crossbeam-deque 0.7.1", "crossbeam-queue", "crossbeam-utils 0.6.5", "lazy_static 1.3.0", From faee5fd388a564febc56aa642241f221c0ac1cd1 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 26 Sep 2019 14:44:08 -0700 Subject: [PATCH 164/545] [WIP] minimize the rust-std component --- src/bootstrap/builder.rs | 1 + src/bootstrap/dist.rs | 79 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 5d586f0c461d..afdcabc08302 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -443,6 +443,7 @@ impl<'a> Builder<'a> { dist::Rustc, dist::DebuggerScripts, dist::Std, + dist::StdZ, dist::Analysis, dist::Src, dist::PlainSourceTarball, diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index d9dff77a30e6..ceb7acb83e74 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -675,6 +675,81 @@ impl Step for Std { return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); } + builder.ensure(compile::Std { compiler, target }); + + let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); + let _ = fs::remove_dir_all(&image); + + + let dst = image.join("lib/rustlib").join(target).join("lib"); + t!(fs::create_dir_all(&dst)); + + let stamp = dbg!(compile::libstd_stamp(builder, compiler, target)); + for (path, host) in builder.read_stamp_file(&stamp) { + if !host { + builder.copy(&path, &dst.join(path.file_name().unwrap())); + } + } + + let mut cmd = rust_installer(builder); + cmd.arg("generate") + .arg("--product-name=Rust") + .arg("--rel-manifest-dir=rustlib") + .arg("--success-message=std-is-standing-at-the-ready.") + .arg("--image-dir").arg(&image) + .arg("--work-dir").arg(&tmpdir(builder)) + .arg("--output-dir").arg(&distdir(builder)) + .arg(format!("--package-name={}-{}", name, target)) + .arg(format!("--component-name=rust-std-{}", target)) + .arg("--legacy-manifest-dirs=rustlib,cargo"); + + builder.info(&format!("Dist std stage{} ({} -> {})", + compiler.stage, &compiler.host, target)); + let _time = timeit(builder); + builder.run(&mut cmd); + builder.remove_dir(&image); + distdir(builder).join(format!("{}-{}.tar.gz", name, target)) + } +} + +#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] +pub struct StdZ { + pub compiler: Compiler, + pub target: Interned, +} + +impl Step for StdZ { + type Output = PathBuf; + const DEFAULT: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path("src/libstdZ") + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(StdZ { + compiler: run.builder.compiler_for( + run.builder.top_stage, + run.builder.config.build, + run.target, + ), + target: run.target, + }); + } + + fn run(self, builder: &Builder<'_>) -> PathBuf { + let compiler = self.compiler; + let target = self.target; + + let name = pkgname(builder, "rust-stdZ"); + + // The only true set of target libraries came from the build triple, so + // let's reduce redundant work by only producing archives from that host. + if compiler.host != builder.config.build { + builder.info("\tskipping, not a build host"); + return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); + } + // We want to package up as many target libraries as possible // for the `rust-std` package, so if this is a host target we // depend on librustc and otherwise we just depend on libtest. @@ -710,12 +785,12 @@ impl Step for Std { cmd.arg("generate") .arg("--product-name=Rust") .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=std-is-standing-at-the-ready.") + .arg("--success-message=stdZ-is-standing-at-the-ready.") .arg("--image-dir").arg(&image) .arg("--work-dir").arg(&tmpdir(builder)) .arg("--output-dir").arg(&distdir(builder)) .arg(format!("--package-name={}-{}", name, target)) - .arg(format!("--component-name=rust-std-{}", target)) + .arg(format!("--component-name=rust-stdZ-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); builder.info(&format!("Dist std stage{} ({} -> {})", From dc8ee51c5418ce37b63f1c9bdee98745f5dfe627 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 27 Sep 2019 12:31:00 -0700 Subject: [PATCH 165/545] Use builder.compiler_for() to find the libstd stamp --- src/bootstrap/dist.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index ceb7acb83e74..e1e47d5370a0 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -680,11 +680,11 @@ impl Step for Std { let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); - let dst = image.join("lib/rustlib").join(target).join("lib"); t!(fs::create_dir_all(&dst)); - let stamp = dbg!(compile::libstd_stamp(builder, compiler, target)); + let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); + let stamp = dbg!(compile::libstd_stamp(builder, compiler_to_use, target)); for (path, host) in builder.read_stamp_file(&stamp) { if !host { builder.copy(&path, &dst.join(path.file_name().unwrap())); From 9175f279b583fa71d8b4f6078af319e9a2155b75 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 3 Oct 2019 10:57:19 -0700 Subject: [PATCH 166/545] add dist::RustcDev for unstable compiler libraries --- src/bootstrap/builder.rs | 2 +- src/bootstrap/dist.rs | 102 +++++++++++++++++---------------------- 2 files changed, 46 insertions(+), 58 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index afdcabc08302..bfba39961a22 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -443,7 +443,7 @@ impl<'a> Builder<'a> { dist::Rustc, dist::DebuggerScripts, dist::Std, - dist::StdZ, + dist::RustcDev, dist::Analysis, dist::Src, dist::PlainSourceTarball, diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e1e47d5370a0..e5a43dcb29f6 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -637,6 +637,28 @@ impl Step for DebuggerScripts { } } +fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { + // The only true set of target libraries came from the build triple, so + // let's reduce redundant work by only producing archives from that host. + if compiler.host != builder.config.build { + builder.info("\tskipping, not a build host"); + true + } else { + false + } +} + +/// Copy stamped files into an image's `target/lib` directory. +fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) { + let dst = image.join("lib/rustlib").join(target).join("lib"); + t!(fs::create_dir_all(&dst)); + for (path, host) in builder.read_stamp_file(stamp) { + if !host || builder.config.build == target { + builder.copy(&path, &dst.join(path.file_name().unwrap())); + } + } +} + #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub compiler: Compiler, @@ -667,12 +689,9 @@ impl Step for Std { let target = self.target; let name = pkgname(builder, "rust-std"); - - // The only true set of target libraries came from the build triple, so - // let's reduce redundant work by only producing archives from that host. - if compiler.host != builder.config.build { - builder.info("\tskipping, not a build host"); - return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); + let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); + if skip_host_target_lib(builder, compiler) { + return archive; } builder.ensure(compile::Std { compiler, target }); @@ -680,16 +699,9 @@ impl Step for Std { let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); - let dst = image.join("lib/rustlib").join(target).join("lib"); - t!(fs::create_dir_all(&dst)); - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - let stamp = dbg!(compile::libstd_stamp(builder, compiler_to_use, target)); - for (path, host) in builder.read_stamp_file(&stamp) { - if !host { - builder.copy(&path, &dst.join(path.file_name().unwrap())); - } - } + let stamp = compile::libstd_stamp(builder, compiler_to_use, target); + copy_target_libs(builder, &target, &image, &stamp); let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -708,26 +720,27 @@ impl Step for Std { let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); - distdir(builder).join(format!("{}-{}.tar.gz", name, target)) + archive } } #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] -pub struct StdZ { +pub struct RustcDev { pub compiler: Compiler, pub target: Interned, } -impl Step for StdZ { +impl Step for RustcDev { type Output = PathBuf; const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/libstdZ") + run.path("rustc-dev") } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(StdZ { + run.builder.ensure(RustcDev { compiler: run.builder.compiler_for( run.builder.top_stage, run.builder.config.build, @@ -741,64 +754,39 @@ impl Step for StdZ { let compiler = self.compiler; let target = self.target; - let name = pkgname(builder, "rust-stdZ"); - - // The only true set of target libraries came from the build triple, so - // let's reduce redundant work by only producing archives from that host. - if compiler.host != builder.config.build { - builder.info("\tskipping, not a build host"); - return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); + let name = pkgname(builder, "rustc-dev"); + let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); + if skip_host_target_lib(builder, compiler) { + return archive; } - // We want to package up as many target libraries as possible - // for the `rust-std` package, so if this is a host target we - // depend on librustc and otherwise we just depend on libtest. - if builder.hosts.iter().any(|t| t == target) { - builder.ensure(compile::Rustc { compiler, target }); - } else { - builder.ensure(compile::Std { compiler, target }); - } + builder.ensure(compile::Rustc { compiler, target }); let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); - let dst = image.join("lib/rustlib").join(target); - t!(fs::create_dir_all(&dst)); - let mut src = builder.sysroot_libdir(compiler, target).to_path_buf(); - src.pop(); // Remove the trailing /lib folder from the sysroot_libdir - builder.cp_filtered(&src, &dst, &|path| { - if let Some(name) = path.file_name().and_then(|s| s.to_str()) { - if name == builder.config.rust_codegen_backends_dir.as_str() { - return false - } - if name == "bin" { - return false - } - if name.contains("LLVM") { - return false - } - } - true - }); + let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); + let stamp = compile::librustc_stamp(builder, compiler_to_use, target); + copy_target_libs(builder, &target, &image, &stamp); let mut cmd = rust_installer(builder); cmd.arg("generate") .arg("--product-name=Rust") .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=stdZ-is-standing-at-the-ready.") + .arg("--success-message=Rust-is-ready-to-develop.") .arg("--image-dir").arg(&image) .arg("--work-dir").arg(&tmpdir(builder)) .arg("--output-dir").arg(&distdir(builder)) .arg(format!("--package-name={}-{}", name, target)) - .arg(format!("--component-name=rust-stdZ-{}", target)) + .arg(format!("--component-name=rustc-dev-{}", target)) .arg("--legacy-manifest-dirs=rustlib,cargo"); - builder.info(&format!("Dist std stage{} ({} -> {})", + builder.info(&format!("Dist rustc-dev stage{} ({} -> {})", compiler.stage, &compiler.host, target)); let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); - distdir(builder).join(format!("{}-{}.tar.gz", name, target)) + archive } } From bd4e9d5fe146d5475dc35f5f61d5186b15692fdc Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 3 Oct 2019 11:40:39 -0700 Subject: [PATCH 167/545] add rustc-dev to tools/build-manifest --- src/tools/build-manifest/src/main.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index f41e7dd17ede..d5933789a649 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -399,6 +399,7 @@ impl Builder { fn add_packages_to(&mut self, manifest: &mut Manifest) { let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets); package("rustc", HOSTS); + package("rustc-dev", HOSTS); package("cargo", HOSTS); package("rust-mingw", MINGW); package("rust-std", TARGETS); @@ -473,6 +474,7 @@ impl Builder { // and so is rust-mingw if it's available for the target. components.extend(vec![ host_component("rustc"), + host_component("rustc-dev"), host_component("rust-std"), host_component("cargo"), host_component("rust-docs"), @@ -498,6 +500,11 @@ impl Builder { .filter(|&&target| target != host) .map(|target| Component::from_str("rust-std", target)) ); + extensions.extend( + HOSTS.iter() + .filter(|&&target| target != host) + .map(|target| Component::from_str("rustc-dev", target)) + ); extensions.push(Component::from_str("rust-src", "*")); // If the components/extensions don't actually exist for this From 2dcf2f0f7b965d5977dfbafec9128084bdd82a42 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 7 Oct 2019 09:31:51 -0700 Subject: [PATCH 168/545] Only install rustc-dev by default on nightly --- src/tools/build-manifest/src/main.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index d5933789a649..97e758f9b823 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -474,7 +474,6 @@ impl Builder { // and so is rust-mingw if it's available for the target. components.extend(vec![ host_component("rustc"), - host_component("rustc-dev"), host_component("rust-std"), host_component("cargo"), host_component("rust-docs"), @@ -483,6 +482,15 @@ impl Builder { components.push(host_component("rust-mingw")); } + // The compiler libraries are not stable for end users, but `rustc-dev` was only recently + // split out of `rust-std`. We'll include it by default as a transition for nightly users, + // but ship it as an optional component on the beta and stable channels. + if self.rust_release == "nightly" { + components.push(host_component("rustc-dev")); + } else { + extensions.push(host_component("rustc-dev")); + } + // Tools are always present in the manifest, // but might be marked as unavailable if they weren't built. extensions.extend(vec![ From 70c14dd9ddb0281195c2cb042ee406e8a55cba9c Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 7 Oct 2019 21:55:35 +0100 Subject: [PATCH 169/545] Move const generic regression tests to their old folder --- src/test/ui/const-generics/{ => issues}/issue-60263.rs | 0 src/test/ui/const-generics/{ => issues}/issue-60263.stderr | 0 .../{ => issues}/issue-60818-struct-constructors.rs | 0 .../{ => issues}/issue-60818-struct-constructors.stderr | 0 src/test/ui/const-generics/{ => issues}/issue-61336-1.rs | 0 src/test/ui/const-generics/{ => issues}/issue-61336-1.stderr | 0 src/test/ui/const-generics/{ => issues}/issue-61336-2.rs | 0 src/test/ui/const-generics/{ => issues}/issue-61336-2.stderr | 0 src/test/ui/const-generics/{ => issues}/issue-61336.rs | 0 src/test/ui/const-generics/{ => issues}/issue-61336.stderr | 0 src/test/ui/const-generics/{ => issues}/issue-61422.rs | 0 src/test/ui/const-generics/{ => issues}/issue-61422.stderr | 0 src/test/ui/const-generics/{ => issues}/issue-61432.rs | 0 src/test/ui/const-generics/{ => issues}/issue-61432.stderr | 0 src/test/ui/const-generics/{ => issues}/issue-64519.rs | 0 src/test/ui/const-generics/{ => issues}/issue-64519.stderr | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/const-generics/{ => issues}/issue-60263.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-60263.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-60818-struct-constructors.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-60818-struct-constructors.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-61336-1.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-61336-1.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-61336-2.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-61336-2.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-61336.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-61336.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-61422.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-61422.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-61432.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-61432.stderr (100%) rename src/test/ui/const-generics/{ => issues}/issue-64519.rs (100%) rename src/test/ui/const-generics/{ => issues}/issue-64519.stderr (100%) diff --git a/src/test/ui/const-generics/issue-60263.rs b/src/test/ui/const-generics/issues/issue-60263.rs similarity index 100% rename from src/test/ui/const-generics/issue-60263.rs rename to src/test/ui/const-generics/issues/issue-60263.rs diff --git a/src/test/ui/const-generics/issue-60263.stderr b/src/test/ui/const-generics/issues/issue-60263.stderr similarity index 100% rename from src/test/ui/const-generics/issue-60263.stderr rename to src/test/ui/const-generics/issues/issue-60263.stderr diff --git a/src/test/ui/const-generics/issue-60818-struct-constructors.rs b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs similarity index 100% rename from src/test/ui/const-generics/issue-60818-struct-constructors.rs rename to src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs diff --git a/src/test/ui/const-generics/issue-60818-struct-constructors.stderr b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr similarity index 100% rename from src/test/ui/const-generics/issue-60818-struct-constructors.stderr rename to src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr diff --git a/src/test/ui/const-generics/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs similarity index 100% rename from src/test/ui/const-generics/issue-61336-1.rs rename to src/test/ui/const-generics/issues/issue-61336-1.rs diff --git a/src/test/ui/const-generics/issue-61336-1.stderr b/src/test/ui/const-generics/issues/issue-61336-1.stderr similarity index 100% rename from src/test/ui/const-generics/issue-61336-1.stderr rename to src/test/ui/const-generics/issues/issue-61336-1.stderr diff --git a/src/test/ui/const-generics/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs similarity index 100% rename from src/test/ui/const-generics/issue-61336-2.rs rename to src/test/ui/const-generics/issues/issue-61336-2.rs diff --git a/src/test/ui/const-generics/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr similarity index 100% rename from src/test/ui/const-generics/issue-61336-2.stderr rename to src/test/ui/const-generics/issues/issue-61336-2.stderr diff --git a/src/test/ui/const-generics/issue-61336.rs b/src/test/ui/const-generics/issues/issue-61336.rs similarity index 100% rename from src/test/ui/const-generics/issue-61336.rs rename to src/test/ui/const-generics/issues/issue-61336.rs diff --git a/src/test/ui/const-generics/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr similarity index 100% rename from src/test/ui/const-generics/issue-61336.stderr rename to src/test/ui/const-generics/issues/issue-61336.stderr diff --git a/src/test/ui/const-generics/issue-61422.rs b/src/test/ui/const-generics/issues/issue-61422.rs similarity index 100% rename from src/test/ui/const-generics/issue-61422.rs rename to src/test/ui/const-generics/issues/issue-61422.rs diff --git a/src/test/ui/const-generics/issue-61422.stderr b/src/test/ui/const-generics/issues/issue-61422.stderr similarity index 100% rename from src/test/ui/const-generics/issue-61422.stderr rename to src/test/ui/const-generics/issues/issue-61422.stderr diff --git a/src/test/ui/const-generics/issue-61432.rs b/src/test/ui/const-generics/issues/issue-61432.rs similarity index 100% rename from src/test/ui/const-generics/issue-61432.rs rename to src/test/ui/const-generics/issues/issue-61432.rs diff --git a/src/test/ui/const-generics/issue-61432.stderr b/src/test/ui/const-generics/issues/issue-61432.stderr similarity index 100% rename from src/test/ui/const-generics/issue-61432.stderr rename to src/test/ui/const-generics/issues/issue-61432.stderr diff --git a/src/test/ui/const-generics/issue-64519.rs b/src/test/ui/const-generics/issues/issue-64519.rs similarity index 100% rename from src/test/ui/const-generics/issue-64519.rs rename to src/test/ui/const-generics/issues/issue-64519.rs diff --git a/src/test/ui/const-generics/issue-64519.stderr b/src/test/ui/const-generics/issues/issue-64519.stderr similarity index 100% rename from src/test/ui/const-generics/issue-64519.stderr rename to src/test/ui/const-generics/issues/issue-64519.stderr From 5e65e2bec2088d23f916fb4ed1a39bc5f9378998 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 7 Oct 2019 22:01:58 +0100 Subject: [PATCH 170/545] Add a regression test for issue 62187 --- .../issue-62187-encountered-polymorphic-const.rs | 16 ++++++++++++++++ ...ue-62187-encountered-polymorphic-const.stderr | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs create mode 100644 src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs new file mode 100644 index 000000000000..4dc46eb0ef65 --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs @@ -0,0 +1,16 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +pub trait BitLen: Sized { + const BIT_LEN: usize; +} + +impl BitLen for [u8; L] { + const BIT_LEN: usize = 8 * L; +} + +fn main() { + let foo = <[u8; 2]>::BIT_LEN; +} diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr new file mode 100644 index 000000000000..20347ac4b7da --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr @@ -0,0 +1,16 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-62187-encountered-polymorphic-const.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +warning: unused variable: `foo` + --> $DIR/issue-62187-encountered-polymorphic-const.rs:15:9 + | +LL | let foo = <[u8; 2]>::BIT_LEN; + | ^^^ help: consider prefixing with an underscore: `_foo` + | + = note: `#[warn(unused_variables)]` on by default + From 2328a7ea4012768e671b9caffd84e7612a5cf624 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 7 Oct 2019 22:05:56 +0100 Subject: [PATCH 171/545] Move stray issue tests into src/test/ui/issues --- src/test/ui/{ => issues}/issue-53912.rs | 0 src/test/ui/{ => issues}/issue-59020.rs | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => issues}/issue-53912.rs (100%) rename src/test/ui/{ => issues}/issue-59020.rs (100%) diff --git a/src/test/ui/issue-53912.rs b/src/test/ui/issues/issue-53912.rs similarity index 100% rename from src/test/ui/issue-53912.rs rename to src/test/ui/issues/issue-53912.rs diff --git a/src/test/ui/issue-59020.rs b/src/test/ui/issues/issue-59020.rs similarity index 100% rename from src/test/ui/issue-59020.rs rename to src/test/ui/issues/issue-59020.rs From 4eba21e4c752b75158b436afab141ebbbbb38439 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 7 Oct 2019 22:06:14 +0100 Subject: [PATCH 172/545] Add regression test for #64792 --- .../ui/issues/issue-64792-bad-unicode-ctor.rs | 5 +++++ .../ui/issues/issue-64792-bad-unicode-ctor.stderr | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui/issues/issue-64792-bad-unicode-ctor.rs create mode 100644 src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr diff --git a/src/test/ui/issues/issue-64792-bad-unicode-ctor.rs b/src/test/ui/issues/issue-64792-bad-unicode-ctor.rs new file mode 100644 index 000000000000..7bce57923a5b --- /dev/null +++ b/src/test/ui/issues/issue-64792-bad-unicode-ctor.rs @@ -0,0 +1,5 @@ +struct X {} + +const Y: X = X("ö"); //~ ERROR expected function, found struct `X` + +fn main() {} diff --git a/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr b/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr new file mode 100644 index 000000000000..ae9025bb041a --- /dev/null +++ b/src/test/ui/issues/issue-64792-bad-unicode-ctor.stderr @@ -0,0 +1,15 @@ +error[E0423]: expected function, found struct `X` + --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14 + | +LL | struct X {} + | ----------- `X` defined here +LL | +LL | const Y: X = X("ö"); + | ^ + | | + | did you mean `X { /* fields */ }`? + | help: a constant with a similar name exists: `Y` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0423`. From 85b7aa2cfbf8c5dbc642d60890b7cf710f1a7d60 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 7 Oct 2019 22:10:50 +0100 Subject: [PATCH 173/545] Add a regression test for #57399 --- .../issue-57399-self-return-impl-trait.rs | 22 +++++++++++++++++++ .../issue-57399-self-return-impl-trait.stderr | 8 +++++++ 2 files changed, 30 insertions(+) create mode 100644 src/test/ui/issues/issue-57399-self-return-impl-trait.rs create mode 100644 src/test/ui/issues/issue-57399-self-return-impl-trait.stderr diff --git a/src/test/ui/issues/issue-57399-self-return-impl-trait.rs b/src/test/ui/issues/issue-57399-self-return-impl-trait.rs new file mode 100644 index 000000000000..23d68263b3a2 --- /dev/null +++ b/src/test/ui/issues/issue-57399-self-return-impl-trait.rs @@ -0,0 +1,22 @@ +// run-pass + +trait T { + type T; +} + +impl T for i32 { + type T = u32; +} + +struct S { + a: A, +} + + +impl From for S<::T> { + fn from(a: u32) -> Self { + Self { a } + } +} + +fn main() {} diff --git a/src/test/ui/issues/issue-57399-self-return-impl-trait.stderr b/src/test/ui/issues/issue-57399-self-return-impl-trait.stderr new file mode 100644 index 000000000000..5c71410a8275 --- /dev/null +++ b/src/test/ui/issues/issue-57399-self-return-impl-trait.stderr @@ -0,0 +1,8 @@ +warning: field is never used: `a` + --> $DIR/issue-57399-self-return-impl-trait.rs:12:5 + | +LL | a: A, + | ^^^^ + | + = note: `#[warn(dead_code)]` on by default + From c99074490bc4e0d8a248bf807dfc3426341d7acd Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 7 Oct 2019 22:24:04 +0100 Subject: [PATCH 174/545] Add a regression test for #57271 --- .../ui/issues/auxiliary/issue-57271-lib.rs | 11 ++++++++ src/test/ui/issues/issue-57271.rs | 24 ++++++++++++++++++ src/test/ui/issues/issue-57271.stderr | 25 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 src/test/ui/issues/auxiliary/issue-57271-lib.rs create mode 100644 src/test/ui/issues/issue-57271.rs create mode 100644 src/test/ui/issues/issue-57271.stderr diff --git a/src/test/ui/issues/auxiliary/issue-57271-lib.rs b/src/test/ui/issues/auxiliary/issue-57271-lib.rs new file mode 100644 index 000000000000..ff625668a9dd --- /dev/null +++ b/src/test/ui/issues/auxiliary/issue-57271-lib.rs @@ -0,0 +1,11 @@ +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +pub enum BaseType { + Byte, + Char, + Double, + Float, + Int, + Long, + Short, + Boolean, +} diff --git a/src/test/ui/issues/issue-57271.rs b/src/test/ui/issues/issue-57271.rs new file mode 100644 index 000000000000..9940fecbeed5 --- /dev/null +++ b/src/test/ui/issues/issue-57271.rs @@ -0,0 +1,24 @@ +// aux-build:issue-57271-lib.rs + +extern crate issue_57271_lib; + +use issue_57271_lib::BaseType; + +pub enum ObjectType { //~ ERROR recursive type `ObjectType` has infinite size + Class(ClassTypeSignature), + Array(TypeSignature), + TypeVariable(()), +} + +pub struct ClassTypeSignature { + pub package: (), + pub class: (), + pub inner: (), +} + +pub enum TypeSignature { //~ ERROR recursive type `TypeSignature` has infinite size + Base(BaseType), + Object(ObjectType), +} + +fn main() {} diff --git a/src/test/ui/issues/issue-57271.stderr b/src/test/ui/issues/issue-57271.stderr new file mode 100644 index 000000000000..4f164624f7a5 --- /dev/null +++ b/src/test/ui/issues/issue-57271.stderr @@ -0,0 +1,25 @@ +error[E0072]: recursive type `ObjectType` has infinite size + --> $DIR/issue-57271.rs:7:1 + | +LL | pub enum ObjectType { + | ^^^^^^^^^^^^^^^^^^^ recursive type has infinite size +LL | Class(ClassTypeSignature), +LL | Array(TypeSignature), + | ------------- recursive without indirection + | + = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable + +error[E0072]: recursive type `TypeSignature` has infinite size + --> $DIR/issue-57271.rs:19:1 + | +LL | pub enum TypeSignature { + | ^^^^^^^^^^^^^^^^^^^^^^ recursive type has infinite size +LL | Base(BaseType), +LL | Object(ObjectType), + | ---------- recursive without indirection + | + = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0072`. From d3052540993b6acf009d39949b79077a49544934 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 7 Oct 2019 15:49:51 -0700 Subject: [PATCH 175/545] Add rustc-dev to nightly default and complete profiles --- src/tools/build-manifest/src/main.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 97e758f9b823..c0d2deab2f8b 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -427,6 +427,13 @@ impl Builder { "rls-preview", "rust-src", "llvm-tools-preview", "lldb-preview", "rust-analysis", "miri-preview" ]); + + // The compiler libraries are not stable for end users, but `rustc-dev` was only recently + // split out of `rust-std`. We'll include it by default as a transition for nightly users. + if self.rust_release == "nightly" { + self.extend_profile("default", &mut manifest.profiles, &["rustc-dev"]); + self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]); + } } fn add_renames_to(&self, manifest: &mut Manifest) { @@ -549,6 +556,14 @@ impl Builder { dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect()); } + fn extend_profile(&mut self, + profile_name: &str, + dst: &mut BTreeMap>, + pkgs: &[&str]) { + dst.get_mut(profile_name).expect("existing profile") + .extend(pkgs.iter().map(|s| (*s).to_owned())); + } + fn package(&mut self, pkgname: &str, dst: &mut BTreeMap, From 5aa37a9c9b99b62a4e8827c133b6a8f97e3b5734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 7 Oct 2019 16:18:02 -0700 Subject: [PATCH 176/545] Use structured suggestion for removal of `as_str()` call --- src/librustc_typeck/check/method/suggest.rs | 25 +++++++++++++++----- src/test/ui/suggestions/remove-as_str.stderr | 8 +++---- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 9820ede5b5c4..e058aeddfb8f 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -518,13 +518,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + let mut fallback_span = true; + let msg = "remove this method call"; if item_name.as_str() == "as_str" && actual.peel_refs().is_str() { - // FIXME: the span is not quite correct, it should point to ".as_str()" instead - // of just "as_str". - err.span_label( - span, - "try removing `as_str`" - ); + if let SelfSource::MethodCall(expr) = source { + let call_expr = self.tcx.hir().expect_expr( + self.tcx.hir().get_parent_node(expr.hir_id), + ); + if let Some(span) = call_expr.span.trim_start(expr.span) { + err.span_suggestion( + span, + msg, + String::new(), + Applicability::MachineApplicable, + ); + fallback_span = false; + } + } + if fallback_span { + err.span_label(span, msg); + } } else if let Some(lev_candidate) = lev_candidate { let def_kind = lev_candidate.def_kind(); err.span_suggestion( diff --git a/src/test/ui/suggestions/remove-as_str.stderr b/src/test/ui/suggestions/remove-as_str.stderr index 2e8b72ebd4f6..eae9cc075084 100644 --- a/src/test/ui/suggestions/remove-as_str.stderr +++ b/src/test/ui/suggestions/remove-as_str.stderr @@ -2,25 +2,25 @@ error[E0599]: no method named `as_str` found for type `&str` in the current scop --> $DIR/remove-as_str.rs:2:7 | LL | s.as_str(); - | ^^^^^^ try removing `as_str` + | -^^^^^^-- help: remove this method call error[E0599]: no method named `as_str` found for type `&'a str` in the current scope --> $DIR/remove-as_str.rs:7:7 | LL | s.as_str(); - | ^^^^^^ try removing `as_str` + | -^^^^^^-- help: remove this method call error[E0599]: no method named `as_str` found for type `&mut str` in the current scope --> $DIR/remove-as_str.rs:12:7 | LL | s.as_str(); - | ^^^^^^ try removing `as_str` + | -^^^^^^-- help: remove this method call error[E0599]: no method named `as_str` found for type `&&str` in the current scope --> $DIR/remove-as_str.rs:17:7 | LL | s.as_str(); - | ^^^^^^ try removing `as_str` + | -^^^^^^-- help: remove this method call error: aborting due to 4 previous errors From e068cec13e2a63dba29d40f0130527d980f83f7c Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 8 Sep 2019 10:00:26 -0400 Subject: [PATCH 177/545] Warn if include macro fails to include entire file --- src/librustc/lint/builtin.rs | 6 ++++++ src/librustc/lint/mod.rs | 2 ++ src/libsyntax/early_buffered_lints.rs | 1 + src/libsyntax_ext/source_util.rs | 12 +++++++++++- src/test/ui/include-single-expr-helper-1.rs | 5 +++++ src/test/ui/include-single-expr-helper.rs | 5 +++++ src/test/ui/include-single-expr.rs | 6 ++++++ src/test/ui/include-single-expr.stderr | 10 ++++++++++ src/tools/error_index_generator/build.rs | 2 +- 9 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/include-single-expr-helper-1.rs create mode 100644 src/test/ui/include-single-expr-helper.rs create mode 100644 src/test/ui/include-single-expr.rs create mode 100644 src/test/ui/include-single-expr.stderr diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 5906a6388a8b..5ca474a8b1d9 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -368,6 +368,12 @@ pub mod parser { Allow, "possible meta-variable misuse at macro definition" } + + declare_lint! { + pub INCOMPLETE_INCLUDE, + Deny, + "trailing content in included file" + } } declare_lint! { diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 5b490b701267..b31efc24e52d 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -28,6 +28,7 @@ use crate::hir::intravisit; use crate::hir; use crate::lint::builtin::BuiltinLintDiagnostics; use crate::lint::builtin::parser::{ILL_FORMED_ATTRIBUTE_INPUT, META_VARIABLE_MISUSE}; +use crate::lint::builtin::parser::INCOMPLETE_INCLUDE; use crate::session::{Session, DiagnosticMessageId}; use crate::ty::TyCtxt; use crate::ty::query::Providers; @@ -83,6 +84,7 @@ impl Lint { match lint_id { BufferedEarlyLintId::IllFormedAttributeInput => ILL_FORMED_ATTRIBUTE_INPUT, BufferedEarlyLintId::MetaVariableMisuse => META_VARIABLE_MISUSE, + BufferedEarlyLintId::IncompleteInclude => INCOMPLETE_INCLUDE, } } diff --git a/src/libsyntax/early_buffered_lints.rs b/src/libsyntax/early_buffered_lints.rs index 36c1da292997..5cc953b90662 100644 --- a/src/libsyntax/early_buffered_lints.rs +++ b/src/libsyntax/early_buffered_lints.rs @@ -11,6 +11,7 @@ use syntax_pos::MultiSpan; pub enum BufferedEarlyLintId { IllFormedAttributeInput, MetaVariableMisuse, + IncompleteInclude, } /// Stores buffered lint info which can later be passed to `librustc`. diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs index 9dc9d66b86f1..f74507dcc21f 100644 --- a/src/libsyntax_ext/source_util.rs +++ b/src/libsyntax_ext/source_util.rs @@ -5,6 +5,7 @@ use syntax::print::pprust; use syntax::ptr::P; use syntax::symbol::Symbol; use syntax::tokenstream::TokenStream; +use syntax::early_buffered_lints::BufferedEarlyLintId; use smallvec::SmallVec; use syntax_pos::{self, Pos, Span}; @@ -83,7 +84,16 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream) } impl<'a> base::MacResult for ExpandResult<'a> { fn make_expr(mut self: Box>) -> Option> { - Some(panictry!(self.p.parse_expr())) + let r = panictry!(self.p.parse_expr()); + if self.p.token != token::Eof { + self.p.sess.buffer_lint( + BufferedEarlyLintId::IncompleteInclude, + self.p.token.span, + ast::CRATE_NODE_ID, + "include macro expected single expression in source", + ); + } + Some(r) } fn make_items(mut self: Box>) -> Option; 1]>> { diff --git a/src/test/ui/include-single-expr-helper-1.rs b/src/test/ui/include-single-expr-helper-1.rs new file mode 100644 index 000000000000..aa6380bd24dc --- /dev/null +++ b/src/test/ui/include-single-expr-helper-1.rs @@ -0,0 +1,5 @@ +// ignore-test auxiliary file for include-single-expr.rs + +0 + +// trailing comment permitted diff --git a/src/test/ui/include-single-expr-helper.rs b/src/test/ui/include-single-expr-helper.rs new file mode 100644 index 000000000000..84d8b69603b6 --- /dev/null +++ b/src/test/ui/include-single-expr-helper.rs @@ -0,0 +1,5 @@ +// ignore-test auxiliary file for include-single-expr.rs + +0 +10 +100 diff --git a/src/test/ui/include-single-expr.rs b/src/test/ui/include-single-expr.rs new file mode 100644 index 000000000000..0f4c29ec0145 --- /dev/null +++ b/src/test/ui/include-single-expr.rs @@ -0,0 +1,6 @@ +// error-pattern include macro expected single expression + +fn main() { + include!("include-single-expr-helper.rs"); + include!("include-single-expr-helper-1.rs"); +} diff --git a/src/test/ui/include-single-expr.stderr b/src/test/ui/include-single-expr.stderr new file mode 100644 index 000000000000..80eecf8f1b97 --- /dev/null +++ b/src/test/ui/include-single-expr.stderr @@ -0,0 +1,10 @@ +error: include macro expected single expression in source + --> $DIR/include-single-expr-helper.rs:4:1 + | +LL | 10 + | ^^ + | + = note: `#[deny(incomplete_include)]` on by default + +error: aborting due to previous error + diff --git a/src/tools/error_index_generator/build.rs b/src/tools/error_index_generator/build.rs index 592b3f14c85a..c59533da1dc3 100644 --- a/src/tools/error_index_generator/build.rs +++ b/src/tools/error_index_generator/build.rs @@ -15,7 +15,7 @@ fn main() { println!("cargo:rerun-if-changed={}", entry.path().to_str().unwrap()); let file = fs::read_to_string(entry.path()).unwrap() .replace("syntax::register_diagnostics!", "register_diagnostics!"); - let contents = format!("(|| {{\n{}\n}})();", file); + let contents = format!("(|| {{\n{}\n}})()", file); fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap(); From 3f9aea199ceefef9855850ab7843ef6935055eca Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 30 Sep 2019 14:03:53 +1000 Subject: [PATCH 178/545] Clarify a comment in `RegionConstraintCollector::leak_check`. --- src/librustc/infer/region_constraints/leak_check.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc/infer/region_constraints/leak_check.rs b/src/librustc/infer/region_constraints/leak_check.rs index 0c83bbc1e539..3d069425685c 100644 --- a/src/librustc/infer/region_constraints/leak_check.rs +++ b/src/librustc/infer/region_constraints/leak_check.rs @@ -14,9 +14,11 @@ impl<'tcx> RegionConstraintCollector<'tcx> { /// retain the older (arguably incorrect) behavior of the /// compiler. /// - /// NB. The use of snapshot here is mostly an efficiency thing -- - /// we could search *all* region constraints, but that'd be a - /// bigger set and the data structures are not setup for that. If + /// NB. Although `_snapshot` isn't used, it's passed in to prove + /// that we are in a snapshot, which guarantees that we can just + /// search the "undo log" for edges. This is mostly an efficiency + /// thing -- we could search *all* region constraints, but that'd be + /// a bigger set and the data structures are not setup for that. If /// we wind up keeping some form of this check long term, it would /// probably be better to remove the snapshot parameter and to /// refactor the constraint set. From 1b41f958c5d0d84b8dac385fb30bb7c7f12c13b8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 30 Sep 2019 14:42:11 +1000 Subject: [PATCH 179/545] Remove `InferCtxt::in_snapshot()`. It's the same as `InferCtxt::commit_unconditionally()` except that it is passed a snapshot and has a worse name. The commit also changes `commit_unconditionally()` to receive a snapshot, for consistency with `commit_if_ok()` and `probe()`. --- src/librustc/infer/mod.rs | 22 +++++----------------- src/librustc/traits/select.rs | 35 ++++++++++++++++++----------------- 2 files changed, 23 insertions(+), 34 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index ea9e931ad838..af74d1357243 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -814,16 +814,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Executes `f` and commit the bindings. pub fn commit_unconditionally(&self, f: F) -> R where - F: FnOnce() -> R, + F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R, { - debug!("commit()"); + debug!("commit_unconditionally()"); let snapshot = self.start_snapshot(); - let r = f(); + let r = f(&snapshot); self.commit_from(snapshot); r } - /// Executes `f` and commit the bindings if closure `f` returns `Ok(_)`. + /// Execute `f` and commit the bindings if closure `f` returns `Ok(_)`. pub fn commit_if_ok(&self, f: F) -> Result where F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> Result, @@ -843,19 +843,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { r } - /// Execute `f` in a snapshot, and commit the bindings it creates. - pub fn in_snapshot(&self, f: F) -> T - where - F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> T, - { - debug!("in_snapshot()"); - let snapshot = self.start_snapshot(); - let r = f(&snapshot); - self.commit_from(snapshot); - r - } - - /// Executes `f` then unroll any bindings it creates. + /// Execute `f` then unroll any bindings it creates. pub fn probe(&self, f: F) -> R where F: FnOnce(&CombinedSnapshot<'a, 'tcx>) -> R, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 4ee5700f43fe..44d611ace77d 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2819,7 +2819,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // binder moved -\ let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ - self.infcx.in_snapshot(|_| { + self.infcx.commit_unconditionally(|_| { let (skol_ty, _) = self.infcx .replace_bound_vars_with_placeholders(&ty); let Normalized { @@ -2932,7 +2932,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) { - self.infcx.in_snapshot(|snapshot| { + self.infcx.commit_unconditionally(|snapshot| { let result = self.match_projection_obligation_against_definition_bounds( obligation, @@ -3054,19 +3054,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { nested, ); - let trait_obligations: Vec> = self.infcx.in_snapshot(|_| { - let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); - let (trait_ref, _) = self.infcx - .replace_bound_vars_with_placeholders(&poly_trait_ref); - let cause = obligation.derived_cause(ImplDerivedObligation); - self.impl_or_trait_obligations( - cause, - obligation.recursion_depth + 1, - obligation.param_env, - trait_def_id, - &trait_ref.substs, - ) - }); + let trait_obligations: Vec> = + self.infcx.commit_unconditionally(|_| { + let poly_trait_ref = obligation.predicate.to_poly_trait_ref(); + let (trait_ref, _) = self.infcx + .replace_bound_vars_with_placeholders(&poly_trait_ref); + let cause = obligation.derived_cause(ImplDerivedObligation); + self.impl_or_trait_obligations( + cause, + obligation.recursion_depth + 1, + obligation.param_env, + trait_def_id, + &trait_ref.substs, + ) + }); // Adds the predicates from the trait. Note that this contains a `Self: Trait` // predicate as usual. It won't have any effect since auto traits are coinductive. @@ -3089,7 +3090,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // First, create the substitutions by matching the impl again, // this time not in a probe. - self.infcx.in_snapshot(|snapshot| { + self.infcx.commit_unconditionally(|snapshot| { let substs = self.rematch_impl(impl_def_id, obligation, snapshot); debug!("confirm_impl_candidate: substs={:?}", substs); let cause = obligation.derived_cause(ImplDerivedObligation); @@ -3253,7 +3254,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation, alias_def_id ); - self.infcx.in_snapshot(|_| { + self.infcx.commit_unconditionally(|_| { let (predicate, _) = self.infcx() .replace_bound_vars_with_placeholders(&obligation.predicate); let trait_ref = predicate.trait_ref; From 3832a634d3aa6a7c60448906e6656a22f7e35628 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 8 Oct 2019 10:34:53 +1100 Subject: [PATCH 180/545] Optimize `TokenStream::from_streams`. Currently, this function creates a new empty stream, and then appends the elements from each given stream onto that stream. This can cause quadratic behaviour. This commit changes the function so that it modifies the first stream (which can be long) by extending it with the elements from the subsequent streams (which are almost always short), which avoids the quadratic behaviour. --- src/libsyntax/tokenstream.rs | 49 ++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 26cae2a8e7c4..76983f8ef854 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -249,20 +249,47 @@ impl TokenStream { 0 => TokenStream::empty(), 1 => streams.pop().unwrap(), _ => { - // rust-lang/rust#57735: pre-allocate vector to avoid - // quadratic blow-up due to on-the-fly reallocations. - let tree_count = streams.iter() - .map(|ts| match &ts.0 { None => 0, Some(s) => s.len() }) - .sum(); - let mut vec = Vec::with_capacity(tree_count); + // We are going to extend the first stream in `streams` with + // the elements from the subsequent streams. This requires + // using `make_mut()` on the first stream, and in practice this + // doesn't cause cloning 99.9% of the time. + // + // One very common use case is when `streams` has two elements, + // where the first stream has any number of elements within + // (often 1, but sometimes many more) and the second stream has + // a single element within. - for stream in streams { - match stream.0 { - None => {}, - Some(stream2) => vec.extend(stream2.iter().cloned()), + // Determine how much the first stream will be extended. + // Needed to avoid quadratic blow up from on-the-fly + // reallocations (#57735). + let num_appends = streams.iter() + .skip(1) + .map(|ts| ts.len()) + .sum(); + + // Get the first stream. If it's `None`, create an empty + // stream. + let mut iter = streams.drain(); + let mut first_stream_lrc = match iter.next().unwrap().0 { + Some(first_stream_lrc) => first_stream_lrc, + None => Lrc::new(vec![]), + }; + + // Append the elements to the first stream, after reserving + // space for them. + let first_vec_mut = Lrc::make_mut(&mut first_stream_lrc); + first_vec_mut.reserve(num_appends); + for stream in iter { + if let Some(stream) = stream.0 { + first_vec_mut.extend(stream.iter().cloned()); } } - TokenStream::new(vec) + + // Create the final `TokenStream`. + match first_vec_mut.len() { + 0 => TokenStream(None), + _ => TokenStream(Some(first_stream_lrc)), + } } } } From 75e0078a1703448a19e25eac85daaa5a4e6e68ac Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 8 Oct 2019 13:32:59 +1100 Subject: [PATCH 181/545] Optimize `TokenStreamBuilder::push`. Currently, when two tokens must be glued together, this function duplicates large chunks of the existing streams. This can cause quadratic behaviour. This commit changes the function so that it overwrites the last token with a glued token, which avoids the quadratic behaviour. This removes the need for `TokenStreamBuilder::push_all_but_{first,last}_tree`. The commit also restructures `push` somewhat, by removing `TokenStream::{first_tree_and_joint,last_tree_if_joint}` in favour of more pattern matching and some comments. This makes the code shorter, and in my opinion, more readable. --- src/libsyntax/tokenstream.rs | 94 +++++++++++++++++------------------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 76983f8ef854..bef12ed4fada 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -390,25 +390,6 @@ impl TokenStream { .collect()) })) } - - fn first_tree_and_joint(&self) -> Option { - self.0.as_ref().map(|stream| { - stream.first().unwrap().clone() - }) - } - - fn last_tree_if_joint(&self) -> Option { - match self.0 { - None => None, - Some(ref stream) => { - if let (tree, Joint) = stream.last().unwrap() { - Some(tree.clone()) - } else { - None - } - } - } - } } // 99.5%+ of the time we have 1 or 2 elements in this vector. @@ -421,18 +402,49 @@ impl TokenStreamBuilder { } pub fn push>(&mut self, stream: T) { - let stream = stream.into(); - let last_tree_if_joint = self.0.last().and_then(TokenStream::last_tree_if_joint); - if let Some(TokenTree::Token(last_token)) = last_tree_if_joint { - if let Some((TokenTree::Token(token), is_joint)) = stream.first_tree_and_joint() { - if let Some(glued_tok) = last_token.glue(&token) { - let last_stream = self.0.pop().unwrap(); - self.push_all_but_last_tree(&last_stream); - let glued_tt = TokenTree::Token(glued_tok); - let glued_tokenstream = TokenStream::new(vec![(glued_tt, is_joint)]); - self.0.push(glued_tokenstream); - self.push_all_but_first_tree(&stream); - return + let mut stream = stream.into(); + + // If `self` is not empty and the last tree within the last stream is a + // token tree marked with `Joint`... + if let Some(TokenStream(Some(ref mut last_stream_lrc))) = self.0.last_mut() { + if let Some((TokenTree::Token(last_token), Joint)) = last_stream_lrc.last() { + + // ...and `stream` is not empty and the first tree within it is + // a token tree... + if let TokenStream(Some(ref mut stream_lrc)) = stream { + if let Some((TokenTree::Token(token), is_joint)) = stream_lrc.first() { + + // ...and the two tokens can be glued together... + if let Some(glued_tok) = last_token.glue(&token) { + + // ...then do so, by overwriting the last token + // tree in `self` and removing the first token tree + // from `stream`. This requires using `make_mut()` + // on the last stream in `self` and on `stream`, + // and in practice this doesn't cause cloning 99.9% + // of the time. + + // Overwrite the last token tree with the merged + // token. + let last_vec_mut = Lrc::make_mut(last_stream_lrc); + *last_vec_mut.last_mut().unwrap() = + (TokenTree::Token(glued_tok), *is_joint); + + // Remove the first token tree from `stream`. (This + // is almost always the only tree in `stream`.) + let stream_vec_mut = Lrc::make_mut(stream_lrc); + stream_vec_mut.remove(0); + + // Don't push `stream` if it's empty -- that could + // block subsequent token gluing, by getting + // between two token trees that should be glued + // together. + if !stream.is_empty() { + self.0.push(stream); + } + return; + } + } } } } @@ -442,26 +454,6 @@ impl TokenStreamBuilder { pub fn build(self) -> TokenStream { TokenStream::from_streams(self.0) } - - fn push_all_but_last_tree(&mut self, stream: &TokenStream) { - if let Some(ref streams) = stream.0 { - let len = streams.len(); - match len { - 1 => {} - _ => self.0.push(TokenStream(Some(Lrc::new(streams[0 .. len - 1].to_vec())))), - } - } - } - - fn push_all_but_first_tree(&mut self, stream: &TokenStream) { - if let Some(ref streams) = stream.0 { - let len = streams.len(); - match len { - 1 => {} - _ => self.0.push(TokenStream(Some(Lrc::new(streams[1 .. len].to_vec())))), - } - } - } } #[derive(Clone)] From 58089717b9f824ff278e37c4b1f29e7dc1fa47a9 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Tue, 8 Oct 2019 12:19:00 +0200 Subject: [PATCH 182/545] Add ?Sized bound to a supertrait listing in E0038 error documentation This example failed to compile because of implicit `Sized` bound for `A` parameter that wasn't required by `Trait`. --- src/librustc/error_codes.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 502172db91c9..2de9cb5e9fb6 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -259,8 +259,8 @@ trait Foo { This is similar to the second sub-error, but subtler. It happens in situations like the following: -```compile_fail -trait Super {} +``` +trait Super {} trait Trait: Super { } @@ -275,8 +275,8 @@ impl Trait for Foo {} Here, the supertrait might have methods as follows: ``` -trait Super { - fn get_a(&self) -> A; // note that this is object safe! +trait Super { + fn get_a(&self) -> &A; // note that this is object safe! } ``` From 3b0fd82bfad814ff777e7aa236b74804e4c469c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 8 Oct 2019 00:00:00 +0000 Subject: [PATCH 183/545] Disable Go and OCaml bindings when building LLVM Instead of instaling OCaml bindings in a location where installation will not fail, don't build them in the first place. --- src/bootstrap/native.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 7bf9ea2688f4..fb308bc35ebc 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -157,6 +157,7 @@ impl Step for Llvm { .define("WITH_POLLY", "OFF") .define("LLVM_ENABLE_TERMINFO", "OFF") .define("LLVM_ENABLE_LIBEDIT", "OFF") + .define("LLVM_ENABLE_BINDINGS", "OFF") .define("LLVM_ENABLE_Z3_SOLVER", "OFF") .define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string()) .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) @@ -169,15 +170,6 @@ impl Step for Llvm { } } - // By default, LLVM will automatically find OCaml and, if it finds it, - // install the LLVM bindings in LLVM_OCAML_INSTALL_PATH, which defaults - // to /usr/bin/ocaml. - // This causes problem for non-root builds of Rust. Side-step the issue - // by setting LLVM_OCAML_INSTALL_PATH to a relative path, so it installs - // in the prefix. - cfg.define("LLVM_OCAML_INSTALL_PATH", - env::var_os("LLVM_OCAML_INSTALL_PATH").unwrap_or_else(|| "usr/lib/ocaml".into())); - let want_lldb = builder.config.lldb_enabled && !self.emscripten; // This setting makes the LLVM tools link to the dynamic LLVM library, From d1d256592bcd3f05d00fe7ad80d1a1ed22c9e7d7 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 6 Oct 2019 21:58:32 +0800 Subject: [PATCH 184/545] suggest to add move keyword for generator --- .../borrow_check/conflict_errors.rs | 26 +++++++++++++++++++ .../borrow_check/nll/explain_borrow/mod.rs | 3 ++- .../async-borrowck-escaping-block-error.fixed | 12 +++++++++ .../async-borrowck-escaping-block-error.rs | 7 +++-- ...async-borrowck-escaping-block-error.stderr | 4 +-- 5 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/async-await/async-borrowck-escaping-block-error.fixed diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index ef459ef0c1b7..2f9df7bd77e8 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -750,6 +750,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let kind_place = kind.filter(|_| place_desc.is_some()).map(|k| (k, place_span.0)); let explanation = self.explain_why_borrow_contains_point(location, &borrow, kind_place); + debug!( + "report_borrowed_value_does_not_live_long_enough(place_desc: {:?}, explanation: {:?})", + place_desc, + explanation + ); let err = match (place_desc, explanation) { (Some(_), _) if self.is_place_thread_local(root_place) => { self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span) @@ -790,6 +795,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { span, &format!("`{}`", name), ), + ( + Some(ref name), + BorrowExplanation::MustBeValidFor { + category: category @ ConstraintCategory::OpaqueType, + from_closure: false, + ref region_name, + span, + .. + }, + + ) if borrow_spans.for_generator() => self.report_escaping_closure_capture( + borrow_spans.args_or_use(), + borrow_span, + region_name, + category, + span, + &format!("`{}`", name), + ), ( ref name, BorrowExplanation::MustBeValidFor { @@ -1214,6 +1237,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ConstraintCategory::Return => { err.span_note(constraint_span, "closure is returned here"); } + ConstraintCategory::OpaqueType => { + err.span_note(constraint_span, "generator is returned here"); + } ConstraintCategory::CallArgument => { fr_name.highlight_region_name(&mut err); err.span_note( diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index ff4243df6e9b..5354b45f92d0 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -17,6 +17,7 @@ use syntax_pos::Span; mod find_use; +#[derive(Debug)] pub(in crate::borrow_check) enum BorrowExplanation { UsedLater(LaterUseKind, Span), UsedLaterInLoop(LaterUseKind, Span), @@ -35,7 +36,7 @@ pub(in crate::borrow_check) enum BorrowExplanation { Unexplained, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub(in crate::borrow_check) enum LaterUseKind { TraitCapture, ClosureCapture, diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed b/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed new file mode 100644 index 000000000000..f004b4180ddc --- /dev/null +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.fixed @@ -0,0 +1,12 @@ +// edition:2018 +// run-rustfix + +fn foo() -> Box> { + let x = 0u32; + Box::new(async move { x } ) + //~^ ERROR E0373 +} + +fn main() { + let _foo = foo(); +} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs index 49f59e414931..4f35fd52ca39 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.rs +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.rs @@ -1,9 +1,12 @@ // edition:2018 -#![feature(async_closure,async_await)] +// run-rustfix + fn foo() -> Box> { let x = 0u32; Box::new(async { x } ) //~^ ERROR E0373 } -fn main() {} +fn main() { + let _foo = foo(); +} diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr index 5771ccbcf9d1..af17ecc86fbf 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -1,5 +1,5 @@ error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function - --> $DIR/async-borrowck-escaping-block-error.rs:5:20 + --> $DIR/async-borrowck-escaping-block-error.rs:6:20 | LL | Box::new(async { x } ) | ^^-^^ @@ -8,7 +8,7 @@ LL | Box::new(async { x } ) | may outlive borrowed value `x` | note: generator is returned here - --> $DIR/async-borrowck-escaping-block-error.rs:3:13 + --> $DIR/async-borrowck-escaping-block-error.rs:4:13 | LL | fn foo() -> Box> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 61d92a09529818bdd3ed832a7e2fdd6394c358bf Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Oct 2019 12:59:39 +0200 Subject: [PATCH 185/545] Add long error explanation for E0567 --- src/librustc_passes/error_codes.rs | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index a3c46f7a6fc9..fbd06c34800d 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -314,6 +314,34 @@ type A3 = fn(i16); // ok! ``` "##, +E0567: r##" +Generics have been used on an auto trait. + +Erroneous code example: + +```compile_fail,E0567 +#![feature(optin_builtin_traits)] + +auto trait Generic {} // error! + +fn main() {} +``` + +Since an auto trait is implemented on all existing types, the +compiler would not be able to infer the types of the trait's generic +parameters. + +To fix this issue, just remove the generics: + +``` +#![feature(optin_builtin_traits)] + +auto trait Generic {} // ok! + +fn main() {} +``` +"##, + E0571: r##" A `break` statement with an argument appeared in a non-`loop` loop. @@ -531,7 +559,6 @@ Switch to the Rust 2018 edition to use `async fn`. ; E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target - E0567, // auto traits can not have generic parameters E0568, // auto traits can not have super traits E0666, // nested `impl Trait` is illegal E0667, // `impl Trait` in projections From 6608e4af1bd80f096f1f52c118e856d23498c787 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Oct 2019 14:08:26 +0200 Subject: [PATCH 186/545] Update ui tests --- src/test/ui/auto-trait-validation.stderr | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-trait-validation.stderr index ae21984c06d7..d797f30a2fc8 100644 --- a/src/test/ui/auto-trait-validation.stderr +++ b/src/test/ui/auto-trait-validation.stderr @@ -18,4 +18,5 @@ LL | auto trait MyTrait { fn foo() {} } error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0380`. +Some errors have detailed explanations: E0380, E0567. +For more information about an error, try `rustc --explain E0380`. From 6d3e242a2b56277d80c89fac3ab238838e3f28b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Tue, 8 Oct 2019 14:14:09 +0200 Subject: [PATCH 187/545] Update Clippy --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 648e5b90b49a..5cb983338e92 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 648e5b90b49af483d07caa8e413473a4517853d6 +Subproject commit 5cb983338e924ec85898880d60e65f2a1291b7be From d84c4cd7188f484083091bee436dc07eb90b47e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Oct 2019 08:26:42 -0700 Subject: [PATCH 188/545] Ignore `ExprKind::DropTemps` for some ref suggestions --- src/librustc/hir/mod.rs | 17 +++++++++++ src/librustc_typeck/check/demand.rs | 3 ++ src/test/ui/if/if-no-match-bindings.stderr | 28 ++++++------------- .../disallowed-positions.stderr | 4 +-- 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 30b050366887..ead7a08c397f 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1548,6 +1548,23 @@ impl Expr { } } } + + /// If `Self.kind` is `ExprKind::DropTemps(expr)`, drill down until we get a non-`DropTemps` + /// `Expr`. This is used in suggestions to ignore this `ExprKind` as it is semantically + /// silent, only signaling the ownership system. By doing this, suggestions that check the + /// `ExprKind` of any given `Expr` for presentation don't have to care about `DropTemps` + /// beyond remembering to call this function before doing analysis on it. + pub fn peel_drop_temps(&self) -> &Self { + let mut base_expr = self; + loop { + match &base_expr.kind { + ExprKind::DropTemps(expr) => { + base_expr = &expr; + } + _ => return base_expr, + } + } + } } impl fmt::Debug for Expr { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 78bd4508e21a..9f7f8b7680f4 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -355,6 +355,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let is_macro = sp.from_expansion() && !is_desugaring; + // `ExprKind::DropTemps` is semantically irrelevant for these suggestions. + let expr = expr.peel_drop_temps(); + match (&expr.kind, &expected.kind, &checked_ty.kind) { (_, &ty::Ref(_, exp, _), &ty::Ref(_, check, _)) => match (&exp.kind, &check.kind) { (&ty::Str, &ty::Array(arr, _)) | diff --git a/src/test/ui/if/if-no-match-bindings.stderr b/src/test/ui/if/if-no-match-bindings.stderr index 53b7aafc430a..fa2455db2b2a 100644 --- a/src/test/ui/if/if-no-match-bindings.stderr +++ b/src/test/ui/if/if-no-match-bindings.stderr @@ -2,10 +2,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:18:8 | LL | if b_ref() {} - | ^^^^^^^ - | | - | expected bool, found &bool - | help: consider dereferencing the borrow: `*b_ref()` + | ^^^^^^^ expected bool, found &bool | = note: expected type `bool` found type `&bool` @@ -14,10 +11,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:19:8 | LL | if b_mut_ref() {} - | ^^^^^^^^^^^ - | | - | expected bool, found &mut bool - | help: consider dereferencing the borrow: `*b_mut_ref()` + | ^^^^^^^^^^^ expected bool, found &mut bool | = note: expected type `bool` found type `&mut bool` @@ -29,7 +23,7 @@ LL | if &true {} | ^^^^^ | | | expected bool, found &bool - | help: consider dereferencing the borrow: `*&true` + | help: consider removing the borrow: `true` | = note: expected type `bool` found type `&bool` @@ -41,7 +35,7 @@ LL | if &mut true {} | ^^^^^^^^^ | | | expected bool, found &mut bool - | help: consider dereferencing the borrow: `*&mut true` + | help: consider removing the borrow: `true` | = note: expected type `bool` found type `&mut bool` @@ -50,10 +44,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:24:11 | LL | while b_ref() {} - | ^^^^^^^ - | | - | expected bool, found &bool - | help: consider dereferencing the borrow: `*b_ref()` + | ^^^^^^^ expected bool, found &bool | = note: expected type `bool` found type `&bool` @@ -62,10 +53,7 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:25:11 | LL | while b_mut_ref() {} - | ^^^^^^^^^^^ - | | - | expected bool, found &mut bool - | help: consider dereferencing the borrow: `*b_mut_ref()` + | ^^^^^^^^^^^ expected bool, found &mut bool | = note: expected type `bool` found type `&mut bool` @@ -77,7 +65,7 @@ LL | while &true {} | ^^^^^ | | | expected bool, found &bool - | help: consider dereferencing the borrow: `*&true` + | help: consider removing the borrow: `true` | = note: expected type `bool` found type `&bool` @@ -89,7 +77,7 @@ LL | while &mut true {} | ^^^^^^^^^ | | | expected bool, found &mut bool - | help: consider dereferencing the borrow: `*&mut true` + | help: consider removing the borrow: `true` | = note: expected type `bool` found type `&mut bool` 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 619f9c85b24d..ad4686c1915d 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 @@ -520,7 +520,7 @@ LL | if &let 0 = 0 {} | ^^^^^^^^^^ | | | expected bool, found &bool - | help: consider dereferencing the borrow: `*&let 0 = 0` + | help: consider removing the borrow: `let 0 = 0` | = note: expected type `bool` found type `&bool` @@ -708,7 +708,7 @@ LL | while &let 0 = 0 {} | ^^^^^^^^^^ | | | expected bool, found &bool - | help: consider dereferencing the borrow: `*&let 0 = 0` + | help: consider removing the borrow: `let 0 = 0` | = note: expected type `bool` found type `&bool` From ac9025c1979d0b4019d90a8ab7ad4336d468a0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Oct 2019 08:42:26 -0700 Subject: [PATCH 189/545] Call `Expr::peel_drop_temps()` from more places for more accurate suggestions --- src/librustc_typeck/check/demand.rs | 1 + src/librustc_typeck/check/expr.rs | 6 +----- src/librustc_typeck/check/mod.rs | 9 +++++---- src/test/ui/if/if-no-match-bindings.stderr | 20 ++++++++++++++++---- 4 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 9f7f8b7680f4..2b672c96dfa6 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -109,6 +109,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { allow_two_phase: AllowTwoPhase) -> (Ty<'tcx>, Option>) { let expected = self.resolve_type_vars_with_obligations(expected); + let expr = expr.peel_drop_temps(); let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase) { Ok(ty) => return (ty, None), diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index aa26c74967a1..ad46a443b8ff 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -87,12 +87,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) { + let expr = expr.peel_drop_temps(); self.suggest_ref_or_into(&mut err, expr, expected_ty, ty); - - let expr = match &expr.kind { - ExprKind::DropTemps(expr) => expr, - _ => expr, - }; extend_err(&mut err); // Error possibly reported in `check_assign` so avoid emitting error again. err.emit_unless(self.is_assign_to_bool(expr, expected_ty)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f130ee821d17..7475b9cc3b32 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4216,20 +4216,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn suggest_mismatched_types_on_tail( &self, err: &mut DiagnosticBuilder<'tcx>, - expression: &'tcx hir::Expr, + expr: &'tcx hir::Expr, expected: Ty<'tcx>, found: Ty<'tcx>, cause_span: Span, blk_id: hir::HirId, ) -> bool { - self.suggest_missing_semicolon(err, expression, expected, cause_span); + let expr = expr.peel_drop_temps(); + self.suggest_missing_semicolon(err, expr, expected, cause_span); let mut pointing_at_return_type = false; if let Some((fn_decl, can_suggest)) = self.get_fn_decl(blk_id) { pointing_at_return_type = self.suggest_missing_return_type( err, &fn_decl, expected, found, can_suggest); } - self.suggest_ref_or_into(err, expression, expected, found); - self.suggest_boxing_when_appropriate(err, expression, expected, found); + self.suggest_ref_or_into(err, expr, expected, found); + self.suggest_boxing_when_appropriate(err, expr, expected, found); pointing_at_return_type } diff --git a/src/test/ui/if/if-no-match-bindings.stderr b/src/test/ui/if/if-no-match-bindings.stderr index fa2455db2b2a..0936f3b9e38e 100644 --- a/src/test/ui/if/if-no-match-bindings.stderr +++ b/src/test/ui/if/if-no-match-bindings.stderr @@ -2,7 +2,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:18:8 | LL | if b_ref() {} - | ^^^^^^^ expected bool, found &bool + | ^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*b_ref()` | = note: expected type `bool` found type `&bool` @@ -11,7 +14,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:19:8 | LL | if b_mut_ref() {} - | ^^^^^^^^^^^ expected bool, found &mut bool + | ^^^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*b_mut_ref()` | = note: expected type `bool` found type `&mut bool` @@ -44,7 +50,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:24:11 | LL | while b_ref() {} - | ^^^^^^^ expected bool, found &bool + | ^^^^^^^ + | | + | expected bool, found &bool + | help: consider dereferencing the borrow: `*b_ref()` | = note: expected type `bool` found type `&bool` @@ -53,7 +62,10 @@ error[E0308]: mismatched types --> $DIR/if-no-match-bindings.rs:25:11 | LL | while b_mut_ref() {} - | ^^^^^^^^^^^ expected bool, found &mut bool + | ^^^^^^^^^^^ + | | + | expected bool, found &mut bool + | help: consider dereferencing the borrow: `*b_mut_ref()` | = note: expected type `bool` found type `&mut bool` From 2afd277bc3ad53ddb6064b7f2a739583e8b4820a Mon Sep 17 00:00:00 2001 From: ben Date: Tue, 1 Oct 2019 17:55:26 +1300 Subject: [PATCH 190/545] Fix calling function pointer const parameters. Also fixes inference of function pointer const parameters. --- src/librustc/ty/relate.rs | 66 +++++++++++-------- src/librustc_mir/monomorphize/collector.rs | 10 ++- .../ui/const-generics/fn-const-param-call.rs | 20 ++++++ .../const-generics/fn-const-param-call.stderr | 8 +++ .../ui/const-generics/fn-const-param-infer.rs | 26 ++++++++ .../fn-const-param-infer.stderr | 45 +++++++++++++ 6 files changed, 145 insertions(+), 30 deletions(-) create mode 100644 src/test/ui/const-generics/fn-const-param-call.rs create mode 100644 src/test/ui/const-generics/fn-const-param-call.stderr create mode 100644 src/test/ui/const-generics/fn-const-param-infer.rs create mode 100644 src/test/ui/const-generics/fn-const-param-infer.stderr diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 5489c6f5d5af..2d811a83c10c 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -8,7 +8,7 @@ use crate::hir::def_id::DefId; use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar}; +use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar, GlobalAlloc}; use std::rc::Rc; use std::iter; use rustc_target::spec::abi; @@ -561,37 +561,47 @@ pub fn super_relate_consts>( // implement both `PartialEq` and `Eq`, corresponding to // `structural_match` types. // FIXME(const_generics): check for `structural_match` synthetic attribute. - match (eagerly_eval(a), eagerly_eval(b)) { + let new_const_val = match (eagerly_eval(a), eagerly_eval(b)) { (ConstValue::Infer(_), _) | (_, ConstValue::Infer(_)) => { // The caller should handle these cases! bug!("var types encountered in super_relate_consts: {:?} {:?}", a, b) } (ConstValue::Param(a_p), ConstValue::Param(b_p)) if a_p.index == b_p.index => { - Ok(a) + return Ok(a); } (ConstValue::Placeholder(p1), ConstValue::Placeholder(p2)) if p1 == p2 => { - Ok(a) + return Ok(a); } - (a_val @ ConstValue::Scalar(Scalar::Raw { .. }), b_val @ _) - if a.ty == b.ty && a_val == b_val => - { - Ok(tcx.mk_const(ty::Const { - val: a_val, - ty: a.ty, - })) + (ConstValue::Scalar(a_val), ConstValue::Scalar(b_val)) if a.ty == b.ty => { + if a_val == b_val { + Ok(ConstValue::Scalar(a_val)) + } else if let ty::FnPtr(_) = a.ty.kind { + let alloc_map = tcx.alloc_map.lock(); + let get_fn_instance = |val: Scalar| { + let ptr = val.to_ptr().unwrap(); + if let Some(GlobalAlloc::Function(instance)) = alloc_map.get(ptr.alloc_id) { + instance + } else { + bug!("Allocation for FnPtr isn't a function"); + } + }; + let a_instance = get_fn_instance(a_val); + let b_instance = get_fn_instance(b_val); + if a_instance == b_instance { + Ok(ConstValue::Scalar(a_val)) + } else { + Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + } + } else { + Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) + } } - // FIXME(const_generics): we should either handle `Scalar::Ptr` or add a comment - // saying that we're not handling it intentionally. - (a_val @ ConstValue::Slice { .. }, b_val @ ConstValue::Slice { .. }) => { let a_bytes = get_slice_bytes(&tcx, a_val); let b_bytes = get_slice_bytes(&tcx, b_val); if a_bytes == b_bytes { - Ok(tcx.mk_const(ty::Const { - val: a_val, - ty: a.ty, - })) + Ok(a_val) } else { Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))) } @@ -602,16 +612,16 @@ pub fn super_relate_consts>( // FIXME(const_generics): this is wrong, as it is a projection (ConstValue::Unevaluated(a_def_id, a_substs), ConstValue::Unevaluated(b_def_id, b_substs)) if a_def_id == b_def_id => { - let substs = - relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; - Ok(tcx.mk_const(ty::Const { - val: ConstValue::Unevaluated(a_def_id, &substs), - ty: a.ty, - })) - } - - _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), - } + let substs = + relation.relate_with_variance(ty::Variance::Invariant, &a_substs, &b_substs)?; + Ok(ConstValue::Unevaluated(a_def_id, &substs)) + } + _ => Err(TypeError::ConstMismatch(expected_found(relation, &a, &b))), + }; + new_const_val.map(|val| tcx.mk_const(ty::Const { + val, + ty: a.ty, + })) } impl<'tcx> Relate<'tcx> for &'tcx ty::List> { diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 3ac837dd330f..a0c3ae82bcc3 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1265,7 +1265,13 @@ fn collect_const<'tcx>( ) { debug!("visiting const {:?}", constant); - match constant.val { + let substituted_constant = if let ConstValue::Param(param) = constant.val { + param_substs.const_at(param.index as usize) + } else { + constant + }; + + match substituted_constant.val { ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), ConstValue::Slice { data: alloc, start: _, end: _ } | @@ -1297,7 +1303,7 @@ fn collect_const<'tcx>( tcx.def_span(def_id), "collection encountered polymorphic constant", ), } - } + }, _ => {}, } } diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs new file mode 100644 index 000000000000..9f64d4bd086d --- /dev/null +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -0,0 +1,20 @@ +// run-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn function() -> u32 { + 17 +} + +struct Wrapper u32>; + +impl u32> Wrapper<{F}> { + fn call() -> u32 { + F() + } +} + +fn main() { + assert_eq!(Wrapper::<{function}>::call(), 17); +} \ No newline at end of file diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr new file mode 100644 index 000000000000..88d7700680b1 --- /dev/null +++ b/src/test/ui/const-generics/fn-const-param-call.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/fn-const-param-call.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs new file mode 100644 index 000000000000..ac48ccc26e13 --- /dev/null +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -0,0 +1,26 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Checked bool>; + +fn not_one(val: usize) -> bool { val != 1 } +fn not_two(val: usize) -> bool { val != 2 } + +fn generic_arg(val: T) -> bool { true } + +fn generic(val: usize) -> bool { val != 1 } + +fn main() { + let _: Option> = None; + let _: Checked<{not_one}> = Checked::<{not_one}>; + let _: Checked<{not_one}> = Checked::<{not_two}>; //~ mismatched types + + let _ = Checked::<{generic_arg}>; + let _ = Checked::<{generic_arg::}>; + let _ = Checked::<{generic_arg::}>; //~ mismatched types + + let _ = Checked::<{generic}>; //~ type annotations needed + let _ = Checked::<{generic::}>; + let _: Checked<{generic::}> = Checked::<{generic::}>; + let _: Checked<{generic::}> = Checked::<{generic::}>; //~ mismatched types +} \ No newline at end of file diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr new file mode 100644 index 000000000000..4ef55fd22d46 --- /dev/null +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -0,0 +1,45 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/fn-const-param-infer.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/fn-const-param-infer.rs:16:33 + | +LL | let _: Checked<{not_one}> = Checked::<{not_two}>; + | ^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(1).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(10).0x0) : fn(usize) -> bool` + | + = note: expected type `Checked<>` + found type `Checked<>` + +error[E0308]: mismatched types + --> $DIR/fn-const-param-infer.rs:20:24 + | +LL | let _ = Checked::<{generic_arg::}>; + | ^^^^^^^^^^^^^^^^^^ expected usize, found u32 + | + = note: expected type `fn(usize) -> bool` + found type `fn(u32) -> bool {generic_arg::}` + +error[E0282]: type annotations needed + --> $DIR/fn-const-param-infer.rs:22:24 + | +LL | let _ = Checked::<{generic}>; + | ^^^^^^^ cannot infer type for `T` + +error[E0308]: mismatched types + --> $DIR/fn-const-param-infer.rs:25:40 + | +LL | let _: Checked<{generic::}> = Checked::<{generic::}>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(7).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(20).0x0) : fn(usize) -> bool` + | + = note: expected type `Checked<>` + found type `Checked<>` + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. From a59eb6d55483e68f790c048efcfc8cdec26db32c Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 2 Oct 2019 20:29:16 +1300 Subject: [PATCH 191/545] Pretty print function pointer const values. --- src/librustc/mir/interpret/mod.rs | 8 ++++++++ src/librustc/ty/print/pretty.rs | 12 ++++++++++++ src/librustc/ty/relate.rs | 14 +++----------- src/test/ui/const-generics/fn-const-param-call.rs | 2 +- src/test/ui/const-generics/fn-const-param-infer.rs | 2 +- .../ui/const-generics/fn-const-param-infer.stderr | 4 ++-- 6 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index e925d7429fff..6c31d54e081c 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -470,6 +470,14 @@ impl<'tcx> AllocMap<'tcx> { } } + /// Panics if the `AllocId` does not refer to a function + pub fn unwrap_fn(&self, id: AllocId) -> Instance<'tcx> { + match self.get(id) { + Some(GlobalAlloc::Function(instance)) => instance, + _ => bug!("expected allocation ID {} to point to a function", id), + } + } + /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to /// call this function twice, even with the same `Allocation` will ICE the compiler. pub fn set_alloc_id_memory(&mut self, id: AllocId, mem: &'tcx Allocation) { diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 07c63a92b39d..7694d529aa3c 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -980,6 +980,18 @@ pub trait PrettyPrinter<'tcx>: return Ok(self); } } + + if let ty::FnPtr(_) = ct.ty.kind { + if let ConstValue::Scalar(Scalar::Ptr(ptr)) = ct.val { + let instance = { + let alloc_map = self.tcx().alloc_map.lock(); + alloc_map.unwrap_fn(ptr.alloc_id) + }; + p!(print_value_path(instance.def_id(), instance.substs)); + return Ok(self); + } + } + p!(write("{:?} : ", ct.val), print(ct.ty)); Ok(self) diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 2d811a83c10c..41f34703622e 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -8,7 +8,7 @@ use crate::hir::def_id::DefId; use crate::ty::subst::{GenericArg, GenericArgKind, SubstsRef}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; use crate::ty::error::{ExpectedFound, TypeError}; -use crate::mir::interpret::{ConstValue, get_slice_bytes, Scalar, GlobalAlloc}; +use crate::mir::interpret::{ConstValue, get_slice_bytes}; use std::rc::Rc; use std::iter; use rustc_target::spec::abi; @@ -577,16 +577,8 @@ pub fn super_relate_consts>( Ok(ConstValue::Scalar(a_val)) } else if let ty::FnPtr(_) = a.ty.kind { let alloc_map = tcx.alloc_map.lock(); - let get_fn_instance = |val: Scalar| { - let ptr = val.to_ptr().unwrap(); - if let Some(GlobalAlloc::Function(instance)) = alloc_map.get(ptr.alloc_id) { - instance - } else { - bug!("Allocation for FnPtr isn't a function"); - } - }; - let a_instance = get_fn_instance(a_val); - let b_instance = get_fn_instance(b_val); + let a_instance = alloc_map.unwrap_fn(a_val.to_ptr().unwrap().alloc_id); + let b_instance = alloc_map.unwrap_fn(b_val.to_ptr().unwrap().alloc_id); if a_instance == b_instance { Ok(ConstValue::Scalar(a_val)) } else { diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs index 9f64d4bd086d..1fb57897e286 100644 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -17,4 +17,4 @@ impl u32> Wrapper<{F}> { fn main() { assert_eq!(Wrapper::<{function}>::call(), 17); -} \ No newline at end of file +} diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs index ac48ccc26e13..65a1523a3547 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -23,4 +23,4 @@ fn main() { let _ = Checked::<{generic::}>; let _: Checked<{generic::}> = Checked::<{generic::}>; let _: Checked<{generic::}> = Checked::<{generic::}>; //~ mismatched types -} \ No newline at end of file +} diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 4ef55fd22d46..8598cd95b816 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -10,7 +10,7 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:16:33 | LL | let _: Checked<{not_one}> = Checked::<{not_two}>; - | ^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(1).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(10).0x0) : fn(usize) -> bool` + | ^^^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two` | = note: expected type `Checked<>` found type `Checked<>` @@ -34,7 +34,7 @@ error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:25:40 | LL | let _: Checked<{generic::}> = Checked::<{generic::}>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(AllocId(7).0x0) : fn(usize) -> bool`, found `Scalar(AllocId(20).0x0) : fn(usize) -> bool` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::`, found `generic::` | = note: expected type `Checked<>` found type `Checked<>` From cf3b561cea59f0063c9f51c9b058a6f2462bb31d Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 5 Oct 2019 10:49:24 +1300 Subject: [PATCH 192/545] Gate use of raw and function pointers in const generics behind const_compare_raw_pointers. --- src/librustc_typeck/collect.rs | 26 +++++++++++-- .../ui/const-generics/fn-const-param-call.rs | 2 +- .../const-generics/fn-const-param-call.stderr | 2 +- .../ui/const-generics/fn-const-param-infer.rs | 2 +- .../fn-const-param-infer.stderr | 2 +- .../raw-ptr-const-param-deref.rs | 19 +++++++++ .../raw-ptr-const-param-deref.stderr | 8 ++++ .../ui/const-generics/raw-ptr-const-param.rs | 9 +++++ .../const-generics/raw-ptr-const-param.stderr | 20 ++++++++++ .../feature-gate-const_generics-ptr.rs | 9 +++++ .../feature-gate-const_generics-ptr.stderr | 39 +++++++++++++++++++ 11 files changed, 131 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/const-generics/raw-ptr-const-param-deref.rs create mode 100644 src/test/ui/const-generics/raw-ptr-const-param-deref.stderr create mode 100644 src/test/ui/const-generics/raw-ptr-const-param.rs create mode 100644 src/test/ui/const-generics/raw-ptr-const-param.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs create mode 100644 src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 64eca1371447..84fb8461c6a1 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1508,9 +1508,29 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option match ¶m.kind { - hir::GenericParamKind::Type { default: Some(ref ty), .. } | - hir::GenericParamKind::Const { ref ty, .. } => { - icx.to_ty(ty) + 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_gate::emit_feature_err( + &tcx.sess.parse_sess, + sym::const_compare_raw_pointers, + hir_ty.span, + feature_gate::GateIssue::Language, + &format!( + "use of {} as const generic arguments are unstable", + unsupported_type + ), + ); + }; + } + ty } x => { if !fail { diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs index 1fb57897e286..84615386d299 100644 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -1,6 +1,6 @@ // run-pass -#![feature(const_generics)] +#![feature(const_generics, const_compare_raw_pointers)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash fn function() -> u32 { diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr index 88d7700680b1..c677d7037493 100644 --- a/src/test/ui/const-generics/fn-const-param-call.stderr +++ b/src/test/ui/const-generics/fn-const-param-call.stderr @@ -1,7 +1,7 @@ warning: the feature `const_generics` is incomplete and may cause the compiler to crash --> $DIR/fn-const-param-call.rs:3:12 | -LL | #![feature(const_generics)] +LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs index 65a1523a3547..78fb10e8cb90 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -1,4 +1,4 @@ -#![feature(const_generics)] +#![feature(const_generics, const_compare_raw_pointers)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash struct Checked bool>; diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 8598cd95b816..408786f98e1c 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -1,7 +1,7 @@ warning: the feature `const_generics` is incomplete and may cause the compiler to crash --> $DIR/fn-const-param-infer.rs:1:12 | -LL | #![feature(const_generics)] +LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs new file mode 100644 index 000000000000..672092a37793 --- /dev/null +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs @@ -0,0 +1,19 @@ +// run-pass +#![feature(const_generics, const_compare_raw_pointers)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +const A: u32 = 3; + +struct Const; + +impl Const<{P}> { + fn get() -> u32 { + unsafe { + *P + } + } +} + +fn main() { + assert_eq!(Const::<{&A as *const _}>::get(), 3) +} \ No newline at end of file diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr new file mode 100644 index 000000000000..73221596c8e8 --- /dev/null +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/raw-ptr-const-param-deref.rs:2:12 + | +LL | #![feature(const_generics, const_compare_raw_pointers)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs new file mode 100644 index 000000000000..435b6c874f4f --- /dev/null +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -0,0 +1,9 @@ +#![feature(const_generics, const_compare_raw_pointers)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Const; + +fn main() { + let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types + let _: Const<{10 as *const _}> = Const::<{10 as *const _}>; +} \ No newline at end of file diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr new file mode 100644 index 000000000000..e432afd9e9d6 --- /dev/null +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -0,0 +1,20 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/raw-ptr-const-param.rs:1:12 + | +LL | #![feature(const_generics, const_compare_raw_pointers)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0308]: mismatched types + --> $DIR/raw-ptr-const-param.rs:7:38 + | +LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(0x000000000000000f) : *const u32`, found `Scalar(0x000000000000000a) : *const u32` + | + = note: expected type `Const<>` + found type `Const<>` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs new file mode 100644 index 000000000000..db5290bdf3be --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs @@ -0,0 +1,9 @@ +struct ConstFn; +//~^ ERROR const generics are unstable +//~^^ ERROR use of function pointers as const generic arguments are unstable + +struct ConstPtr; +//~^ ERROR const generics are unstable +//~^^ ERROR use of raw pointers as const generic arguments are unstable + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr new file mode 100644 index 000000000000..0afaf4f8e49e --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr @@ -0,0 +1,39 @@ +error[E0658]: const generics are unstable + --> $DIR/feature-gate-const_generics-ptr.rs:1:22 + | +LL | struct ConstFn; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44580 + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: const generics are unstable + --> $DIR/feature-gate-const_generics-ptr.rs:5:23 + | +LL | struct ConstPtr; + | ^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/44580 + = help: add `#![feature(const_generics)]` to the crate attributes to enable + +error[E0658]: use of function pointers as const generic arguments are unstable + --> $DIR/feature-gate-const_generics-ptr.rs:1:25 + | +LL | struct ConstFn; + | ^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/53020 + = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable + +error[E0658]: use of raw pointers as const generic arguments are unstable + --> $DIR/feature-gate-const_generics-ptr.rs:5:26 + | +LL | struct ConstPtr; + | ^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/53020 + = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. From 43badf9b1d02f0e79341a93a442b0bad9312dc54 Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 5 Oct 2019 11:19:24 +1300 Subject: [PATCH 193/545] Substitute and normalize all types of consts within collect const --- src/librustc_mir/monomorphize/collector.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index a0c3ae82bcc3..1fc8a865c189 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1265,11 +1265,12 @@ fn collect_const<'tcx>( ) { debug!("visiting const {:?}", constant); - let substituted_constant = if let ConstValue::Param(param) = constant.val { - param_substs.const_at(param.index as usize) - } else { - constant - }; + let param_env = ty::ParamEnv::reveal_all(); + let substituted_constant = tcx.subst_and_normalize_erasing_regions( + param_substs, + param_env, + &constant, + ); match substituted_constant.val { ConstValue::Scalar(Scalar::Ptr(ptr)) => @@ -1281,12 +1282,6 @@ fn collect_const<'tcx>( } } ConstValue::Unevaluated(def_id, substs) => { - let param_env = ty::ParamEnv::reveal_all(); - let substs = tcx.subst_and_normalize_erasing_regions( - param_substs, - param_env, - &substs, - ); let instance = ty::Instance::resolve(tcx, param_env, def_id, From 9677cbe82e4b317c63e4459d90f7a1f2498c16ae Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 5 Oct 2019 12:57:12 +1300 Subject: [PATCH 194/545] Refactor pretty print const to use a big match statement --- src/librustc/ty/print/pretty.rs | 223 ++++++++---------- .../raw-ptr-const-param-deref.rs | 2 +- .../ui/const-generics/raw-ptr-const-param.rs | 2 +- 3 files changed, 105 insertions(+), 122 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 7694d529aa3c..8cd637468ccd 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -863,137 +863,120 @@ pub trait PrettyPrinter<'tcx>: } let u8 = self.tcx().types.u8; - if let ty::FnDef(did, substs) = ct.ty.kind { - p!(print_value_path(did, substs)); - return Ok(self); - } - if let ConstValue::Unevaluated(did, substs) = ct.val { - match self.tcx().def_kind(did) { - | Some(DefKind::Static) - | Some(DefKind::Const) - | Some(DefKind::AssocConst) => p!(print_value_path(did, substs)), - _ => if did.is_local() { - let span = self.tcx().def_span(did); - if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { - p!(write("{}", snip)) + + match (ct.val, &ct.ty.kind) { + (_, ty::FnDef(did, substs)) => p!(print_value_path(*did, substs)), + (ConstValue::Unevaluated(did, substs), _) => { + match self.tcx().def_kind(did) { + | Some(DefKind::Static) + | Some(DefKind::Const) + | Some(DefKind::AssocConst) => p!(print_value_path(did, substs)), + _ => if did.is_local() { + let span = self.tcx().def_span(did); + if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) { + p!(write("{}", snip)) + } else { + p!(write("_: "), print(ct.ty)) + } } else { p!(write("_: "), print(ct.ty)) - } + }, + } + }, + (ConstValue::Infer(..), _) => p!(write("_: "), print(ct.ty)), + (ConstValue::Param(ParamConst { name, .. }), _) => p!(write("{}", name)), + (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Bool) => + p!(write("{}", if data == 0 { "false" } else { "true" })), + (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F32)) => + p!(write("{}f32", Single::from_bits(data))), + (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Float(ast::FloatTy::F64)) => + p!(write("{}f64", Double::from_bits(data))), + (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); + + if data == max { + p!(write("std::{}::MAX", ui)) } else { - p!(write("_: "), print(ct.ty)) - }, - } - return Ok(self); - } - if let ConstValue::Infer(..) = ct.val { - p!(write("_: "), print(ct.ty)); - return Ok(self); - } - if let ConstValue::Param(ParamConst { name, .. }) = ct.val { - p!(write("{}", name)); - return Ok(self); - } - if let ConstValue::Scalar(Scalar::Raw { data, .. }) = ct.val { - match ct.ty.kind { - ty::Bool => { - p!(write("{}", if data == 0 { "false" } else { "true" })); - return Ok(self); - }, - ty::Float(ast::FloatTy::F32) => { - p!(write("{}f32", Single::from_bits(data))); - return Ok(self); - }, - ty::Float(ast::FloatTy::F64) => { - p!(write("{}f64", Double::from_bits(data))); - return Ok(self); - }, - ty::Uint(ui) => { - let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(ui)).size(); - let max = truncate(u128::max_value(), bit_size); + p!(write("{}{}", data, ui)) + }; + }, + (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Int(i)) => { + let bit_size = Integer::from_attr(&self.tcx(), SignedInt(*i)) + .size().bits() as u128; + let min = 1u128 << (bit_size - 1); + let max = min - 1; - if data == max { - p!(write("std::{}::MAX", ui)) - } else { - p!(write("{}{}", data, ui)) - }; - return Ok(self); - }, - ty::Int(i) =>{ - let bit_size = Integer::from_attr(&self.tcx(), SignedInt(i)) - .size().bits() as u128; - let min = 1u128 << (bit_size - 1); - let max = min - 1; - - let ty = self.tcx().lift(&ct.ty).unwrap(); - let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)) - .unwrap() - .size; - match data { - d if d == min => p!(write("std::{}::MIN", i)), - d if d == max => p!(write("std::{}::MAX", i)), - _ => p!(write("{}{}", sign_extend(data, size) as i128, i)) - } - return Ok(self); - }, - ty::Char => { - p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())); - return Ok(self); + let ty = self.tcx().lift(&ct.ty).unwrap(); + let size = self.tcx().layout_of(ty::ParamEnv::empty().and(ty)) + .unwrap() + .size; + match data { + d if d == min => p!(write("std::{}::MIN", i)), + d if d == max => p!(write("std::{}::MAX", i)), + _ => p!(write("{}{}", sign_extend(data, size) as i128, i)) } - _ => {}, - } - } - if let ty::Ref(_, ref_ty, _) = ct.ty.kind { - let byte_str = match (ct.val, &ref_ty.kind) { - (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { - let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); - Some(self.tcx() - .alloc_map.lock() - .unwrap_memory(ptr.alloc_id) - .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap()) - }, - (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { - // The `inspect` here is okay since we checked the bounds, and there are no - // relocations (we have an active slice reference here). We don't use this - // result to affect interpreter execution. - Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) - }, - (ConstValue::Slice { data, start, end }, ty::Str) => { - // The `inspect` here is okay since we checked the bounds, and there are no - // relocations (we have an active `str` reference here). We don't use this - // result to affect interpreter execution. - let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); - let s = ::std::str::from_utf8(slice) - .expect("non utf8 str from miri"); - p!(write("{:?}", s)); - return Ok(self); - }, - _ => None, - }; - if let Some(byte_str) = byte_str { - p!(write("b\"")); - for &c in byte_str { - for e in std::ascii::escape_default(c) { - self.write_char(e as char)?; - } - } - p!(write("\"")); - return Ok(self); - } - } - - if let ty::FnPtr(_) = ct.ty.kind { - if let ConstValue::Scalar(Scalar::Ptr(ptr)) = ct.val { + }, + (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => + p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())), + (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => { let instance = { let alloc_map = self.tcx().alloc_map.lock(); alloc_map.unwrap_fn(ptr.alloc_id) }; p!(print_value_path(instance.def_id(), instance.substs)); - return Ok(self); + }, + _ => { + let printed = if let ty::Ref(_, ref_ty, _) = ct.ty.kind { + let byte_str = match (ct.val, &ref_ty.kind) { + (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::Array(t, n)) if *t == u8 => { + let n = n.eval_usize(self.tcx(), ty::ParamEnv::empty()); + Some(self.tcx() + .alloc_map.lock() + .unwrap_memory(ptr.alloc_id) + .get_bytes(&self.tcx(), ptr, Size::from_bytes(n)).unwrap()) + }, + (ConstValue::Slice { data, start, end }, ty::Slice(t)) if *t == u8 => { + // The `inspect` here is okay since we checked the bounds, and there are + // no relocations (we have an active slice reference here). We don't use + // this result to affect interpreter execution. + Some(data.inspect_with_undef_and_ptr_outside_interpreter(start..end)) + }, + _ => None, + }; + + if let Some(byte_str) = byte_str { + p!(write("b\"")); + for &c in byte_str { + for e in std::ascii::escape_default(c) { + self.write_char(e as char)?; + } + } + p!(write("\"")); + true + } else if let (ConstValue::Slice { data, start, end }, ty::Str) = + (ct.val, &ref_ty.kind) + { + // The `inspect` here is okay since we checked the bounds, and there are no + // relocations (we have an active `str` reference here). We don't use this + // result to affect interpreter execution. + let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end); + let s = ::std::str::from_utf8(slice) + .expect("non utf8 str from miri"); + p!(write("{:?}", s)); + true + } else { + false + } + } else { + false + }; + if !printed { + // fallback + p!(write("{:?} : ", ct.val), print(ct.ty)) + } } - } - - p!(write("{:?} : ", ct.val), print(ct.ty)); - + }; Ok(self) } } diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs index 672092a37793..d26ab8be4c3f 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs @@ -16,4 +16,4 @@ impl Const<{P}> { fn main() { assert_eq!(Const::<{&A as *const _}>::get(), 3) -} \ No newline at end of file +} diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index 435b6c874f4f..f69c37fbb8f3 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -6,4 +6,4 @@ struct Const; fn main() { let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; //~ mismatched types let _: Const<{10 as *const _}> = Const::<{10 as *const _}>; -} \ No newline at end of file +} From 50ea5f45356b645e44a03d809fa86c78c264ae28 Mon Sep 17 00:00:00 2001 From: ben Date: Sat, 5 Oct 2019 14:03:41 +1300 Subject: [PATCH 195/545] Fix reify_fn_ptr test as we now pretty print const function pointers. --- src/test/mir-opt/const_prop/reify_fn_ptr.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/mir-opt/const_prop/reify_fn_ptr.rs b/src/test/mir-opt/const_prop/reify_fn_ptr.rs index e9b61690cf89..ad7f195676a6 100644 --- a/src/test/mir-opt/const_prop/reify_fn_ptr.rs +++ b/src/test/mir-opt/const_prop/reify_fn_ptr.rs @@ -16,7 +16,7 @@ fn main() { // START rustc.main.ConstProp.after.mir // bb0: { // ... -// _3 = const Scalar(AllocId(0).0x0) : fn(); +// _3 = const main; // _2 = move _3 as usize (Misc); // ... // _1 = move _2 as *const fn() (Misc); From 16b7f44b070994cc450ae7a85c3e886656dd8fb5 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Tue, 8 Oct 2019 07:55:47 +1300 Subject: [PATCH 196/545] Update feature gate error message Co-Authored-By: varkor --- src/librustc_typeck/collect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 84fb8461c6a1..6992f8c5b7f7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1524,7 +1524,7 @@ pub fn checked_type_of(tcx: TyCtxt<'_>, def_id: DefId, fail: bool) -> Option Date: Tue, 8 Oct 2019 09:46:57 -0700 Subject: [PATCH 197/545] review comments --- src/librustc/hir/mod.rs | 12 ++++-------- src/librustc_typeck/check/demand.rs | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index ead7a08c397f..1f792ecc2da9 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1555,15 +1555,11 @@ impl Expr { /// `ExprKind` of any given `Expr` for presentation don't have to care about `DropTemps` /// beyond remembering to call this function before doing analysis on it. pub fn peel_drop_temps(&self) -> &Self { - let mut base_expr = self; - loop { - match &base_expr.kind { - ExprKind::DropTemps(expr) => { - base_expr = &expr; - } - _ => return base_expr, - } + let mut expr = self; + while let ExprKind::DropTemps(inner) = &expr.kind { + expr = inner; } + expr } } diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 2b672c96dfa6..d92ea7fd49a7 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -109,13 +109,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { allow_two_phase: AllowTwoPhase) -> (Ty<'tcx>, Option>) { let expected = self.resolve_type_vars_with_obligations(expected); - let expr = expr.peel_drop_temps(); let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase) { Ok(ty) => return (ty, None), Err(e) => e }; + let expr = expr.peel_drop_temps(); let cause = self.misc(expr.span); let expr_ty = self.resolve_type_vars_with_obligations(checked_ty); let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e); From ccbf2b76a6ca8ff3ca94e1ff9858089e67f79c04 Mon Sep 17 00:00:00 2001 From: David Wood Date: Sat, 5 Oct 2019 16:55:58 +0100 Subject: [PATCH 198/545] resolve: prohibit foreign statics w/ generics This commit modifies resolve to disallow foreign statics that use parent generics. `improper_ctypes` is not written to support type parameters, as these are normally disallowed before the lint is run. Thus, type parameters in foreign statics must be prohibited before the lint. The only other case where this *could* have occured is in functions, but typeck prohibits this with a "foreign items may not have type parameters" error - a similar error did not exist for statics, because statics cannot have type parameters, but they can use any type parameters that are in scope (which isn't the case for functions). Signed-off-by: David Wood --- src/librustc_resolve/diagnostics.rs | 38 +-- src/librustc_resolve/late.rs | 249 ++++++++---------- src/librustc_resolve/lib.rs | 46 ++-- .../ui/inner-static-type-parameter.stderr | 4 +- ...sue-65025-extern-static-parent-generics.rs | 10 + ...65025-extern-static-parent-generics.stderr | 12 + ...issue-65035-static-with-parent-generics.rs | 29 ++ ...e-65035-static-with-parent-generics.stderr | 53 ++++ 8 files changed, 263 insertions(+), 178 deletions(-) create mode 100644 src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs create mode 100644 src/test/ui/resolve/issue-65025-extern-static-parent-generics.stderr create mode 100644 src/test/ui/resolve/issue-65035-static-with-parent-generics.rs create mode 100644 src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 7f819486f5bd..8aab2b97a006 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -20,7 +20,7 @@ use syntax_pos::{BytePos, Span, MultiSpan}; use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; use crate::{path_names_to_string, KNOWN_TOOLS}; -use crate::{BindingError, CrateLint, LegacyScope, Module, ModuleOrUniformRoot}; +use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot}; use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment}; type Res = def::Res; @@ -102,7 +102,7 @@ impl<'a> Resolver<'a> { &self, span: Span, resolution_error: ResolutionError<'_> ) -> DiagnosticBuilder<'_> { match resolution_error { - ResolutionError::GenericParamsFromOuterFunction(outer_res) => { + ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => { let mut err = struct_span_err!(self.session, span, E0401, @@ -148,22 +148,24 @@ 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, new_snippet)) = cm.generate_local_type_param_snippet(span) { - // Suggest the modification to the user - err.span_suggestion( - sugg_span, - sugg_msg, - new_snippet, - Applicability::MachineApplicable, - ); - } else if let Some(sp) = cm.generate_fn_name_span(span) { - err.span_label(sp, - format!("try adding a local generic parameter in this method instead")); - } else { - err.help(&format!("try using a local generic parameter instead")); + 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"); + if let Some((sugg_span, snippet)) = cm.generate_local_type_param_snippet(span) { + // Suggest the modification to the user + err.span_suggestion( + sugg_span, + sugg_msg, + snippet, + Applicability::MachineApplicable, + ); + } else if let Some(sp) = cm.generate_fn_name_span(span) { + err.span_label(sp, + format!("try adding a local generic parameter in this method instead")); + } else { + err.help(&format!("try using a local generic parameter instead")); + } } err diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 93c96b9f75ba..bb9f895c5f39 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -5,7 +5,6 @@ //! If you wonder why there's no `early.rs`, that's because it's split into three files - //! `build_reduced_graph.rs`, `macros.rs` and `resolve_imports.rs`. -use GenericParameters::*; use RibKind::*; use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; @@ -46,16 +45,6 @@ struct BindingInfo { binding_mode: BindingMode, } -#[derive(Copy, Clone)] -enum GenericParameters<'a, 'b> { - NoGenericParams, - HasGenericParams(// Type parameters. - &'b Generics, - - // The kind of the rib used for type parameters. - RibKind<'a>), -} - #[derive(Copy, Clone, PartialEq, Eq, Debug)] enum PatternSource { Match, @@ -85,6 +74,10 @@ enum PatBoundCtx { Or, } +/// Does this the item (from the item rib scope) allow generic parameters? +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +crate enum HasGenericParams { Yes, No } + /// The rib kind restricts certain accesses, /// e.g. to a `Res::Local` of an outer item. #[derive(Copy, Clone, Debug)] @@ -103,7 +96,7 @@ crate enum RibKind<'a> { FnItemRibKind, /// We passed through an item scope. Disallow upvars. - ItemRibKind, + ItemRibKind(HasGenericParams), /// We're in a constant item. Can't refer to dynamic stuff. ConstantItemRibKind, @@ -134,7 +127,7 @@ impl RibKind<'_> { | ModuleRibKind(_) | MacroDefinition(_) => false, AssocItemRibKind - | ItemRibKind + | ItemRibKind(_) | ForwardTyParamBanRibKind | TyParamAsConstParamTy => true, } @@ -406,17 +399,21 @@ impl<'a, 'tcx> Visitor<'tcx> for LateResolutionVisitor<'a, '_> { visit::walk_poly_trait_ref(self, tref, m); } fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) { - let generic_params = match foreign_item.kind { + match foreign_item.kind { ForeignItemKind::Fn(_, ref generics) => { - HasGenericParams(generics, ItemRibKind) + self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { + visit::walk_foreign_item(this, foreign_item); + }); } - ForeignItemKind::Static(..) => NoGenericParams, - ForeignItemKind::Ty => NoGenericParams, - ForeignItemKind::Macro(..) => NoGenericParams, - }; - self.with_generic_param_rib(generic_params, |this| { - visit::walk_foreign_item(this, foreign_item); - }); + ForeignItemKind::Static(..) => { + self.with_item_rib(HasGenericParams::No, |this| { + visit::walk_foreign_item(this, foreign_item); + }); + } + ForeignItemKind::Ty | ForeignItemKind::Macro(..) => { + visit::walk_foreign_item(self, foreign_item); + } + } } fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) { debug!("(resolving function) entering function"); @@ -660,7 +657,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { fn resolve_adt(&mut self, item: &Item, generics: &Generics) { debug!("resolve_adt"); self.with_current_self_item(item, |this| { - this.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { + this.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { let item_def_id = this.r.definitions.local_def_id(item.id); this.with_self_rib(Res::SelfTy(None, Some(item_def_id)), |this| { visit::walk_item(this, item); @@ -719,10 +716,8 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ItemKind::TyAlias(_, ref generics) | ItemKind::OpaqueTy(_, ref generics) | ItemKind::Fn(_, _, ref generics, _) => { - self.with_generic_param_rib( - HasGenericParams(generics, ItemRibKind), - |this| visit::walk_item(this, item) - ); + self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), + |this| visit::walk_item(this, item)); } ItemKind::Enum(_, ref generics) | @@ -740,7 +735,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ItemKind::Trait(.., ref generics, ref bounds, ref trait_items) => { // Create a new rib for the trait-wide type parameters. - self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { + self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { let local_def_id = this.r.definitions.local_def_id(item.id); this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); @@ -748,35 +743,32 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { for trait_item in trait_items { this.with_trait_items(trait_items, |this| { - let generic_params = HasGenericParams( - &trait_item.generics, - AssocItemRibKind, - ); - this.with_generic_param_rib(generic_params, |this| { - match trait_item.kind { - TraitItemKind::Const(ref ty, ref default) => { - this.visit_ty(ty); + this.with_generic_param_rib(&trait_item.generics, AssocItemRibKind, + |this| { + match trait_item.kind { + TraitItemKind::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); - }); + // 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); + }); + } } - } - TraitItemKind::Method(_, _) => { - visit::walk_trait_item(this, trait_item) - } - TraitItemKind::Type(..) => { - visit::walk_trait_item(this, trait_item) - } - TraitItemKind::Macro(_) => { - panic!("unexpanded macro in resolve!") - } - }; - }); + TraitItemKind::Method(_, _) => { + visit::walk_trait_item(this, trait_item) + } + TraitItemKind::Type(..) => { + visit::walk_trait_item(this, trait_item) + } + TraitItemKind::Macro(_) => { + panic!("unexpanded macro in resolve!") + } + }; + }); }); } }); @@ -785,7 +777,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ItemKind::TraitAlias(ref generics, ref bounds) => { // Create a new rib for the trait-wide type parameters. - self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { + self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { let local_def_id = this.r.definitions.local_def_id(item.id); this.with_self_rib(Res::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); @@ -803,7 +795,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(ref ty, ref expr) => { debug!("resolve_item ItemKind::Const"); - self.with_item_rib(|this| { + self.with_item_rib(HasGenericParams::No, |this| { this.visit_ty(ty); this.with_constant_rib(|this| { this.visit_expr(expr); @@ -824,91 +816,75 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { } } - fn with_generic_param_rib<'c, F>(&'c mut self, generic_params: GenericParameters<'a, 'c>, f: F) + fn with_generic_param_rib<'c, F>(&'c mut self, generics: &'c Generics, kind: RibKind<'a>, f: F) where F: FnOnce(&mut Self) { debug!("with_generic_param_rib"); - match generic_params { - HasGenericParams(generics, rib_kind) => { - let mut function_type_rib = Rib::new(rib_kind); - let mut function_value_rib = Rib::new(rib_kind); - let mut seen_bindings = FxHashMap::default(); - // We also can't shadow bindings from the parent item - if let AssocItemRibKind = rib_kind { - let mut add_bindings_for_ns = |ns| { - let parent_rib = self.ribs[ns].iter() - .rfind(|rib| if let ItemRibKind = rib.kind { true } else { false }) - .expect("associated item outside of an item"); - seen_bindings.extend( - parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)), - ); - }; - add_bindings_for_ns(ValueNS); - add_bindings_for_ns(TypeNS); - } - for param in &generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => {} - GenericParamKind::Type { .. } => { - let ident = param.ident.modern(); - debug!("with_generic_param_rib: {}", param.id); + let mut function_type_rib = Rib::new(kind); + let mut function_value_rib = Rib::new(kind); + let mut seen_bindings = FxHashMap::default(); - if seen_bindings.contains_key(&ident) { - let span = seen_bindings.get(&ident).unwrap(); - let err = ResolutionError::NameAlreadyUsedInParameterList( - ident.name, - *span, - ); - self.r.report_error(param.ident.span, err); - } - seen_bindings.entry(ident).or_insert(param.ident.span); + // We also can't shadow bindings from the parent item + if let AssocItemRibKind = kind { + let mut add_bindings_for_ns = |ns| { + let parent_rib = self.ribs[ns].iter() + .rfind(|r| if let ItemRibKind(_) = r.kind { true } else { false }) + .expect("associated item outside of an item"); + seen_bindings.extend( + parent_rib.bindings.iter().map(|(ident, _)| (*ident, ident.span)), + ); + }; + add_bindings_for_ns(ValueNS); + add_bindings_for_ns(TypeNS); + } - // Plain insert (no renaming). - let res = Res::Def( - DefKind::TyParam, - self.r.definitions.local_def_id(param.id), - ); - function_type_rib.bindings.insert(ident, res); - self.r.record_partial_res(param.id, PartialRes::new(res)); - } - GenericParamKind::Const { .. } => { - let ident = param.ident.modern(); - debug!("with_generic_param_rib: {}", param.id); - - if seen_bindings.contains_key(&ident) { - let span = seen_bindings.get(&ident).unwrap(); - let err = ResolutionError::NameAlreadyUsedInParameterList( - ident.name, - *span, - ); - self.r.report_error(param.ident.span, err); - } - seen_bindings.entry(ident).or_insert(param.ident.span); - - let res = Res::Def( - DefKind::ConstParam, - self.r.definitions.local_def_id(param.id), - ); - function_value_rib.bindings.insert(ident, res); - self.r.record_partial_res(param.id, PartialRes::new(res)); - } - } - } - self.ribs[ValueNS].push(function_value_rib); - self.ribs[TypeNS].push(function_type_rib); + for param in &generics.params { + if let GenericParamKind::Lifetime { .. } = param.kind { + continue; } - NoGenericParams => { - // Nothing to do. + let def_kind = match param.kind { + GenericParamKind::Type { .. } => DefKind::TyParam, + GenericParamKind::Const { .. } => DefKind::ConstParam, + _ => unreachable!(), + }; + + let ident = param.ident.modern(); + debug!("with_generic_param_rib: {}", param.id); + + if seen_bindings.contains_key(&ident) { + let span = seen_bindings.get(&ident).unwrap(); + let err = ResolutionError::NameAlreadyUsedInParameterList( + ident.name, + *span, + ); + self.r.report_error(param.ident.span, err); + } + seen_bindings.entry(ident).or_insert(param.ident.span); + + // Plain insert (no renaming). + let res = Res::Def(def_kind, self.r.definitions.local_def_id(param.id)); + + match param.kind { + GenericParamKind::Type { .. } => { + function_type_rib.bindings.insert(ident, res); + self.r.record_partial_res(param.id, PartialRes::new(res)); + } + GenericParamKind::Const { .. } => { + function_value_rib.bindings.insert(ident, res); + self.r.record_partial_res(param.id, PartialRes::new(res)); + } + _ => unreachable!(), } } + self.ribs[ValueNS].push(function_value_rib); + self.ribs[TypeNS].push(function_type_rib); + f(self); - if let HasGenericParams(..) = generic_params { - self.ribs[TypeNS].pop(); - self.ribs[ValueNS].pop(); - } + self.ribs[TypeNS].pop(); + self.ribs[ValueNS].pop(); } fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) { @@ -917,8 +893,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { self.label_ribs.pop(); } - fn with_item_rib(&mut self, f: impl FnOnce(&mut Self)) { - self.with_rib(ValueNS, ItemRibKind, |this| this.with_rib(TypeNS, ItemRibKind, f)) + fn with_item_rib(&mut self, has_generic_params: HasGenericParams, f: impl FnOnce(&mut Self)) { + let kind = ItemRibKind(has_generic_params); + self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f)) } fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) { @@ -1023,7 +1000,7 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { impl_items: &[ImplItem]) { debug!("resolve_implementation"); // If applicable, create a rib for the type parameters. - self.with_generic_param_rib(HasGenericParams(generics, ItemRibKind), |this| { + self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { // Dummy self type for better errors if `Self` is used in the trait path. this.with_self_rib(Res::SelfTy(None, None), |this| { // Resolve the trait reference, if necessary. @@ -1044,9 +1021,9 @@ impl<'a, 'b> LateResolutionVisitor<'a, '_> { 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. - let generic_params = HasGenericParams(&impl_item.generics, - AssocItemRibKind); - this.with_generic_param_rib(generic_params, |this| { + this.with_generic_param_rib(&impl_item.generics, + AssocItemRibKind, + |this| { use crate::ResolutionError::*; match impl_item.kind { ImplItemKind::Const(..) => { diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e7292b52ab3e..acad86c2de80 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -61,7 +61,7 @@ use rustc_data_structures::sync::Lrc; use diagnostics::{Suggestion, ImportSuggestion}; use diagnostics::{find_span_of_binding_until_next_binding, extend_span_to_previous_binding}; -use late::{PathSource, Rib, RibKind::*}; +use late::{HasGenericParams, PathSource, Rib, RibKind::*}; use resolve_imports::{ImportDirective, ImportDirectiveSubclass, NameResolution, ImportResolver}; use macros::{LegacyBinding, LegacyScope}; @@ -178,7 +178,7 @@ impl Ord for BindingError { enum ResolutionError<'a> { /// Error E0401: can't use type or const parameters from outer function. - GenericParamsFromOuterFunction(Res), + GenericParamsFromOuterFunction(Res, HasGenericParams), /// Error E0403: the name is already used for a type or const parameter in this generic /// parameter list. NameAlreadyUsedInParameterList(Name, Span), @@ -2167,7 +2167,7 @@ impl<'a> Resolver<'a> { ForwardTyParamBanRibKind | TyParamAsConstParamTy => { // Nothing to do. Continue. } - ItemRibKind | FnItemRibKind | AssocItemRibKind => { + ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => { // This was an attempt to access an upvar inside a // named function item. This is not allowed, so we // report an error. @@ -2195,22 +2195,23 @@ impl<'a> Resolver<'a> { } Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { for rib in ribs { - match rib.kind { + let has_generic_params = match rib.kind { NormalRibKind | AssocItemRibKind | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind | ConstantItemRibKind | TyParamAsConstParamTy => { // Nothing to do. Continue. + continue; } - ItemRibKind | FnItemRibKind => { - // This was an attempt to use a type parameter outside its scope. - if record_used { - self.report_error( - span, ResolutionError::GenericParamsFromOuterFunction(res) - ); - } - return Res::Err; - } + // This was an attempt to use a type parameter outside its scope. + ItemRibKind(has_generic_params) => has_generic_params, + FnItemRibKind => HasGenericParams::Yes, + }; + + if record_used { + self.report_error(span, ResolutionError::GenericParamsFromOuterFunction( + res, has_generic_params)); } + return Res::Err; } } Res::Def(DefKind::ConstParam, _) => { @@ -2222,15 +2223,18 @@ impl<'a> Resolver<'a> { ribs.next(); } for rib in ribs { - if let ItemRibKind | FnItemRibKind = rib.kind { - // This was an attempt to use a const parameter outside its scope. - if record_used { - self.report_error( - span, ResolutionError::GenericParamsFromOuterFunction(res) - ); - } - return Res::Err; + let has_generic_params = match rib.kind { + ItemRibKind(has_generic_params) => has_generic_params, + FnItemRibKind => HasGenericParams::Yes, + _ => continue, + }; + + // This was an attempt to use a const parameter outside its scope. + if record_used { + self.report_error(span, ResolutionError::GenericParamsFromOuterFunction( + res, has_generic_params)); } + return Res::Err; } } _ => {} diff --git a/src/test/ui/inner-static-type-parameter.stderr b/src/test/ui/inner-static-type-parameter.stderr index dfc663e4a79f..1e74445af55c 100644 --- a/src/test/ui/inner-static-type-parameter.stderr +++ b/src/test/ui/inner-static-type-parameter.stderr @@ -2,9 +2,7 @@ error[E0401]: can't use generic parameters from outer function --> $DIR/inner-static-type-parameter.rs:6:19 | LL | fn foo() { - | --- - type parameter from outer function - | | - | try adding a local generic parameter in this method instead + | - type parameter from outer function LL | static a: Bar = Bar::What; | ^ use of generic parameter from outer function diff --git a/src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs b/src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs new file mode 100644 index 000000000000..ce45f630e48a --- /dev/null +++ b/src/test/ui/resolve/issue-65025-extern-static-parent-generics.rs @@ -0,0 +1,10 @@ +unsafe fn foo() { + extern "C" { + static baz: *const A; + //~^ ERROR can't use generic parameters from outer function + } + + let bar: *const u64 = core::mem::transmute(&baz); +} + +fn main() { } diff --git a/src/test/ui/resolve/issue-65025-extern-static-parent-generics.stderr b/src/test/ui/resolve/issue-65025-extern-static-parent-generics.stderr new file mode 100644 index 000000000000..6bbf76dd1fbb --- /dev/null +++ b/src/test/ui/resolve/issue-65025-extern-static-parent-generics.stderr @@ -0,0 +1,12 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65025-extern-static-parent-generics.rs:3:28 + | +LL | unsafe fn foo() { + | - type parameter from outer function +LL | extern "C" { +LL | static baz: *const A; + | ^ use of generic parameter from outer function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0401`. diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs b/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs new file mode 100644 index 000000000000..63d3431ec9b2 --- /dev/null +++ b/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs @@ -0,0 +1,29 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn f() { + extern "C" { + static a: *const T; + //~^ ERROR can't use generic parameters from outer function + } +} + +fn g() { + static a: *const T = Default::default(); + //~^ ERROR can't use generic parameters from outer function +} + +fn h() { + extern "C" { + static a: [u8; N]; + //~^ ERROR can't use generic parameters from outer function + } +} + +fn i() { + static a: [u8; N] = [0; N]; + //~^ ERROR can't use generic parameters from outer function + //~^^ ERROR can't use generic parameters from outer function +} + +fn main() {} diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr new file mode 100644 index 000000000000..82e2aa2db8e2 --- /dev/null +++ b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -0,0 +1,53 @@ +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:6:26 + | +LL | fn f() { + | - type parameter from outer function +LL | extern "C" { +LL | static a: *const T; + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:12:22 + | +LL | fn g() { + | - type parameter from outer function +LL | static a: *const T = Default::default(); + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:18:24 + | +LL | fn h() { + | - const parameter from outer function +LL | extern "C" { +LL | static a: [u8; N]; + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:24:20 + | +LL | fn i() { + | - const parameter from outer function +LL | static a: [u8; N] = [0; N]; + | ^ use of generic parameter from outer function + +error[E0401]: can't use generic parameters from outer function + --> $DIR/issue-65035-static-with-parent-generics.rs:24:29 + | +LL | fn i() { + | - const parameter from outer function +LL | static a: [u8; N] = [0; N]; + | ^ use of generic parameter from outer function + +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-65035-static-with-parent-generics.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0401`. From 5986fe24bd40162f11aca0327d2ecd62973c354d Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 9 Oct 2019 06:58:39 +1300 Subject: [PATCH 199/545] Update ui tests --- src/test/ui/const-generics/fn-const-param-infer.stderr | 8 ++++---- src/test/ui/const-generics/raw-ptr-const-param.stderr | 4 ++-- .../ui/feature-gates/feature-gate-const_generics-ptr.rs | 4 ++-- .../feature-gates/feature-gate-const_generics-ptr.stderr | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 408786f98e1c..de0916b26bfe 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -12,8 +12,8 @@ error[E0308]: mismatched types LL | let _: Checked<{not_one}> = Checked::<{not_two}>; | ^^^^^^^^^^^^^^^^^^^^ expected `not_one`, found `not_two` | - = note: expected type `Checked<>` - found type `Checked<>` + = note: expected type `Checked` + found type `Checked` error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:20:24 @@ -36,8 +36,8 @@ error[E0308]: mismatched types LL | let _: Checked<{generic::}> = Checked::<{generic::}>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `generic::`, found `generic::` | - = note: expected type `Checked<>` - found type `Checked<>` + = note: expected type `Checked>` + found type `Checked>` error: aborting due to 4 previous errors diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index e432afd9e9d6..31db64d30a7d 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -12,8 +12,8 @@ error[E0308]: mismatched types LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(0x000000000000000f) : *const u32`, found `Scalar(0x000000000000000a) : *const u32` | - = note: expected type `Const<>` - found type `Const<>` + = note: expected type `Const` + found type `Const` error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs index db5290bdf3be..1ab11ce3b442 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.rs @@ -1,9 +1,9 @@ struct ConstFn; //~^ ERROR const generics are unstable -//~^^ ERROR use of function pointers as const generic arguments are unstable +//~^^ ERROR using function pointers as const generic parameters is unstable struct ConstPtr; //~^ ERROR const generics are unstable -//~^^ ERROR use of raw pointers as const generic arguments are unstable +//~^^ ERROR using raw pointers as const generic parameters is unstable fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr index 0afaf4f8e49e..935f84b9163d 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr @@ -16,7 +16,7 @@ LL | struct ConstPtr; = note: for more information, see https://github.com/rust-lang/rust/issues/44580 = help: add `#![feature(const_generics)]` to the crate attributes to enable -error[E0658]: use of function pointers as const generic arguments are unstable +error[E0658]: using function pointers as const generic parameters is unstable --> $DIR/feature-gate-const_generics-ptr.rs:1:25 | LL | struct ConstFn; @@ -25,7 +25,7 @@ LL | struct ConstFn; = note: for more information, see https://github.com/rust-lang/rust/issues/53020 = help: add `#![feature(const_compare_raw_pointers)]` to the crate attributes to enable -error[E0658]: use of raw pointers as const generic arguments are unstable +error[E0658]: using raw pointers as const generic parameters is unstable --> $DIR/feature-gate-const_generics-ptr.rs:5:26 | LL | struct ConstPtr; From dfe76a10935cf93fdc72abc47167691b7aa44a7f Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 8 Oct 2019 17:09:23 +0100 Subject: [PATCH 200/545] Split non-CAS atomic support off into target_has_atomic_load_store --- src/liballoc/lib.rs | 2 +- src/libcore/sync/atomic.rs | 162 ++++++++++-------- src/librustc/session/config.rs | 25 +-- src/libstd/panic.rs | 32 ++-- src/libsyntax/feature_gate/builtin_attrs.rs | 1 + src/libsyntax_pos/symbol.rs | 1 + .../target-without-atomic-cas/Makefile | 2 +- 7 files changed, 127 insertions(+), 98 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 247cd9a02016..2e3b8f25adf3 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -154,7 +154,7 @@ mod boxed { #[cfg(test)] mod tests; pub mod collections; -#[cfg(all(target_has_atomic = "ptr", target_has_atomic = "cas"))] +#[cfg(target_has_atomic = "ptr")] pub mod sync; pub mod rc; pub mod raw_vec; diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index c9ccef972c2b..19b13852c78a 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -113,8 +113,8 @@ //! ``` #![stable(feature = "rust1", since = "1.0.0")] -#![cfg_attr(not(target_has_atomic = "8"), allow(dead_code))] -#![cfg_attr(not(target_has_atomic = "8"), allow(unused_imports))] +#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(dead_code))] +#![cfg_attr(not(target_has_atomic_load_store = "8"), allow(unused_imports))] use self::Ordering::*; @@ -160,14 +160,14 @@ pub fn spin_loop_hint() { /// This type has the same in-memory representation as a [`bool`]. /// /// [`bool`]: ../../../std/primitive.bool.html -#[cfg(target_has_atomic = "8")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] #[stable(feature = "rust1", since = "1.0.0")] #[repr(C, align(1))] pub struct AtomicBool { v: UnsafeCell, } -#[cfg(target_has_atomic = "8")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] #[stable(feature = "rust1", since = "1.0.0")] impl Default for AtomicBool { /// Creates an `AtomicBool` initialized to `false`. @@ -177,14 +177,14 @@ impl Default for AtomicBool { } // Send is implicitly implemented for AtomicBool. -#[cfg(target_has_atomic = "8")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for AtomicBool {} /// A raw pointer type which can be safely shared between threads. /// /// This type has the same in-memory representation as a `*mut T`. -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(target_pointer_width = "16", repr(C, align(2)))] #[cfg_attr(target_pointer_width = "32", repr(C, align(4)))] @@ -193,7 +193,7 @@ pub struct AtomicPtr { p: UnsafeCell<*mut T>, } -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[stable(feature = "rust1", since = "1.0.0")] impl Default for AtomicPtr { /// Creates a null `AtomicPtr`. @@ -202,10 +202,10 @@ impl Default for AtomicPtr { } } -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for AtomicPtr {} -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for AtomicPtr {} @@ -304,7 +304,7 @@ pub enum Ordering { /// An [`AtomicBool`] initialized to `false`. /// /// [`AtomicBool`]: struct.AtomicBool.html -#[cfg(target_has_atomic = "8")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] #[stable(feature = "rust1", since = "1.0.0")] #[rustc_deprecated( since = "1.34.0", @@ -313,7 +313,7 @@ pub enum Ordering { )] pub const ATOMIC_BOOL_INIT: AtomicBool = AtomicBool::new(false); -#[cfg(target_has_atomic = "8")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] impl AtomicBool { /// Creates a new `AtomicBool`. /// @@ -462,7 +462,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "8")] pub fn swap(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_swap(self.v.get(), val as u8, order) != 0 } } @@ -500,7 +500,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "8")] pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -551,7 +551,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "8")] pub fn compare_exchange(&self, current: bool, new: bool, @@ -607,7 +607,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "8")] pub fn compare_exchange_weak(&self, current: bool, new: bool, @@ -658,7 +658,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "8")] pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_and(self.v.get(), val as u8, order) != 0 } } @@ -700,7 +700,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "8")] pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { // We can't use atomic_nand here because it can result in a bool with // an invalid value. This happens because the atomic operation is done @@ -753,7 +753,7 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "8")] pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_or(self.v.get(), val as u8, order) != 0 } } @@ -794,13 +794,13 @@ impl AtomicBool { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "8")] pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool { unsafe { atomic_xor(self.v.get(), val as u8, order) != 0 } } } -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] impl AtomicPtr { /// Creates a new `AtomicPtr`. /// @@ -951,7 +951,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "ptr")] pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T } } @@ -987,7 +987,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "ptr")] pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T { match self.compare_exchange(current, new, order, strongest_failure_ordering(order)) { Ok(x) => x, @@ -1029,7 +1029,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "ptr")] pub fn compare_exchange(&self, current: *mut T, new: *mut T, @@ -1089,7 +1089,7 @@ impl AtomicPtr { /// ``` #[inline] #[stable(feature = "extended_compare_and_swap", since = "1.10.0")] - #[cfg(target_has_atomic = "cas")] + #[cfg(target_has_atomic = "ptr")] pub fn compare_exchange_weak(&self, current: *mut T, new: *mut T, @@ -1110,7 +1110,7 @@ impl AtomicPtr { } } -#[cfg(target_has_atomic = "8")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] #[stable(feature = "atomic_bool_from", since = "1.24.0")] impl From for AtomicBool { /// Converts a `bool` into an `AtomicBool`. @@ -1126,16 +1126,17 @@ impl From for AtomicBool { fn from(b: bool) -> Self { Self::new(b) } } -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[stable(feature = "atomic_from", since = "1.23.0")] impl From<*mut T> for AtomicPtr { #[inline] fn from(p: *mut T) -> Self { Self::new(p) } } -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] macro_rules! atomic_int { - ($stable:meta, + ($cfg_cas:meta, + $stable:meta, $stable_cxchg:meta, $stable_debug:meta, $stable_access:meta, @@ -1356,7 +1357,7 @@ assert_eq!(some_var.swap(10, Ordering::Relaxed), 5); ```"), #[inline] #[$stable] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_swap(self.v.get(), val, order) } } @@ -1396,7 +1397,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[$stable] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn compare_and_swap(&self, current: $int_type, new: $int_type, @@ -1454,7 +1455,7 @@ assert_eq!(some_var.load(Ordering::Relaxed), 10); ```"), #[inline] #[$stable_cxchg] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn compare_exchange(&self, current: $int_type, new: $int_type, @@ -1506,7 +1507,7 @@ loop { ```"), #[inline] #[$stable_cxchg] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn compare_exchange_weak(&self, current: $int_type, new: $int_type, @@ -1544,7 +1545,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[$stable] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_add(self.v.get(), val, order) } } @@ -1576,7 +1577,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 10); ```"), #[inline] #[$stable] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_sub(self.v.get(), val, order) } } @@ -1611,7 +1612,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b100001); ```"), #[inline] #[$stable] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_and(self.v.get(), val, order) } } @@ -1647,7 +1648,7 @@ assert_eq!(foo.load(Ordering::SeqCst), !(0x13 & 0x31)); ```"), #[inline] #[$stable_nand] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_nand(self.v.get(), val, order) } } @@ -1682,7 +1683,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b111111); ```"), #[inline] #[$stable] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_or(self.v.get(), val, order) } } @@ -1717,7 +1718,7 @@ assert_eq!(foo.load(Ordering::SeqCst), 0b011110); ```"), #[inline] #[$stable] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { atomic_xor(self.v.get(), val, order) } } @@ -1767,7 +1768,7 @@ assert_eq!(x.load(Ordering::SeqCst), 9); #[unstable(feature = "no_more_cas", reason = "no more CAS loops in user code", issue = "48655")] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn fetch_update(&self, mut f: F, fetch_order: Ordering, @@ -1828,7 +1829,7 @@ assert!(max_foo == 42); #[unstable(feature = "atomic_min_max", reason = "easier and faster min/max than writing manual CAS loop", issue = "48655")] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { $max_fn(self.v.get(), val, order) } } @@ -1880,7 +1881,7 @@ assert_eq!(min_foo, 12); #[unstable(feature = "atomic_min_max", reason = "easier and faster min/max than writing manual CAS loop", issue = "48655")] - #[cfg(target_has_atomic = "cas")] + #[$cfg_cas] pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { unsafe { $min_fn(self.v.get(), val, order) } } @@ -1890,8 +1891,9 @@ assert_eq!(min_foo, 12); } } -#[cfg(target_has_atomic = "8")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] atomic_int! { + cfg(target_has_atomic = "8"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1906,8 +1908,9 @@ atomic_int! { "AtomicI8::new(0)", i8 AtomicI8 ATOMIC_I8_INIT } -#[cfg(target_has_atomic = "8")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] atomic_int! { + cfg(target_has_atomic = "8"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1922,8 +1925,9 @@ atomic_int! { "AtomicU8::new(0)", u8 AtomicU8 ATOMIC_U8_INIT } -#[cfg(target_has_atomic = "16")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))] atomic_int! { + cfg(target_has_atomic = "16"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1938,8 +1942,9 @@ atomic_int! { "AtomicI16::new(0)", i16 AtomicI16 ATOMIC_I16_INIT } -#[cfg(target_has_atomic = "16")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "16"))] atomic_int! { + cfg(target_has_atomic = "16"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1954,8 +1959,9 @@ atomic_int! { "AtomicU16::new(0)", u16 AtomicU16 ATOMIC_U16_INIT } -#[cfg(target_has_atomic = "32")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))] atomic_int! { + cfg(target_has_atomic = "32"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1970,8 +1976,9 @@ atomic_int! { "AtomicI32::new(0)", i32 AtomicI32 ATOMIC_I32_INIT } -#[cfg(target_has_atomic = "32")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "32"))] atomic_int! { + cfg(target_has_atomic = "32"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -1986,8 +1993,12 @@ atomic_int! { "AtomicU32::new(0)", u32 AtomicU32 ATOMIC_U32_INIT } -#[cfg(target_has_atomic = "64")] +#[cfg(any( + all(bootstrap, target_has_atomic = "64"), + target_has_atomic_load_store = "64" +))] atomic_int! { + cfg(target_has_atomic = "64"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -2002,8 +2013,12 @@ atomic_int! { "AtomicI64::new(0)", i64 AtomicI64 ATOMIC_I64_INIT } -#[cfg(target_has_atomic = "64")] +#[cfg(any( + all(bootstrap, target_has_atomic = "64"), + target_has_atomic_load_store = "64" +))] atomic_int! { + cfg(target_has_atomic = "64"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), stable(feature = "integer_atomics_stable", since = "1.34.0"), @@ -2018,8 +2033,9 @@ atomic_int! { "AtomicU64::new(0)", u64 AtomicU64 ATOMIC_U64_INIT } -#[cfg(target_has_atomic = "128")] +#[cfg(target_has_atomic_load_store = "128")] atomic_int! { + cfg(target_has_atomic = "128"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), @@ -2034,8 +2050,9 @@ atomic_int! { "AtomicI128::new(0)", i128 AtomicI128 ATOMIC_I128_INIT } -#[cfg(target_has_atomic = "128")] +#[cfg(target_has_atomic_load_store = "128")] atomic_int! { + cfg(target_has_atomic = "128"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), unstable(feature = "integer_atomics", issue = "32976"), @@ -2050,20 +2067,24 @@ atomic_int! { "AtomicU128::new(0)", u128 AtomicU128 ATOMIC_U128_INIT } +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[cfg(target_pointer_width = "16")] macro_rules! ptr_width { () => { 2 } } +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[cfg(target_pointer_width = "32")] macro_rules! ptr_width { () => { 4 } } +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[cfg(target_pointer_width = "64")] macro_rules! ptr_width { () => { 8 } } -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] atomic_int!{ + cfg(target_has_atomic = "ptr"), stable(feature = "rust1", since = "1.0.0"), stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), @@ -2078,8 +2099,9 @@ atomic_int!{ "AtomicIsize::new(0)", isize AtomicIsize ATOMIC_ISIZE_INIT } -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] atomic_int!{ + cfg(target_has_atomic = "ptr"), stable(feature = "rust1", since = "1.0.0"), stable(feature = "extended_compare_and_swap", since = "1.10.0"), stable(feature = "atomic_debug", since = "1.3.0"), @@ -2096,7 +2118,7 @@ atomic_int!{ } #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] fn strongest_failure_ordering(order: Ordering) -> Ordering { match order { Release => Relaxed, @@ -2130,7 +2152,7 @@ unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xchg_acq(dst, val), @@ -2143,7 +2165,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 = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xadd_acq(dst, val), @@ -2156,7 +2178,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 = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xsub_acq(dst, val), @@ -2168,7 +2190,7 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_compare_exchange(dst: *mut T, old: T, new: T, @@ -2193,7 +2215,7 @@ unsafe fn atomic_compare_exchange(dst: *mut T, } #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_compare_exchange_weak(dst: *mut T, old: T, new: T, @@ -2218,7 +2240,7 @@ unsafe fn atomic_compare_exchange_weak(dst: *mut T, } #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_and_acq(dst, val), @@ -2230,7 +2252,7 @@ unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_nand_acq(dst, val), @@ -2242,7 +2264,7 @@ unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_or_acq(dst, val), @@ -2254,7 +2276,7 @@ unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { } #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xor_acq(dst, val), @@ -2267,7 +2289,7 @@ unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (signed comparison) #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_max_acq(dst, val), @@ -2280,7 +2302,7 @@ unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (signed comparison) #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_min_acq(dst, val), @@ -2293,7 +2315,7 @@ unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (signed comparison) #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_umax_acq(dst, val), @@ -2306,7 +2328,7 @@ unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (signed comparison) #[inline] -#[cfg(target_has_atomic = "cas")] +#[cfg(target_has_atomic = "8")] unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_umin_acq(dst, val), @@ -2504,7 +2526,7 @@ pub fn compiler_fence(order: Ordering) { } -#[cfg(target_has_atomic = "8")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "8"))] #[stable(feature = "atomic_debug", since = "1.3.0")] impl fmt::Debug for AtomicBool { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -2512,7 +2534,7 @@ impl fmt::Debug for AtomicBool { } } -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[stable(feature = "atomic_debug", since = "1.3.0")] impl fmt::Debug for AtomicPtr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -2520,7 +2542,7 @@ impl fmt::Debug for AtomicPtr { } } -#[cfg(target_has_atomic = "ptr")] +#[cfg(any(bootstrap, target_has_atomic_load_store = "ptr"))] #[stable(feature = "atomic_pointer", since = "1.24.0")] impl fmt::Pointer for AtomicPtr { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index b48353e73308..e1b8e5fa1c74 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1514,22 +1514,25 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig { } for &i in &[8, 16, 32, 64, 128] { if i >= min_atomic_width && i <= max_atomic_width { - let s = i.to_string(); - ret.insert(( - sym::target_has_atomic, - Some(Symbol::intern(&s)), - )); - if &s == wordsz { + let mut insert_atomic = |s| { ret.insert(( - sym::target_has_atomic, - Some(Symbol::intern("ptr")), + sym::target_has_atomic_load_store, + Some(Symbol::intern(s)), )); + if atomic_cas { + ret.insert(( + sym::target_has_atomic, + Some(Symbol::intern(s)) + )); + } + }; + let s = i.to_string(); + insert_atomic(&s); + if &s == wordsz { + insert_atomic("ptr"); } } } - if atomic_cas { - ret.insert((sym::target_has_atomic, Some(Symbol::intern("cas")))); - } if sess.opts.debug_assertions { ret.insert((Symbol::intern("debug_assertions"), None)); } diff --git a/src/libstd/panic.rs b/src/libstd/panic.rs index 1d4fd98dd754..24c693790e84 100644 --- a/src/libstd/panic.rs +++ b/src/libstd/panic.rs @@ -12,7 +12,9 @@ use crate::ops::{Deref, DerefMut}; use crate::panicking; use crate::ptr::{Unique, NonNull}; use crate::rc::Rc; -use crate::sync::{Arc, Mutex, RwLock, atomic}; +use crate::sync::{Arc, Mutex, RwLock}; +#[cfg(not(bootstrap))] +use crate::sync::atomic; use crate::task::{Context, Poll}; use crate::thread::Result; @@ -240,49 +242,49 @@ impl RefUnwindSafe for Mutex {} #[stable(feature = "unwind_safe_lock_refs", since = "1.12.0")] impl RefUnwindSafe for RwLock {} -#[cfg(target_has_atomic = "ptr")] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] impl RefUnwindSafe for atomic::AtomicIsize {} -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic_load_store = "8")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI8 {} -#[cfg(target_has_atomic = "16")] +#[cfg(target_has_atomic_load_store = "16")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI16 {} -#[cfg(target_has_atomic = "32")] +#[cfg(target_has_atomic_load_store = "32")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI32 {} -#[cfg(target_has_atomic = "64")] +#[cfg(target_has_atomic_load_store = "64")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI64 {} -#[cfg(target_has_atomic = "128")] +#[cfg(target_has_atomic_load_store = "128")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicI128 {} -#[cfg(target_has_atomic = "ptr")] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] impl RefUnwindSafe for atomic::AtomicUsize {} -#[cfg(target_has_atomic = "8")] +#[cfg(target_hastarget_has_atomic_load_store_atomic = "8")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU8 {} -#[cfg(target_has_atomic = "16")] +#[cfg(target_has_atomic_load_store = "16")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU16 {} -#[cfg(target_has_atomic = "32")] +#[cfg(target_has_atomic_load_store = "32")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU32 {} -#[cfg(target_has_atomic = "64")] +#[cfg(target_has_atomic_load_store = "64")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU64 {} -#[cfg(target_has_atomic = "128")] +#[cfg(target_has_atomic_load_store = "128")] #[unstable(feature = "integer_atomics", issue = "32976")] impl RefUnwindSafe for atomic::AtomicU128 {} -#[cfg(target_has_atomic = "8")] +#[cfg(target_has_atomic_load_store = "8")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] impl RefUnwindSafe for atomic::AtomicBool {} -#[cfg(target_has_atomic = "ptr")] +#[cfg(target_has_atomic_load_store = "ptr")] #[stable(feature = "unwind_safe_atomic_refs", since = "1.14.0")] impl RefUnwindSafe for atomic::AtomicPtr {} diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index c12d0ce06ffe..b611351d5c4e 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -29,6 +29,7 @@ const GATED_CFGS: &[(Symbol, Symbol, GateFn)] = &[ // (name in cfg, feature, function to check if the feature is enabled) (sym::target_thread_local, sym::cfg_target_thread_local, cfg_fn!(cfg_target_thread_local)), (sym::target_has_atomic, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), + (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)), (sym::rustdoc, sym::doc_cfg, cfg_fn!(doc_cfg)), (sym::doctest, sym::cfg_doctest, cfg_fn!(cfg_doctest)), ]; diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index c7230d5ca152..5b060828812e 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -658,6 +658,7 @@ symbols! { suggestion, target_feature, target_has_atomic, + target_has_atomic_load_store, target_thread_local, task, tbm_target_feature, diff --git a/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile b/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile index c2eb4caea263..9868fc1d4170 100644 --- a/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile +++ b/src/test/run-make-fulldeps/target-without-atomic-cas/Makefile @@ -2,4 +2,4 @@ # The target used below doesn't support atomic CAS operations. Verify that's the case all: - $(RUSTC) --print cfg --target thumbv6m-none-eabi | $(CGREP) -v 'target_has_atomic="cas"' + $(RUSTC) --print cfg --target thumbv6m-none-eabi | $(CGREP) -v 'target_has_atomic="ptr"' From 2c81089425660c78c066c650c44aea25c5d58543 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Tue, 8 Oct 2019 13:07:27 -0700 Subject: [PATCH 201/545] Update LLVM for Emscripten exception handling support Updates LLVM to pick up the cherry-picked support for correctly handling exception handling with aggregates passed by value. This will be necessary to continue to support Emscripten's exception handling once we switch using Emscripten's LLVM backend. See #63649. --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 8473db5f2af9..14a3b123074e 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 8473db5f2af9dc36aaf6f9b053fcc2e0e6ac8026 +Subproject commit 14a3b123074e066d64a99886941473058e52197d From bdcc21cbc4dabe73662634ffada8d0f353bc1ce9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fe=CC=81lix=20Saparelli?= Date: Sat, 21 Sep 2019 22:56:05 +1200 Subject: [PATCH 202/545] Implement (HashMap) Entry::insert as per #60142 --- Cargo.lock | 21 +++++++++++-- src/libstd/Cargo.toml | 2 +- src/libstd/collections/hash/map.rs | 47 ++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 80364515a7cc..6c05efcbec5e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,12 @@ dependencies = [ "winapi 0.3.6", ] +[[package]] +name = "autocfg" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" + [[package]] name = "backtrace" version = "0.3.37" @@ -1259,7 +1265,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d" dependencies = [ - "hashbrown", + "hashbrown 0.5.0", "lazy_static 1.3.0", "log", "pest", @@ -1276,10 +1282,19 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" dependencies = [ + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6587d09be37fb98a11cb08b9000a3f592451c1b1b613ca69d949160e313a430a" +dependencies = [ + "autocfg", "compiler_builtins", "rustc-std-workspace-alloc", "rustc-std-workspace-core", - "serde", ] [[package]] @@ -4073,7 +4088,7 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown", + "hashbrown 0.6.1", "libc", "panic_abort", "panic_unwind", diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index ee4b367b5c5b..5309af6f4c34 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -23,7 +23,7 @@ libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of compiler_builtins = { version = "0.1.16" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } -hashbrown = { version = "0.5.0", features = ['rustc-dep-of-std'] } +hashbrown = { version = "0.6.1", default-features = false, features = ['rustc-dep-of-std'] } [dependencies.backtrace_rs] package = "backtrace" diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index ff50051ef504..fcca112563d2 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2030,6 +2030,31 @@ impl<'a, K, V> Entry<'a, K, V> { Vacant(entry) => Vacant(entry), } } + + /// Sets the value of the entry, and returns an OccupiedEntry. + /// + /// # Examples + /// + /// ``` + /// #![feature(entry_insert)] + /// use std::collections::HashMap; + /// + /// let mut map: HashMap<&str, String> = HashMap::new(); + /// let entry = map.entry("poneyland").insert("hoho".to_string()); + /// + /// assert_eq!(entry.key(), &"poneyland"); + /// ``` + #[inline] + #[unstable(feature = "entry_insert", issue = "65225")] + pub fn insert(self, value: V) -> OccupiedEntry<'a, K, V> { + match self { + Occupied(mut entry) => { + entry.insert(value); + entry + }, + Vacant(entry) => entry.insert_entry(value), + } + } } impl<'a, K, V: Default> Entry<'a, K, V> { @@ -2347,6 +2372,28 @@ impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> { pub fn insert(self, value: V) -> &'a mut V { self.base.insert(value) } + + /// Sets the value of the entry with the VacantEntry's key, + /// and returns an OccupiedEntry. + /// + /// # Examples + /// + /// ``` + /// use std::collections::HashMap; + /// use std::collections::hash_map::Entry; + /// + /// let mut map: HashMap<&str, u32> = HashMap::new(); + /// + /// if let Entry::Vacant(o) = map.entry("poneyland") { + /// o.insert(37); + /// } + /// assert_eq!(map["poneyland"], 37); + /// ``` + #[inline] + fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> { + let base = self.base.insert_entry(value); + OccupiedEntry { base } + } } #[stable(feature = "rust1", since = "1.0.0")] From 45aca119a6c94a2c408fb6da7a47d363ab852bac Mon Sep 17 00:00:00 2001 From: Jon Gjengset Date: Mon, 23 Sep 2019 13:54:37 -0400 Subject: [PATCH 203/545] Stabilize mem::take (mem_take) Tracking issue: https://github.com/rust-lang/rust/issues/61129 --- src/liballoc/lib.rs | 1 - src/libcore/lib.rs | 1 - src/libcore/mem/mod.rs | 6 +----- src/libproc_macro/lib.rs | 1 - src/librustc/lib.rs | 1 - src/librustc_codegen_llvm/lib.rs | 1 - src/librustc_codegen_ssa/lib.rs | 1 - src/librustc_mir/lib.rs | 1 - src/librustc_resolve/lib.rs | 1 - src/librustc_typeck/lib.rs | 1 - src/librustdoc/lib.rs | 1 - src/libstd/lib.rs | 1 - src/libsyntax/lib.rs | 1 - src/libsyntax_ext/lib.rs | 1 - 14 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 247cd9a02016..e6b174beaae6 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -121,7 +121,6 @@ #![feature(maybe_uninit_extra, maybe_uninit_slice)] #![feature(alloc_layout_extra)] #![feature(try_trait)] -#![feature(mem_take)] #![feature(associated_type_bounds)] // Allow testing this library diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index e8c76b49a8e5..30e8dddff85a 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -127,7 +127,6 @@ #![feature(adx_target_feature)] #![feature(maybe_uninit_slice)] #![feature(external_doc)] -#![feature(mem_take)] #![feature(associated_type_bounds)] #[prelude_import] diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 95ad4272cedd..23608931b1dd 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -520,8 +520,6 @@ pub fn swap(x: &mut T, y: &mut T) { /// A simple example: /// /// ``` -/// #![feature(mem_take)] -/// /// use std::mem; /// /// let mut v: Vec = vec![1, 2]; @@ -552,8 +550,6 @@ pub fn swap(x: &mut T, y: &mut T) { /// `self`, allowing it to be returned: /// /// ``` -/// #![feature(mem_take)] -/// /// use std::mem; /// /// # struct Buffer { buf: Vec } @@ -572,7 +568,7 @@ pub fn swap(x: &mut T, y: &mut T) { /// /// [`Clone`]: ../../std/clone/trait.Clone.html #[inline] -#[unstable(feature = "mem_take", issue = "61129")] +#[stable(feature = "mem_take", since = "1.40.0")] pub fn take(dest: &mut T) -> T { replace(dest, T::default()) } diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index e199670b561c..f612c52d3983 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -25,7 +25,6 @@ #![feature(extern_types)] #![feature(in_band_lifetimes)] #![feature(optin_builtin_traits)] -#![feature(mem_take)] #![feature(non_exhaustive)] #![feature(rustc_attrs)] #![feature(specialization)] diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 9c3cb3af9e79..197ca191a5d0 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -58,7 +58,6 @@ #![feature(crate_visibility_modifier)] #![feature(proc_macro_hygiene)] #![feature(log_syntax)] -#![feature(mem_take)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 87eab484fafc..52797e64f7df 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -19,7 +19,6 @@ #![feature(link_args)] #![feature(static_nobundle)] #![feature(trusted_len)] -#![feature(mem_take)] use back::write::{create_target_machine, create_informational_target_machine}; use syntax_pos::symbol::Symbol; diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index 5017a60ca699..d700001430e2 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -10,7 +10,6 @@ #![feature(in_band_lifetimes)] #![feature(nll)] #![feature(trusted_len)] -#![feature(mem_take)] #![feature(associated_type_bounds)] #![recursion_limit="256"] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 81c08ee87e98..a837c34e8d47 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -22,7 +22,6 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(slice_concat_ext)] #![feature(trusted_len)] #![feature(try_blocks)] -#![feature(mem_take)] #![feature(associated_type_bounds)] #![feature(range_is_empty)] #![feature(stmt_expr_attributes)] diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index cc75961e6b1a..2a0643ca9bb6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -11,7 +11,6 @@ #![feature(crate_visibility_modifier)] #![feature(label_break_value)] -#![feature(mem_take)] #![feature(nll)] #![recursion_limit="256"] diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index e2e8c09bb584..9374113e1c95 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -67,7 +67,6 @@ This API is completely unstable and subject to change. #![feature(nll)] #![feature(slice_patterns)] #![feature(never_type)] -#![feature(mem_take)] #![recursion_limit="256"] diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index c23890e2a05e..6bcb4a817d78 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -15,7 +15,6 @@ #![feature(const_fn)] #![feature(drain_filter)] #![feature(never_type)] -#![feature(mem_take)] #![feature(unicode_internals)] #![recursion_limit="256"] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 5ff32d7adafc..af6cb656444d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -277,7 +277,6 @@ #![feature(log_syntax)] #![feature(maybe_uninit_ref)] #![feature(maybe_uninit_slice)] -#![feature(mem_take)] #![feature(needs_panic_runtime)] #![feature(never_type)] #![feature(nll)] diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index d2c76b669dd5..03b00188e255 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -12,7 +12,6 @@ #![feature(const_transmute)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] -#![feature(mem_take)] #![feature(nll)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 631ab7a33106..64d46a84cba4 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -5,7 +5,6 @@ #![feature(crate_visibility_modifier)] #![feature(decl_macro)] -#![feature(mem_take)] #![feature(nll)] #![feature(proc_macro_internals)] #![feature(proc_macro_quote)] From 7dc4bf4f935a929d1a9b8beb5d72ae1daa117f34 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Wed, 9 Oct 2019 01:03:56 +0200 Subject: [PATCH 204/545] Change incorrect trait name in E0038 error documentation --- src/librustc/error_codes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index 2de9cb5e9fb6..caa7282c701c 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -280,7 +280,7 @@ trait Super { } ``` -If the trait `Foo` was deriving from something like `Super` or +If the trait `Trait` was deriving from something like `Super` or `Super` (where `Foo` itself is `Foo`), this is okay, because given a type `get_a()` will definitely return an object of that type. From 175db95b3d98b1874b9d49a5e79a0755aed3e8fa Mon Sep 17 00:00:00 2001 From: Baoshan Pang Date: Mon, 7 Oct 2019 09:59:08 -0700 Subject: [PATCH 205/545] add checking (r == 0) --- src/libstd/sys/vxworks/rwlock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/vxworks/rwlock.rs b/src/libstd/sys/vxworks/rwlock.rs index 718f422ed11e..19b123f2b613 100644 --- a/src/libstd/sys/vxworks/rwlock.rs +++ b/src/libstd/sys/vxworks/rwlock.rs @@ -25,7 +25,7 @@ impl RWLock { let r = libc::pthread_rwlock_rdlock(self.inner.get()); if r == libc::EAGAIN { panic!("rwlock maximum reader count exceeded"); - } else if r == libc::EDEADLK || *self.write_locked.get() { + } else if r == libc::EDEADLK || (r == 0 && *self.write_locked.get()) { if r == 0 { self.raw_unlock(); } From 8231f46a8f72cc56c92f258bd434fa6234daf3f5 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Wed, 9 Oct 2019 09:52:08 +0300 Subject: [PATCH 206/545] Resolve divergency with master --- src/libtest/lib.rs | 90 +++++++++++++++++++++++++++++--------------- src/libtest/tests.rs | 2 +- 2 files changed, 60 insertions(+), 32 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 8a8ea7452932..c303c1995226 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1731,6 +1731,7 @@ pub fn run_test( } struct TestRunOpts { + pub strategy: RunStrategy, pub nocapture: bool, pub concurrency: Concurrent, pub time: Option, @@ -1738,7 +1739,6 @@ pub fn run_test( fn run_test_inner( desc: TestDesc, - strategy: RunStrategy, monitor_ch: Sender, testfn: Box, opts: TestRunOpts, @@ -1747,10 +1747,10 @@ pub fn run_test( let name = desc.name.clone(); let runtest = move || { - match strategy { + match opts.strategy { RunStrategy::InProcess => - run_test_in_process(desc, nocapture, report_time, testfn, monitor_ch), - RunStrategy::SpawnPrimary => spawn_test_subprocess(desc, report_time, monitor_ch), + run_test_in_process(desc, opts.nocapture, opts.time.is_some(), testfn, monitor_ch, opts.time), + RunStrategy::SpawnPrimary => spawn_test_subprocess(desc, opts.time.is_some(), monitor_ch, opts.time), } }; @@ -1767,6 +1767,7 @@ pub fn run_test( } let test_run_opts = TestRunOpts { + strategy, nocapture: opts.nocapture, concurrency, time: opts.time_options @@ -1792,15 +1793,13 @@ pub fn run_test( }; run_test_inner( desc, - strategy, monitor_ch, Box::new(move || __rust_begin_short_backtrace(f)), - concurrency + test_run_opts, ); } StaticTestFn(f) => run_test_inner( desc, - strategy, monitor_ch, Box::new(move || __rust_begin_short_backtrace(f)), test_run_opts, @@ -1816,10 +1815,10 @@ fn __rust_begin_short_backtrace(f: F) { fn calc_result<'a>( desc: &TestDesc, - task_result: Result<(), &'a (dyn Any + 'static + Send)>) + task_result: Result<(), &'a (dyn Any + 'static + Send)>, time_opts: &Option, - exec_time: &Option) --> TestResult { + exec_time: &Option +) -> TestResult { let result = match (&desc.should_panic, task_result) { (&ShouldPanic::No, Ok(())) | (&ShouldPanic::Yes, Err(_)) => TrOk, (&ShouldPanic::YesWithMessage(msg), Err(ref err)) => { @@ -1844,6 +1843,33 @@ fn calc_result<'a>( _ => TrFailed, }; + // If test is already failed (or allowed to fail), do not change the result. + if result != TrOk { + return result; + } + + // Check if test is failed due to timeout. + if let (Some(opts), Some(time)) = (time_opts, exec_time) { + if opts.error_on_excess && opts.is_critical(desc, time) { + return TrTimedFail; + } + } + + result +} + +fn get_result_from_exit_code( + desc: &TestDesc, + code: i32, + time_opts: &Option, + exec_time: &Option, +) -> TestResult { + let result = match (desc.allow_fail, code) { + (_, TR_OK) => TrOk, + (true, TR_FAILED) => TrAllowedFail, + (false, TR_FAILED) => TrFailed, + (_, _) => TrFailedMsg(format!("got unexpected return code {}", code)), + }; // If test is already failed (or allowed to fail), do not change the result. if result != TrOk { @@ -1860,20 +1886,14 @@ fn calc_result<'a>( result } -fn get_result_from_exit_code(desc: &TestDesc, code: i32) -> TestResult { - match (desc.allow_fail, code) { - (_, TR_OK) => TrOk, - (true, TR_FAILED) => TrAllowedFail, - (false, TR_FAILED) => TrFailed, - (_, _) => TrFailedMsg(format!("got unexpected return code {}", code)), - } -} - -fn run_test_in_process(desc: TestDesc, - nocapture: bool, - report_time: bool, - testfn: Box, - monitor_ch: Sender) { +fn run_test_in_process( + desc: TestDesc, + nocapture: bool, + report_time: bool, + testfn: Box, + monitor_ch: Sender, + time_opts: Option, +) { // Buffer for capturing standard I/O let data = Arc::new(Mutex::new(Vec::new())); @@ -1903,14 +1923,19 @@ fn run_test_in_process(desc: TestDesc, } let test_result = match result { - Ok(()) => calc_result(&desc, Ok(())), - Err(e) => calc_result(&desc, Err(e.as_ref())), + Ok(()) => calc_result(&desc, Ok(()), &time_opts, &exec_time), + Err(e) => calc_result(&desc, Err(e.as_ref()), &time_opts, &exec_time), }; let stdout = data.lock().unwrap().to_vec(); monitor_ch.send((desc.clone(), test_result, exec_time, stdout)).unwrap(); } -fn spawn_test_subprocess(desc: TestDesc, report_time: bool, monitor_ch: Sender) { +fn spawn_test_subprocess( + desc: TestDesc, + report_time: bool, + monitor_ch: Sender, + time_opts: Option, +) { let (result, test_output, exec_time) = (|| { let args = env::args().collect::>(); let current_exe = &args[0]; @@ -1941,7 +1966,7 @@ fn spawn_test_subprocess(desc: TestDesc, report_time: bool, monitor_ch: Sender Result { let exit_code = get_exit_code(status)?; - Ok(get_result_from_exit_code(&desc, exit_code)) + Ok(get_result_from_exit_code(&desc, exit_code, &time_opts, &exec_time)) })() { Ok(r) => r, Err(e) => { @@ -1956,12 +1981,15 @@ fn spawn_test_subprocess(desc: TestDesc, report_time: bool, monitor_ch: Sender) -> ! { +fn run_test_in_spawned_subprocess( + desc: TestDesc, + testfn: Box, +) -> ! { let builtin_panic_hook = panic::take_hook(); let record_result = Arc::new(move |panic_info: Option<&'_ PanicInfo<'_>>| { let test_result = match panic_info { - Some(info) => calc_result(&desc, Err(info.payload())), - None => calc_result(&desc, Ok(())), + Some(info) => calc_result(&desc, Err(info.payload()), &None, &None), + None => calc_result(&desc, Ok(()), &None, &None), }; // We don't support serializing TrFailedMsg, so just diff --git a/src/libtest/tests.rs b/src/libtest/tests.rs index d345c8503812..880d02a28ff0 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -240,7 +240,7 @@ fn time_test_failure_template(test_type: TestType) -> TestResult { ..TestOpts::new() }; let (tx, rx) = channel(); - run_test(&test_opts, false, desc, tx, Concurrent::No); + run_test(&test_opts, false, desc, RunStrategy::InProcess, tx, Concurrent::No); let (_, result, _, _) = rx.recv().unwrap(); result From 375a051f7fbda8eb58f3fc290f39a6a6e11a0468 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Wed, 9 Oct 2019 10:03:08 +0300 Subject: [PATCH 207/545] Make interface of the feature more convenient --- src/libtest/formatters/pretty.rs | 2 +- src/libtest/lib.rs | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/libtest/formatters/pretty.rs b/src/libtest/formatters/pretty.rs index 58824a3952ac..2935b4c99cec 100644 --- a/src/libtest/formatters/pretty.rs +++ b/src/libtest/formatters/pretty.rs @@ -209,7 +209,7 @@ impl OutputFormatter for PrettyFormatter { TrAllowedFail => self.write_allowed_fail()?, TrBench(ref bs) => { self.write_bench()?; - self.write_plain(&format!(": {}\n", fmt_bench_samples(bs)))?; + self.write_plain(&format!(": {}", fmt_bench_samples(bs)))?; } TrTimedFail => self.write_time_failed()?, } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index c303c1995226..60bd088ea427 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -514,6 +514,10 @@ impl TimeThreshold { durations.next().unwrap_or_else(panic_on_incorrect_value) ); + if warn > critical { + panic!("Test execution warn time should be less or equal to the critical time"); + } + Some(Self::new(Duration::from_millis(warn), Duration::from_millis(critical))) } } @@ -704,17 +708,24 @@ fn optgroups() -> getopts::Options { `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and `RUST_TEST_TIME_DOCTEST` environment variables. + Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`. + Not available for --format=terse", "plain|colored" ) .optflag( "", - "ensure-test-time", + "ensure-time", "Treat excess of the test execution time limit as error. Threshold values for this option can be configured via `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` and - `RUST_TEST_TIME_DOCTEST` environment variables." + `RUST_TEST_TIME_DOCTEST` environment variables. + + Expected format of environment variable is `VARIABLE=WARN_TIME,CRITICAL_TIME`. + + `CRITICAL_TIME` here means the limit that should not be exceeded by test. + " ); return opts; } @@ -785,12 +796,15 @@ fn get_time_options( -> Option> { let report_time = unstable_optflag!(matches, allow_unstable, "report-time"); let colored_opt_str = matches.opt_str("report-time"); - let report_time_colored = report_time && colored_opt_str == Some("colored".into()); - let ensure_test_time = unstable_optflag!(matches, allow_unstable, "ensure-test-time"); + let mut report_time_colored = report_time && colored_opt_str == Some("colored".into()); + let ensure_test_time = unstable_optflag!(matches, allow_unstable, "ensure-time"); // If `ensure-test-time` option is provided, time output is enforced, // so user won't be confused if any of tests will silently fail. let options = if report_time || ensure_test_time { + if ensure_test_time && !report_time { + report_time_colored = true; + } Some(TestTimeOptions::new_from_env(ensure_test_time, report_time_colored)) } else { None @@ -872,7 +886,7 @@ pub fn parse_opts(args: &[String]) -> Option { let time_options = match get_time_options(&matches, allow_unstable) { Some(Ok(val)) => val, Some(Err(e)) => return Some(Err(e)), - x => panic!("Unexpected output from `get_time_options`: {:?}", x), + None => panic!("Unexpected output from `get_time_options`"), }; let test_threads = match matches.opt_str("test-threads") { From d7423f143dd89623ab47d7b314122ab2dbe2bba3 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Wed, 9 Oct 2019 10:03:27 +0300 Subject: [PATCH 208/545] Add an entry to the unstable book --- .../src/library-features/report-time.md | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 src/doc/unstable-book/src/library-features/report-time.md diff --git a/src/doc/unstable-book/src/library-features/report-time.md b/src/doc/unstable-book/src/library-features/report-time.md new file mode 100644 index 000000000000..ed4e9c6b5684 --- /dev/null +++ b/src/doc/unstable-book/src/library-features/report-time.md @@ -0,0 +1,80 @@ +# `report-time` + +The tracking issue for this feature is: [#64888] + +[#64888]: https://github.com/rust-lang/rust/issues/64888 + +------------------------ + +The `report-time` feature adds a possibility to report execution time of the +tests generated via `libtest`. + +This is unstable feature, so you have to provide `-Zunstable-options` to get +this feature working. + +Sample usage command: + +```sh +./test_executable -Zunstable-options --report-time +``` + +Available options: + +```sh +--report-time [plain|colored] + Show execution time of each test. Awailable values: + plain = do not colorize the execution time (default); + colored = colorize output according to the `color` + parameter value; + Threshold values for colorized output can be + configured via + `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` + and + `RUST_TEST_TIME_DOCTEST` environment variables. + Expected format of environment variable is + `VARIABLE=WARN_TIME,CRITICAL_TIME`. + Not available for --format=terse +--ensure-time + Treat excess of the test execution time limit as + error. + Threshold values for this option can be configured via + `RUST_TEST_TIME_UNIT`, `RUST_TEST_TIME_INTEGRATION` + and + `RUST_TEST_TIME_DOCTEST` environment variables. + Expected format of environment variable is + `VARIABLE=WARN_TIME,CRITICAL_TIME`. + `CRITICAL_TIME` here means the limit that should not be + exceeded by test. +``` + +Example of the environment variable format: + +```sh +RUST_TEST_TIME_UNIT=100,200 +``` + +where 100 stands for warn time, and 200 stands for critical time. + +## Examples + +```sh +cargo test --tests -- -Zunstable-options --report-time + Finished dev [unoptimized + debuginfo] target(s) in 0.02s + Running target/debug/deps/example-27fb188025bec02c + +running 3 tests +test tests::unit_test_quick ... ok <0.000s> +test tests::unit_test_warn ... ok <0.055s> +test tests::unit_test_critical ... ok <0.110s> + +test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out + + Running target/debug/deps/tests-cedb06f6526d15d9 + +running 3 tests +test unit_test_quick ... ok <0.000s> +test unit_test_warn ... ok <0.550s> +test unit_test_critical ... ok <1.100s> + +test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out +``` From 56077605fd47e4df6c1897b4c3dab12f23774bb4 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Wed, 9 Oct 2019 10:29:20 +0300 Subject: [PATCH 209/545] Follow the styling guide --- src/libtest/lib.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 60bd088ea427..26766f401ad2 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1763,8 +1763,16 @@ pub fn run_test( let runtest = move || { match opts.strategy { RunStrategy::InProcess => - run_test_in_process(desc, opts.nocapture, opts.time.is_some(), testfn, monitor_ch, opts.time), - RunStrategy::SpawnPrimary => spawn_test_subprocess(desc, opts.time.is_some(), monitor_ch, opts.time), + run_test_in_process( + desc, + opts.nocapture, + opts.time.is_some(), + testfn, + monitor_ch, + opts.time + ), + RunStrategy::SpawnPrimary => + spawn_test_subprocess(desc, opts.time.is_some(), monitor_ch, opts.time), } }; From 3f9d834fb3c32b67a5f368c8265a9ca6d83de7c3 Mon Sep 17 00:00:00 2001 From: Konrad Borowski Date: Wed, 9 Oct 2019 12:33:24 +0200 Subject: [PATCH 210/545] Add failing example for Self in supertrait listing in E0038 documentation --- src/librustc/error_codes.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index caa7282c701c..f3f1c9c6c7de 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -259,7 +259,7 @@ trait Foo { This is similar to the second sub-error, but subtler. It happens in situations like the following: -``` +```compile_fail,E0038 trait Super {} trait Trait: Super { @@ -270,6 +270,10 @@ struct Foo; impl Super for Foo{} impl Trait for Foo {} + +fn main() { + let x: Box; +} ``` Here, the supertrait might have methods as follows: From ceb1a9cfe314b9729a7d8e29e5bd6e5f5798bb0c Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 8 Oct 2019 14:05:41 +0200 Subject: [PATCH 211/545] self-profiling: Add events for everything except trait selection. --- src/librustc/dep_graph/graph.rs | 2 ++ src/librustc/hir/lowering.rs | 2 ++ src/librustc/hir/map/mod.rs | 2 ++ src/librustc_incremental/persist/load.rs | 5 +++++ src/librustc_incremental/persist/save.rs | 2 ++ src/librustc_interface/passes.rs | 2 ++ src/librustc_mir/monomorphize/collector.rs | 7 +++++++ src/librustc_mir/monomorphize/partitioning.rs | 18 ++++++++++++++---- src/librustc_resolve/lib.rs | 3 +++ 9 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index e0cb00cf697f..8f18e0312862 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -845,6 +845,8 @@ impl DepGraph { // This method will only load queries that will end up in the disk cache. // Other queries will not be executed. pub fn exec_cache_promotions(&self, tcx: TyCtxt<'_>) { + let _prof_timer = tcx.prof.generic_activity("incr_comp_query_cache_promotion"); + let data = self.data.as_ref().unwrap(); for prev_index in data.colors.values.indices() { match data.colors.get(prev_index) { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index d773c454432d..72fd054ee8a2 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -242,6 +242,8 @@ pub fn lower_crate( // incr. comp. yet. dep_graph.assert_ignored(); + let _prof_timer = sess.prof.generic_activity("hir_lowering"); + LoweringContext { crate_root: sess.parse_sess.injected_crate_name.try_get().copied(), sess, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 1705f5692d4f..16c4ab7187de 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1222,6 +1222,8 @@ pub fn map_crate<'hir>(sess: &crate::session::Session, forest: &'hir Forest, definitions: &'hir Definitions) -> Map<'hir> { + let _prof_timer = sess.prof.generic_activity("build_hir_map"); + // Build the reverse mapping of `node_to_hir_id`. let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated() .map(|(node_id, &hir_id)| (hir_id, node_id)).collect(); diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index b7f4df62b494..673da52c3250 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -101,6 +101,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { // before we fire the background thread. let time_passes = sess.time_passes(); + let prof = sess.prof.clone(); if sess.opts.incremental.is_none() { // No incremental compilation. @@ -161,6 +162,8 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { MaybeAsync::Async(std::thread::spawn(move || { time_ext(time_passes, "background load prev dep-graph", move || { + let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph"); + match load_data(report_incremental_info, &path) { LoadResult::DataOutOfDate => LoadResult::DataOutOfDate, LoadResult::Error { message } => LoadResult::Error { message }, @@ -198,6 +201,8 @@ pub fn load_query_result_cache(sess: &Session) -> OnDiskCache<'_> { return OnDiskCache::new_empty(sess.source_map()); } + let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache"); + match load_data(sess.opts.debugging_opts.incremental_info, &query_cache_path(sess)) { LoadResult::Ok{ data: (bytes, start_pos) } => OnDiskCache::new(sess, bytes, start_pos), _ => OnDiskCache::new_empty(sess.source_map()) diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 6af065513ee0..f5935c9969ba 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -241,6 +241,8 @@ fn encode_work_product_index(work_products: &FxHashMap, encoder: &mut Encoder) { time(tcx.sess, "serialize query result cache", || { + let _timer = tcx.prof.generic_activity("incr_comp_serialize_result_cache"); + tcx.serialize_query_result_cache(encoder).unwrap(); }) } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 870f804ed447..a1dc5b01aba8 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -250,6 +250,8 @@ pub fn register_plugins<'a>( if sess.opts.incremental.is_some() { time(sess, "garbage-collect incremental cache directory", || { + let _prof_timer = + sess.prof.generic_activity("incr_comp_garbage_collect_session_directories"); if let Err(e) = rustc_incremental::garbage_collect_session_directories(sess) { warn!( "Error while trying to garbage collect incremental \ diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 3ac837dd330f..3f0a2674305d 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -285,7 +285,11 @@ pub fn collect_crate_mono_items( tcx: TyCtxt<'_>, mode: MonoItemCollectionMode, ) -> (FxHashSet>, InliningMap<'_>) { + let _prof_timer = tcx.prof.generic_activity("monomorphization_collector"); + let roots = time(tcx.sess, "collecting roots", || { + let _prof_timer = tcx.prof + .generic_activity("monomorphization_collector_root_collections"); collect_roots(tcx, mode) }); @@ -295,6 +299,9 @@ pub fn collect_crate_mono_items( let mut inlining_map = MTLock::new(InliningMap::new()); { + let _prof_timer = tcx.prof + .generic_activity("monomorphization_collector_graph_walk"); + let visited: MTRef<'_, _> = &mut visited; let inlining_map: MTRef<'_, _> = &mut inlining_map; diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 61868b24c0b8..6d9dae7214cc 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -134,10 +134,15 @@ pub fn partition<'tcx, I>( where I: Iterator>, { + let _prof_timer = tcx.prof.generic_activity("cgu_partitioning"); + // In the first step, we place all regular monomorphizations into their // respective 'home' codegen unit. Regular monomorphizations are all // functions and statics defined in the local crate. - let mut initial_partitioning = place_root_mono_items(tcx, mono_items); + let mut initial_partitioning = { + let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots"); + place_root_mono_items(tcx, mono_items) + }; initial_partitioning.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx)); @@ -146,8 +151,8 @@ where // If the partitioning should produce a fixed count of codegen units, merge // until that count is reached. if let PartitioningStrategy::FixedUnitCount(count) = strategy { + let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus"); merge_codegen_units(tcx, &mut initial_partitioning, count); - debug_dump(tcx, "POST MERGING:", initial_partitioning.codegen_units.iter()); } @@ -155,8 +160,11 @@ where // monomorphizations have to go into each codegen unit. These additional // monomorphizations can be drop-glue, functions from external crates, and // local functions the definition of which is marked with `#[inline]`. - let mut post_inlining = place_inlined_mono_items(initial_partitioning, - inlining_map); + let mut post_inlining = { + let _prof_timer = + tcx.prof.generic_activity("cgu_partitioning_place_inline_items"); + place_inlined_mono_items(initial_partitioning, inlining_map) + }; post_inlining.codegen_units.iter_mut().for_each(|cgu| cgu.estimate_size(tcx)); @@ -165,6 +173,8 @@ where // Next we try to make as many symbols "internal" as possible, so LLVM has // more freedom to optimize. if !tcx.sess.opts.cg.link_dead_code { + let _prof_timer = + tcx.prof.generic_activity("cgu_partitioning_internalize_symbols"); internalize_symbols(tcx, &mut post_inlining, inlining_map); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 9c4281bbb62c..9211ee5f1453 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1255,6 +1255,9 @@ impl<'a> Resolver<'a> { /// Entry point to crate resolution. pub fn resolve_crate(&mut self, krate: &Crate) { + let _prof_timer = + self.session.prof.generic_activity("resolve_crate"); + ImportResolver { r: self }.finalize_imports(); self.finalize_macro_resolutions(); From 15f571bbd3ce370d925d21f1ab281aee993e4860 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Wed, 9 Oct 2019 17:43:27 +0300 Subject: [PATCH 212/545] Move unstable book entry into compiler flags directory --- .../src/{library-features => compiler-flags}/report-time.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/doc/unstable-book/src/{library-features => compiler-flags}/report-time.md (100%) diff --git a/src/doc/unstable-book/src/library-features/report-time.md b/src/doc/unstable-book/src/compiler-flags/report-time.md similarity index 100% rename from src/doc/unstable-book/src/library-features/report-time.md rename to src/doc/unstable-book/src/compiler-flags/report-time.md From 9dbd7be70f8b09aad232d5c4eda684cff622102d Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 9 Oct 2019 16:41:24 +0200 Subject: [PATCH 213/545] Cache the DepNodeIndex of upstream crates in order to avoid multiple locks and table lookups on each access of crate metadata. --- src/librustc/dep_graph/graph.rs | 2 +- src/librustc_metadata/creader.rs | 6 ++++-- src/librustc_metadata/cstore.rs | 10 +++++++++- src/librustc_metadata/cstore_impl.rs | 16 ++++++---------- src/librustc_metadata/decoder.rs | 25 +++++++++++++++++++++++++ 5 files changed, 45 insertions(+), 14 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index e0cb00cf697f..7e506f6e1b7f 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -30,7 +30,7 @@ rustc_index::newtype_index! { } impl DepNodeIndex { - const INVALID: DepNodeIndex = DepNodeIndex::MAX; + pub const INVALID: DepNodeIndex = DepNodeIndex::MAX; } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 042252bc13e6..cae4858c844c 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -3,10 +3,11 @@ use crate::cstore::{self, CStore, CrateSource, MetadataBlob}; use crate::locator::{self, CratePaths}; use crate::schema::{CrateRoot, CrateDep}; -use rustc_data_structures::sync::{Lrc, RwLock, Lock}; +use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell}; use rustc::hir::def_id::CrateNum; use rustc_data_structures::svh::Svh; +use rustc::dep_graph::DepNodeIndex; use rustc::middle::cstore::DepKind; use rustc::mir::interpret::AllocDecodingState; use rustc::session::{Session, CrateDisambiguator}; @@ -271,7 +272,8 @@ impl<'a> CrateLoader<'a> { }, private_dep, span, - raw_proc_macros + raw_proc_macros, + dep_node_index: AtomicCell::new(DepNodeIndex::INVALID), }; let cmeta = Lrc::new(cmeta); diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 833c846573f6..98a08e501f14 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -2,6 +2,7 @@ // crates and libraries use crate::schema; +use rustc::dep_graph::DepNodeIndex; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::map::definitions::DefPathTable; use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader}; @@ -9,7 +10,7 @@ use rustc::mir::interpret::AllocDecodingState; use rustc_index::vec::IndexVec; use rustc::util::nodemap::{FxHashMap, NodeMap}; -use rustc_data_structures::sync::{Lrc, RwLock, Lock}; +use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell}; use syntax::ast; use syntax::ext::base::SyntaxExtension; use syntax_pos; @@ -83,6 +84,13 @@ pub struct CrateMetadata { pub span: Span, pub raw_proc_macros: Option<&'static [ProcMacro]>, + + /// The `DepNodeIndex` of the `DepNode` representing this upstream crate. + /// It is initialized on the first access in `get_crate_dep_node_index()`. + /// Do not access the value directly, as it might not have been initialized + /// yet. + /// The field must always be initialized to `DepNodeIndex::INVALID`. + pub(super) dep_node_index: AtomicCell, } pub struct CStore { diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index cce0900bef3d..b9f1d5a0a920 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -51,19 +51,15 @@ macro_rules! provide { let ($def_id, $other) = def_id_arg.into_args(); assert!(!$def_id.is_local()); - let def_path_hash = $tcx.def_path_hash(DefId { - krate: $def_id.krate, - index: CRATE_DEF_INDEX - }); - let dep_node = def_path_hash - .to_dep_node(rustc::dep_graph::DepKind::CrateMetadata); - // The DepNodeIndex of the DepNode::CrateMetadata should be - // cached somewhere, so that we can use read_index(). - $tcx.dep_graph.read(dep_node); - let $cdata = $tcx.crate_data_as_rc_any($def_id.krate); let $cdata = $cdata.downcast_ref::() .expect("CrateStore created data is not a CrateMetadata"); + + if $tcx.dep_graph.is_fully_enabled() { + let crate_dep_node_index = $cdata.get_crate_dep_node_index($tcx); + $tcx.dep_graph.read_index(crate_dep_node_index); + } + $compute })* diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index eed355cbc135..ce66534e5659 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -13,6 +13,7 @@ use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; +use rustc::dep_graph::{DepNodeIndex, DepKind}; use rustc::middle::lang_items; use rustc::mir::{self, interpret}; use rustc::mir::interpret::AllocDecodingSession; @@ -1365,6 +1366,30 @@ impl<'a, 'tcx> CrateMetadata { // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref. self.source_map_import_info.borrow() } + + /// Get the `DepNodeIndex` corresponding this crate. The result of this + /// method is cached in the `dep_node_index` field. + pub(super) fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex { + let mut dep_node_index = self.dep_node_index.load(); + + if 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(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 003d5a63670b61eabf16fe3057bd1d5e2ec65e11 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 9 Oct 2019 16:43:47 +0200 Subject: [PATCH 214/545] self-profiling: Add events for tracking crate metadata loading related activities. --- src/librustc_metadata/creader.rs | 3 +++ src/librustc_metadata/cstore_impl.rs | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index cae4858c844c..50a2187c9374 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -197,6 +197,9 @@ impl<'a> CrateLoader<'a> { dep_kind: DepKind, name: Symbol ) -> (CrateNum, Lrc) { + let _prof_timer = + self.sess.prof.generic_activity("metadata_register_crate"); + let crate_root = lib.metadata.get_root(); self.verify_no_symbol_conflicts(span, &crate_root); diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index b9f1d5a0a920..cc68cc7f56e3 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -47,6 +47,9 @@ macro_rules! provide { $tcx: TyCtxt<$lt>, def_id_arg: T, ) -> as QueryConfig<$lt>>::Value { + let _prof_timer = + $tcx.prof.generic_activity("metadata_decode_entry"); + #[allow(unused_variables)] let ($def_id, $other) = def_id_arg.into_args(); assert!(!$def_id.is_local()); @@ -444,6 +447,8 @@ impl cstore::CStore { } pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { + let _prof_timer = sess.prof.generic_activity("metadata_load_macro"); + let data = self.get_crate_data(id.krate); if data.is_proc_macro_crate() { return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess)); From 0ee6a96eb76c4526012127cf1b65941233473579 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 9 Oct 2019 16:45:22 +0200 Subject: [PATCH 215/545] Remove some outdated comments about dependency tracking from cstore_impl. --- src/librustc_metadata/cstore_impl.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index cc68cc7f56e3..b701933a540c 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -526,20 +526,10 @@ impl CrateStore for cstore::CStore { /// parent `DefId` as well as some idea of what kind of data the /// `DefId` refers to. fn def_key(&self, def: DefId) -> DefKey { - // Note: loading the def-key (or def-path) for a def-id is not - // a *read* of its metadata. This is because the def-id is - // really just an interned shorthand for a def-path, which is the - // canonical name for an item. - // - // self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).def_key(def.index) } fn def_path(&self, def: DefId) -> DefPath { - // See `Note` above in `def_key()` for why this read is - // commented out: - // - // self.dep_graph.read(DepNode::MetaData(def)); self.get_crate_data(def.krate).def_path(def.index) } From 5d8af38329a2f3cf93f392239252664fd7d25a69 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 9 Oct 2019 17:37:28 +0300 Subject: [PATCH 216/545] resolve: Keep field spans for diagnostics --- src/librustc_metadata/cstore_impl.rs | 5 +++-- src/librustc_metadata/decoder.rs | 6 +++--- src/librustc_resolve/build_reduced_graph.rs | 14 ++++++++------ src/librustc_resolve/late/diagnostics.rs | 3 ++- src/librustc_resolve/lib.rs | 3 ++- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 91532d84473a..147c0472ebc8 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -33,6 +33,7 @@ use syntax::source_map; use syntax::edition::Edition; use syntax::parse::source_file_to_stream; use syntax::parse::parser::emit_unclosed_delims; +use syntax::source_map::Spanned; use syntax::symbol::Symbol; use syntax_pos::{Span, FileName}; use rustc_index::bit_set::BitSet; @@ -420,8 +421,8 @@ impl cstore::CStore { self.get_crate_data(cnum).root.edition } - pub fn struct_field_names_untracked(&self, def: DefId) -> Vec { - self.get_crate_data(def.krate).get_struct_field_names(def.index) + pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec> { + self.get_crate_data(def.krate).get_struct_field_names(def.index, sess) } pub fn ctor_kind_untracked(&self, def: DefId) -> def::CtorKind { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 34f86707ad32..74715278c829 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -29,7 +29,7 @@ use std::u32; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; -use syntax::source_map; +use syntax::source_map::{self, respan, Spanned}; use syntax::symbol::{Symbol, sym}; use syntax::ext::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension}; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}}; @@ -1021,11 +1021,11 @@ impl<'a, 'tcx> CrateMetadata { Lrc::from(self.get_attributes(&item, sess)) } - pub fn get_struct_field_names(&self, id: DefIndex) -> Vec { + pub fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec> { self.entry(id) .children .decode(self) - .map(|index| self.item_name(index)) + .map(|index| respan(self.get_span(index, sess), self.item_name(index))) .collect() } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f76aa95dd2cc..030f9b97eb8b 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -38,6 +38,7 @@ use syntax::ext::hygiene::ExpnId; use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; use syntax::{span_err, struct_span_err}; +use syntax::source_map::{respan, Spanned}; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; @@ -301,7 +302,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } - fn insert_field_names(&mut self, def_id: DefId, field_names: Vec) { + fn insert_field_names(&mut self, def_id: DefId, field_names: Vec>) { if !field_names.is_empty() { self.r.field_names.insert(def_id, field_names); } @@ -752,12 +753,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } // Record field names for error reporting. - let field_names = struct_def.fields().iter().filter_map(|field| { + let field_names = struct_def.fields().iter().map(|field| { let field_vis = self.resolve_visibility(&field.vis); if ctor_vis.is_at_least(field_vis, &*self.r) { ctor_vis = field_vis; } - field.ident.map(|ident| ident.name) + respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name)) }).collect(); let item_def_id = self.r.definitions.local_def_id(item.id); self.insert_field_names(item_def_id, field_names); @@ -779,9 +780,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); // Record field names for error reporting. - let field_names = vdata.fields().iter().filter_map(|field| { + let field_names = vdata.fields().iter().map(|field| { self.resolve_visibility(&field.vis); - field.ident.map(|ident| ident.name) + respan(field.span, field.ident.map_or(kw::Invalid, |ident| ident.name)) }).collect(); let item_def_id = self.r.definitions.local_def_id(item.id); self.insert_field_names(item_def_id, field_names); @@ -895,7 +896,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // Record some extra data for better diagnostics. match res { Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) => { - let field_names = self.r.cstore.struct_field_names_untracked(def_id); + let field_names = + self.r.cstore.struct_field_names_untracked(def_id, self.r.session); self.insert_field_names(def_id, field_names); } Res::Def(DefKind::Method, def_id) => { diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index d3bf82b66ad1..1e6c5b46b68d 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -497,7 +497,8 @@ impl<'a> LateResolutionVisitor<'a, '_> { Res::Def(DefKind::Struct, did) | Res::Def(DefKind::Union, did) if resolution.unresolved_segments() == 0 => { if let Some(field_names) = self.r.field_names.get(&did) { - if field_names.iter().any(|&field_name| ident.name == field_name) { + if field_names.iter() + .any(|&field_name| ident.name == field_name.node) { return Some(AssocSuggestion::Field); } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e7292b52ab3e..e625cf1f4884 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -47,6 +47,7 @@ use syntax::attr; use syntax::ast::{CRATE_NODE_ID, Crate}; use syntax::ast::{ItemKind, Path}; use syntax::{struct_span_err, unwrap_or}; +use syntax::source_map::Spanned; use syntax_pos::{Span, DUMMY_SP}; use errors::{Applicability, DiagnosticBuilder}; @@ -840,7 +841,7 @@ pub struct Resolver<'a> { /// Names of fields of an item `DefId` accessible with dot syntax. /// Used for hints during error reporting. - field_names: FxHashMap>, + field_names: FxHashMap>>, /// All imports known to succeed or fail. determined_imports: Vec<&'a ImportDirective<'a>>, From 48f8beddd8e28a5bbdf1334f2c1de402196fa7f1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 9 Oct 2019 17:37:48 +0300 Subject: [PATCH 217/545] resolve: Use field spans for reporting the private constructor error --- src/librustc_resolve/lib.rs | 30 +-- src/test/ui/privacy/privacy5.stderr | 240 ++++++++++++------ .../ui/resolve/privacy-struct-ctor.stderr | 30 ++- .../ui/rfc-2008-non-exhaustive/struct.stderr | 5 +- .../ui/rfc-2008-non-exhaustive/variant.stderr | 6 - 5 files changed, 204 insertions(+), 107 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e625cf1f4884..d87c6032bd91 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -30,7 +30,7 @@ use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrK use rustc::hir::def::Namespace::*; use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; use rustc::hir::{TraitMap, GlobMap}; -use rustc::ty; +use rustc::ty::{self, DefIdTree}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; use rustc::span_bug; @@ -1006,7 +1006,7 @@ impl<'a> AsMut> for Resolver<'a> { fn as_mut(&mut self) -> &mut Resolver<'a> { self } } -impl<'a, 'b> ty::DefIdTree for &'a Resolver<'b> { +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, @@ -2391,23 +2391,17 @@ impl<'a> Resolver<'a> { binding.res().descr(), ident.name, ); - // FIXME: use the ctor's `def_id` to check wether any of the fields is not visible - match binding.kind { - NameBindingKind::Res(Res::Def(DefKind::Ctor( - CtorOf::Struct, - CtorKind::Fn, - ), _def_id), _) => { - err.note("a tuple struct constructor is private if any of its fields \ - is private"); + if let NameBindingKind::Res( + Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id), _ + ) = binding.kind { + let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor"); + if let Some(fields) = self.field_names.get(&def_id) { + let first_field = fields.first().expect("empty field list in the map"); + err.span_label( + fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)), + "a tuple struct constructor is private if any of its fields is private", + ); } - NameBindingKind::Res(Res::Def(DefKind::Ctor( - CtorOf::Variant, - CtorKind::Fn, - ), _def_id), _) => { - err.note("a tuple variant constructor is private if any of its fields \ - is private"); - } - _ => {} } err.emit(); } diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr index 532d1ac1e2fb..c1b90d7c6bf2 100644 --- a/src/test/ui/privacy/privacy5.stderr +++ b/src/test/ui/privacy/privacy5.stderr @@ -1,386 +1,482 @@ error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:51:16 | +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private +... LL | let a = a::A(()); | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:52:16 | +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private +... LL | let b = a::B(2); | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:53:16 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | let c = a::C(2, 3); | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:56:12 | +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private +... LL | let a::A(()) = a; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:57:12 | +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private +... LL | let a::A(_) = a; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:58:18 | +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private +... LL | match a { a::A(()) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:59:18 | +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private +... LL | match a { a::A(_) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:61:12 | +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private +... LL | let a::B(_) = b; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:62:12 | +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private +... LL | let a::B(_b) = b; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:63:18 | +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private +... LL | match b { a::B(_) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:64:18 | +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private +... LL | match b { a::B(_b) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:65:18 | +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private +... LL | match b { a::B(1) => {} a::B(_) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:65:32 | +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private +... LL | match b { a::B(1) => {} a::B(_) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:68:12 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | let a::C(_, _) = c; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:69:12 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | let a::C(_a, _) = c; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:70:12 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | let a::C(_, _b) = c; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:71:12 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | let a::C(_a, _b) = c; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:72:18 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | match c { a::C(_, _) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:73:18 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | match c { a::C(_a, _) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:74:18 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | match c { a::C(_, _b) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:75:18 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | match c { a::C(_a, _b) => {} } | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:83:17 | +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private +... LL | let a2 = a::A; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:84:17 | +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private +... LL | let b2 = a::B; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:85:17 | +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private +... LL | let c2 = a::C; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:90:20 | LL | let a = other::A(()); | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:91:20 | LL | let b = other::B(2); | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:92:20 | LL | let c = other::C(2, 3); | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:95:16 | LL | let other::A(()) = a; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:96:16 | LL | let other::A(_) = a; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:97:22 | LL | match a { other::A(()) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:98:22 | LL | match a { other::A(_) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:100:16 | LL | let other::B(_) = b; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:101:16 | LL | let other::B(_b) = b; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:102:22 | LL | match b { other::B(_) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:103:22 | LL | match b { other::B(_b) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:104:22 | LL | match b { other::B(1) => {} other::B(_) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:104:40 | LL | match b { other::B(1) => {} other::B(_) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:107:16 | LL | let other::C(_, _) = c; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:108:16 | LL | let other::C(_a, _) = c; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:109:16 | LL | let other::C(_, _b) = c; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:110:16 | LL | let other::C(_a, _b) = c; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:111:22 | LL | match c { other::C(_, _) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:112:22 | LL | match c { other::C(_a, _) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:113:22 | LL | match c { other::C(_, _b) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:114:22 | LL | match c { other::C(_a, _b) => {} } | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `A` is private --> $DIR/privacy5.rs:122:21 | LL | let a2 = other::A; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct A(()); + | -- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `B` is private --> $DIR/privacy5.rs:123:21 | LL | let b2 = other::B; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct B(isize); + | ----- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `C` is private --> $DIR/privacy5.rs:124:21 | LL | let c2 = other::C; | ^ + | + ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct C(pub isize, isize); + | ---------------- a tuple struct constructor is private if any of its fields is private error: aborting due to 48 previous errors diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index 979367bc623f..d5311fde2e79 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -37,50 +37,60 @@ LL | use m::S; error[E0603]: tuple struct `Z` is private --> $DIR/privacy-struct-ctor.rs:18:12 | +LL | pub(in m) struct Z(pub(in m::n) u8); + | --------------- a tuple struct constructor is private if any of its fields is private +... LL | n::Z; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `S` is private --> $DIR/privacy-struct-ctor.rs:29:8 | +LL | pub struct S(u8); + | -- a tuple struct constructor is private if any of its fields is private +... LL | m::S; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `S` is private --> $DIR/privacy-struct-ctor.rs:31:19 | +LL | pub struct S(u8); + | -- a tuple struct constructor is private if any of its fields is private +... LL | let _: S = m::S(2); | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `Z` is private --> $DIR/privacy-struct-ctor.rs:35:11 | +LL | pub(in m) struct Z(pub(in m::n) u8); + | --------------- a tuple struct constructor is private if any of its fields is private +... LL | m::n::Z; | ^ - | - = note: a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `S` is private --> $DIR/privacy-struct-ctor.rs:41:16 | LL | xcrate::m::S; | ^ + | + ::: $DIR/auxiliary/privacy-struct-ctor.rs:2:18 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct S(u8); + | -- a tuple struct constructor is private if any of its fields is private error[E0603]: tuple struct `Z` is private --> $DIR/privacy-struct-ctor.rs:45:19 | LL | xcrate::m::n::Z; | ^ + | + ::: $DIR/auxiliary/privacy-struct-ctor.rs:5:28 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub(in m) struct Z(pub(in m::n) u8); + | --------------- a tuple struct constructor is private if any of its fields is private error: aborting due to 10 previous errors diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index d75a376286fc..15f97f7e1d6f 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -15,8 +15,11 @@ error[E0603]: tuple struct `TupleStruct` is private | LL | let ts_explicit = structs::TupleStruct(640, 480); | ^^^^^^^^^^^ + | + ::: $DIR/auxiliary/structs.rs:13:24 | - = note: a tuple struct constructor is private if any of its fields is private +LL | pub struct TupleStruct(pub u16, pub u16); + | ---------------- a tuple struct constructor is private if any of its fields is private error[E0603]: unit struct `UnitStruct` is private --> $DIR/struct.rs:32:32 diff --git a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr index ac0025ec7580..d9d6ea21b8bd 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/variant.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/variant.stderr @@ -3,8 +3,6 @@ error[E0603]: tuple variant `Tuple` is private | LL | let variant_tuple = NonExhaustiveVariants::Tuple(640); | ^^^^^ - | - = note: a tuple variant constructor is private if any of its fields is private error[E0603]: unit variant `Unit` is private --> $DIR/variant.rs:14:47 @@ -23,16 +21,12 @@ error[E0603]: tuple variant `Tuple` is private | LL | NonExhaustiveVariants::Tuple(fe_tpl) => "", | ^^^^^ - | - = note: a tuple variant constructor is private if any of its fields is private error[E0603]: tuple variant `Tuple` is private --> $DIR/variant.rs:26:35 | LL | if let NonExhaustiveVariants::Tuple(fe_tpl) = variant_struct { | ^^^^^ - | - = note: a tuple variant constructor is private if any of its fields is private error[E0639]: cannot create non-exhaustive variant using struct expression --> $DIR/variant.rs:8:26 From 6ae36a37ac1279d2ce20eca927cd89136a15a346 Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Wed, 9 Oct 2019 17:45:19 +0200 Subject: [PATCH 218/545] make it possible to add args to cargo in x.py eg. make it easier to test -Ztimings for rustc --- src/bootstrap/builder.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 9b43bb0eff0e..b8071b98f707 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -817,12 +817,22 @@ impl<'a> Builder<'a> { let mut rustflags = Rustflags::new(&target); if stage != 0 { + if let Ok(s) = env::var("CARGOFLAGS_NOT_BOOTSTRAP") { + cargo.args(s.split_whitespace()); + } rustflags.env("RUSTFLAGS_NOT_BOOTSTRAP"); } else { + if let Ok(s) = env::var("CARGOFLAGS_BOOTSTRAP") { + cargo.args(s.split_whitespace()); + } rustflags.env("RUSTFLAGS_BOOTSTRAP"); rustflags.arg("--cfg=bootstrap"); } + if let Ok(s) = env::var("CARGOFLAGS") { + cargo.args(s.split_whitespace()); + } + match mode { Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}, Mode::Rustc | Mode::Codegen | Mode::ToolRustc => { From 76a7667e792e4f4e4849ace0f6b016e2695a693c Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 9 Oct 2019 19:09:08 +0200 Subject: [PATCH 219/545] Move test next to likeminded ones --- src/test/ui/{issues => consts}/issue-64506.rs | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{issues => consts}/issue-64506.rs (100%) diff --git a/src/test/ui/issues/issue-64506.rs b/src/test/ui/consts/issue-64506.rs similarity index 100% rename from src/test/ui/issues/issue-64506.rs rename to src/test/ui/consts/issue-64506.rs From 76fe6a41ba156b59a78c162c0c1b0fadd02dd3f6 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 9 Oct 2019 19:12:49 +0200 Subject: [PATCH 220/545] Refactor a nested `if` to a `match` --- src/librustc/ty/layout.rs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 2751ce57e3e8..d12194aefa6b 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -825,17 +825,13 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }); (present_variants.next(), present_variants.next()) }; - let present_first = if present_first.is_none() { - if def.is_enum() { - // Uninhabited because it has no variants, or only absent ones. - return tcx.layout_raw(param_env.and(tcx.types.never)); - } else { - // if it's a struct, still compute a layout so that we can still compute the - // field offsets - Some(VariantIdx::new(0)) - } - } else { - present_first + let present_first = match present_first { + present_first @ Some(_) => present_first, + // Uninhabited because it has no variants, or only absent ones. + None if def.is_enum() => return tcx.layout_raw(param_env.and(tcx.types.never)), + // if it's a struct, still compute a layout so that we can still compute the + // field offsets + None => Some(VariantIdx::new(0)), }; let is_struct = !def.is_enum() || From 6d6d978baa3abb56ad56d481ab994698069626d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 17:10:37 -0700 Subject: [PATCH 221/545] Note when a mutable trait object is needed --- src/librustc/traits/error_reporting.rs | 111 ++++++++++++++---- src/librustc_typeck/check/method/mod.rs | 64 ++++++---- src/librustc_typeck/check/method/suggest.rs | 11 +- src/test/ui/not-panic/not-panic-safe.stderr | 1 + .../ui/parser/lex-bad-char-literals-6.stderr | 2 + .../imm-ref-trait-object-literal.rs | 14 +++ .../imm-ref-trait-object-literal.stderr | 30 +++++ .../ui/suggestions/imm-ref-trait-object.rs | 8 ++ .../suggestions/imm-ref-trait-object.stderr | 10 ++ src/test/ui/suggestions/into-str.stderr | 1 + .../suggestions/mut-borrow-needed-by-trait.rs | 23 ++++ .../mut-borrow-needed-by-trait.stderr | 41 +++++++ .../suggestions/suggest-remove-refs-1.stderr | 1 + 13 files changed, 271 insertions(+), 46 deletions(-) create mode 100644 src/test/ui/suggestions/imm-ref-trait-object-literal.rs create mode 100644 src/test/ui/suggestions/imm-ref-trait-object-literal.stderr create mode 100644 src/test/ui/suggestions/imm-ref-trait-object.rs create mode 100644 src/test/ui/suggestions/imm-ref-trait-object.stderr create mode 100644 src/test/ui/suggestions/mut-borrow-needed-by-trait.rs create mode 100644 src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index a1c97d6c6879..f85ba1459f5f 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -453,21 +453,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - 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); + 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); + 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 @@ -482,10 +478,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - fn report_similar_impl_candidates(&self, - impl_candidates: Vec>, - err: &mut DiagnosticBuilder<'_>) - { + fn report_similar_impl_candidates( + &self, + impl_candidates: Vec>, + err: &mut DiagnosticBuilder<'_>, + ) { if impl_candidates.is_empty() { return; } @@ -720,10 +717,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // which is somewhat confusing. err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate())); - } 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); + } 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 @@ -1081,9 +1086,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let substs = self.tcx.mk_substs_trait(trait_type, &[]); let new_trait_ref = ty::TraitRef::new(trait_ref.def_id, substs); - let new_obligation = Obligation::new(ObligationCause::dummy(), - obligation.param_env, - new_trait_ref.to_predicate()); + let new_obligation = Obligation::new( + ObligationCause::dummy(), + obligation.param_env, + new_trait_ref.to_predicate(), + ); if self.predicate_may_hold(&new_obligation) { let sp = self.tcx.sess.source_map() @@ -1105,6 +1112,68 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } + /// Check if the trait bound is implemented for a different mutability and note it in the + /// final error. + fn suggest_change_mut( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + points_at_arg: bool, + ) { + let span = obligation.cause.span; + 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() + { // Do not suggest removal of borrow from type arguments. + return; + } + + if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind { + let trait_type = match mutability { + hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type), + hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type), + }; + + let substs = self.tcx.mk_substs_trait(&trait_type, &[]); + let new_trait_ref = ty::TraitRef::new(trait_ref.skip_binder().def_id, substs); + let new_obligation = Obligation::new( + ObligationCause::dummy(), + obligation.param_env, + new_trait_ref.to_predicate(), + ); + + if self.predicate_may_hold(&new_obligation) { + let sp = self.tcx.sess.source_map() + .span_take_while(span, |c| c.is_whitespace() || *c == '&'); + if points_at_arg && + mutability == hir::Mutability::MutImmutable && + refs_number > 0 + { + err.span_suggestion( + sp, + "consider changing this borrow's mutability", + "&mut ".to_string(), + Applicability::MachineApplicable, + ); + } else { + err.note(&format!( + "`{}` is implemented for `{:?}`", + trait_ref, + trait_type, + )); + } + } + } + } + } + fn suggest_semicolon_removal( &self, obligation: &PredicateObligation<'tcx>, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 2be311127214..4522be21cab5 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -58,7 +58,7 @@ pub enum MethodError<'tcx> { // Found a `Self: Sized` bound where `Self` is a trait object, also the caller may have // forgotten to import a trait. - IllegalSizedBound(Vec), + IllegalSizedBound(Vec, bool), // Found a match, but the return type is wrong BadReturnType, @@ -213,33 +213,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { segment, ); + let mut needs_mut = false; + if let ty::Ref(region, t_type, mutability) = self_ty.kind { + let trait_type = match mutability { + hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type), + hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type), + }; + match self.lookup_probe( + span, + segment.ident, + trait_type, + call_expr, + ProbeScope::TraitsInScope + ) { + Ok(ref new_pick) if *new_pick != pick => { + needs_mut = true; + } + _ => {} + } + } + if result.illegal_sized_bound { // We probe again, taking all traits into account (not only those in scope). - let candidates = - match self.lookup_probe(span, - segment.ident, - self_ty, - call_expr, - ProbeScope::AllTraits) { - - // If we find a different result the caller probably forgot to import a trait. - Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()], - Err(Ambiguity(ref sources)) => { - sources.iter() - .filter_map(|source| { - match *source { - // Note: this cannot come from an inherent impl, - // because the first probing succeeded. - ImplSource(def) => self.tcx.trait_id_of_impl(def), - TraitSource(_) => None, - } - }) - .collect() + let candidates = match self.lookup_probe( + span, + segment.ident, + self_ty, + call_expr, + ProbeScope::AllTraits, + ) { + // If we find a different result the caller probably forgot to import a trait. + Ok(ref new_pick) if *new_pick != pick => vec![new_pick.item.container.id()], + Err(Ambiguity(ref sources)) => sources.iter().filter_map(|source| { + match *source { + // Note: this cannot come from an inherent impl, + // because the first probing succeeded. + ImplSource(def) => self.tcx.trait_id_of_impl(def), + TraitSource(_) => None, } - _ => Vec::new(), - }; + }).collect(), + _ => Vec::new(), + }; - return Err(IllegalSizedBound(candidates)); + return Err(IllegalSizedBound(candidates, needs_mut)); } Ok(result.callee) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 9820ede5b5c4..a30b7faca0db 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -560,7 +560,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } - MethodError::IllegalSizedBound(candidates) => { + MethodError::IllegalSizedBound(candidates, needs_mut) => { let msg = format!("the `{}` method cannot be invoked on a trait object", item_name); let mut err = self.sess().struct_span_err(span, &msg); if !candidates.is_empty() { @@ -576,6 +576,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); self.suggest_use_candidates(&mut err, help, candidates); } + if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind { + let trait_type = match mutability { + hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type), + hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type), + }; + if needs_mut { + err.note(&format!("you need `{}` instead", trait_type)); + } + } err.emit(); } diff --git a/src/test/ui/not-panic/not-panic-safe.stderr b/src/test/ui/not-panic/not-panic-safe.stderr index aa18b923044c..2ae5ba523a70 100644 --- a/src/test/ui/not-panic/not-panic-safe.stderr +++ b/src/test/ui/not-panic/not-panic-safe.stderr @@ -8,6 +8,7 @@ LL | assert::<&mut i32>(); | ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary | = help: the trait `std::panic::UnwindSafe` is not implemented for `&mut i32` + = note: `std::panic::UnwindSafe` is implemented for `&i32` error: aborting due to previous error diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/parser/lex-bad-char-literals-6.stderr index a7bbe05e94b7..4792aacefe5e 100644 --- a/src/test/ui/parser/lex-bad-char-literals-6.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-6.stderr @@ -35,6 +35,7 @@ LL | if x == y {} | ^^ no implementation for `&str == char` | = help: the trait `std::cmp::PartialEq` is not implemented for `&str` + = note: `std::cmp::PartialEq` is implemented for `&mut str` error[E0308]: mismatched types --> $DIR/lex-bad-char-literals-6.rs:15:20 @@ -52,6 +53,7 @@ LL | if x == z {} | ^^ no implementation for `&str == char` | = help: the trait `std::cmp::PartialEq` is not implemented for `&str` + = note: `std::cmp::PartialEq` is implemented for `&mut str` error: aborting due to 6 previous errors diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.rs b/src/test/ui/suggestions/imm-ref-trait-object-literal.rs new file mode 100644 index 000000000000..22ca6dde45ee --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.rs @@ -0,0 +1,14 @@ +trait Trait {} + +struct S; + +impl<'a> Trait for &'a mut S {} + +fn foo(_: X) {} + + +fn main() { + let s = S; + foo(&s); //~ ERROR the trait bound `&S: Trait` is not satisfied + foo(s); //~ ERROR the trait bound `S: Trait` is not satisfied +} diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr new file mode 100644 index 000000000000..ccaceefacd73 --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr @@ -0,0 +1,30 @@ +error[E0277]: the trait bound `&S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal.rs:12:7 + | +LL | fn foo(_: X) {} + | --- ----- required by this bound in `foo` +... +LL | foo(&s); + | -^ + | | + | the trait `Trait` is not implemented for `&S` + | help: consider changing this borrow's mutability: `&mut` + | + = help: the following implementations were found: + <&'a mut S as Trait> + +error[E0277]: the trait bound `S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal.rs:13:7 + | +LL | fn foo(_: X) {} + | --- ----- required by this bound in `foo` +... +LL | foo(s); + | ^ the trait `Trait` is not implemented for `S` + | + = help: the following implementations were found: + <&'a mut S as Trait> + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/imm-ref-trait-object.rs b/src/test/ui/suggestions/imm-ref-trait-object.rs new file mode 100644 index 000000000000..288d6c699f59 --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object.rs @@ -0,0 +1,8 @@ +fn test(t: &dyn Iterator) -> u64 { + t.min().unwrap() //~ ERROR the `min` method cannot be invoked on a trait object +} + +fn main() { + let array = [0u64]; + test(&mut array.iter()); +} diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr new file mode 100644 index 000000000000..e272d2a73f52 --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object.stderr @@ -0,0 +1,10 @@ +error: the `min` method cannot be invoked on a trait object + --> $DIR/imm-ref-trait-object.rs:2:8 + | +LL | t.min().unwrap() + | ^^^ + | + = note: you need `&mut dyn std::iter::Iterator` instead + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index fb3e1096ad54..6af1267f26fa 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -8,6 +8,7 @@ LL | foo(String::new()); | ^^^ the trait `std::convert::From` is not implemented for `&str` | = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix + = note: `std::convert::From` is implemented for `&mut str` = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String` error: aborting due to previous error diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs new file mode 100644 index 000000000000..dcef2ada63be --- /dev/null +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -0,0 +1,23 @@ +use std::env::args; +use std::fs::File; +use std::io::{stdout, Write, BufWriter}; + +fn main() { + let mut args = args(); + let _ = args.next(); + let dest = args.next(); + + let h1; let h2; let h3; + + let fp: &dyn Write = match dest { + Some(path) => { h1 = File::create(path).unwrap(); &h1 }, + None => { h2 = stdout(); h3 = h2.lock(); &h3 } + }; + + let fp = BufWriter::new(fp); + //~^ ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + //~| ERROR the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + + writeln!(fp, "hello world").unwrap(); //~ ERROR no method named `write_fmt` found for type +} diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr new file mode 100644 index 000000000000..66dc5b66744b --- /dev/null +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -0,0 +1,41 @@ +error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied + --> $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` + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write` + = 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 + | +LL | let fp = BufWriter::new(fp); + | ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write` + = 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 + | +LL | let fp = BufWriter::new(fp); + | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` + | + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write` + = note: required by `std::io::BufWriter` + +error[E0599]: no method named `write_fmt` found for type `std::io::BufWriter<&dyn std::io::Write>` in the current scope + --> $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>` + | + = note: the method `write_fmt` exists but the following trait bounds were not satisfied: + `std::io::BufWriter<&dyn std::io::Write> : std::io::Write` + = 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 4 previous errors + +Some errors have detailed explanations: E0277, E0599. +For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr index bfc313cabdc4..069b0a4db6c6 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr @@ -8,6 +8,7 @@ LL | for (i, n) in &v.iter().enumerate() { | help: consider removing 1 leading `&`-references | = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate>` + = note: `std::iter::Iterator` is implemented for `&mut std::iter::Enumerate>` = note: required by `std::iter::IntoIterator::into_iter` error: aborting due to previous error From acd6540a74e5e83ce6d24c696ad833b6f80027b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 3 Oct 2019 17:39:58 -0700 Subject: [PATCH 222/545] Tweak wording --- src/librustc/traits/error_reporting.rs | 3 ++- src/librustc_typeck/check/method/suggest.rs | 2 +- src/test/ui/not-panic/not-panic-safe.stderr | 2 +- src/test/ui/parser/lex-bad-char-literals-6.stderr | 4 ++-- src/test/ui/suggestions/imm-ref-trait-object.stderr | 2 +- src/test/ui/suggestions/into-str.stderr | 2 +- src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr | 6 +++--- src/test/ui/suggestions/suggest-remove-refs-1.stderr | 2 +- 8 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index f85ba1459f5f..ecd27fa99676 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1164,9 +1164,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } else { err.note(&format!( - "`{}` is implemented for `{:?}`", + "`{}` is implemented for `{:?}`, but not for `{:?}`", trait_ref, trait_type, + trait_ref.skip_binder().self_ty(), )); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index a30b7faca0db..0ffccc03e041 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -582,7 +582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type), }; if needs_mut { - err.note(&format!("you need `{}` instead", trait_type)); + err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty)); } } err.emit(); diff --git a/src/test/ui/not-panic/not-panic-safe.stderr b/src/test/ui/not-panic/not-panic-safe.stderr index 2ae5ba523a70..2362ccd32de9 100644 --- a/src/test/ui/not-panic/not-panic-safe.stderr +++ b/src/test/ui/not-panic/not-panic-safe.stderr @@ -8,7 +8,7 @@ LL | assert::<&mut i32>(); | ^^^^^^^^^^^^^^^^^^ `&mut i32` may not be safely transferred across an unwind boundary | = help: the trait `std::panic::UnwindSafe` is not implemented for `&mut i32` - = note: `std::panic::UnwindSafe` is implemented for `&i32` + = note: `std::panic::UnwindSafe` is implemented for `&i32`, but not for `&mut i32` error: aborting due to previous error diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/parser/lex-bad-char-literals-6.stderr index 4792aacefe5e..dc6e1e6e972c 100644 --- a/src/test/ui/parser/lex-bad-char-literals-6.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-6.stderr @@ -35,7 +35,7 @@ LL | if x == y {} | ^^ no implementation for `&str == char` | = help: the trait `std::cmp::PartialEq` is not implemented for `&str` - = note: `std::cmp::PartialEq` is implemented for `&mut str` + = note: `std::cmp::PartialEq` is implemented for `&mut str`, but not for `&str` error[E0308]: mismatched types --> $DIR/lex-bad-char-literals-6.rs:15:20 @@ -53,7 +53,7 @@ LL | if x == z {} | ^^ no implementation for `&str == char` | = help: the trait `std::cmp::PartialEq` is not implemented for `&str` - = note: `std::cmp::PartialEq` is implemented for `&mut str` + = note: `std::cmp::PartialEq` is implemented for `&mut str`, but not for `&str` error: aborting due to 6 previous errors diff --git a/src/test/ui/suggestions/imm-ref-trait-object.stderr b/src/test/ui/suggestions/imm-ref-trait-object.stderr index e272d2a73f52..9185eaa65c06 100644 --- a/src/test/ui/suggestions/imm-ref-trait-object.stderr +++ b/src/test/ui/suggestions/imm-ref-trait-object.stderr @@ -4,7 +4,7 @@ error: the `min` method cannot be invoked on a trait object LL | t.min().unwrap() | ^^^ | - = note: you need `&mut dyn std::iter::Iterator` instead + = note: you need `&mut dyn std::iter::Iterator` instead of `&dyn std::iter::Iterator` error: aborting due to previous error diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr index 6af1267f26fa..a1e1f4d13572 100644 --- a/src/test/ui/suggestions/into-str.stderr +++ b/src/test/ui/suggestions/into-str.stderr @@ -8,7 +8,7 @@ LL | foo(String::new()); | ^^^ the trait `std::convert::From` is not implemented for `&str` | = note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix - = note: `std::convert::From` is implemented for `&mut str` + = note: `std::convert::From` is implemented for `&mut str`, but not for `&str` = note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String` error: aborting due to previous error 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 66dc5b66744b..daa8e1162d19 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -4,7 +4,7 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis LL | let fp = BufWriter::new(fp); | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` | - = note: `std::io::Write` is implemented for `&mut dyn std::io::Write` + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` = note: required by `std::io::BufWriter::::new` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied @@ -13,7 +13,7 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` | - = note: `std::io::Write` is implemented for `&mut dyn std::io::Write` + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` = note: required by `std::io::BufWriter` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied @@ -22,7 +22,7 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satis LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` | - = note: `std::io::Write` is implemented for `&mut dyn std::io::Write` + = note: `std::io::Write` is implemented for `&mut dyn std::io::Write`, but not for `&dyn std::io::Write` = note: required by `std::io::BufWriter` error[E0599]: no method named `write_fmt` found for type `std::io::BufWriter<&dyn std::io::Write>` in the current scope diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr index 069b0a4db6c6..04d17a16cc35 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr @@ -8,7 +8,7 @@ LL | for (i, n) in &v.iter().enumerate() { | help: consider removing 1 leading `&`-references | = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate>` - = note: `std::iter::Iterator` is implemented for `&mut std::iter::Enumerate>` + = note: `std::iter::Iterator` is implemented for `&mut std::iter::Enumerate>`, but not for `&std::iter::Enumerate>` = note: required by `std::iter::IntoIterator::into_iter` error: aborting due to previous error From 722bb515e2b5f93aad4cfdbc3de664af9ac445c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 5 Oct 2019 10:41:24 -0700 Subject: [PATCH 223/545] Obligation must apply modulo regions --- src/librustc/traits/error_reporting.rs | 4 +++- src/librustc/traits/query/evaluate_obligation.rs | 2 +- src/test/ui/parser/lex-bad-char-literals-6.stderr | 2 -- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index ecd27fa99676..1e8f699b520f 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1149,7 +1149,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { new_trait_ref.to_predicate(), ); - if self.predicate_may_hold(&new_obligation) { + if self.evaluate_obligation_no_overflow( + &new_obligation, + ).must_apply_modulo_regions() { let sp = self.tcx.sess.source_map() .span_take_while(span, |c| c.is_whitespace() || *c == '&'); if points_at_arg && diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc/traits/query/evaluate_obligation.rs index 17684df7e9b8..0d426cab9b75 100644 --- a/src/librustc/traits/query/evaluate_obligation.rs +++ b/src/librustc/traits/query/evaluate_obligation.rs @@ -56,7 +56,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. - fn evaluate_obligation_no_overflow( + crate fn evaluate_obligation_no_overflow( &self, obligation: &PredicateObligation<'tcx>, ) -> EvaluationResult { diff --git a/src/test/ui/parser/lex-bad-char-literals-6.stderr b/src/test/ui/parser/lex-bad-char-literals-6.stderr index dc6e1e6e972c..a7bbe05e94b7 100644 --- a/src/test/ui/parser/lex-bad-char-literals-6.stderr +++ b/src/test/ui/parser/lex-bad-char-literals-6.stderr @@ -35,7 +35,6 @@ LL | if x == y {} | ^^ no implementation for `&str == char` | = help: the trait `std::cmp::PartialEq` is not implemented for `&str` - = note: `std::cmp::PartialEq` is implemented for `&mut str`, but not for `&str` error[E0308]: mismatched types --> $DIR/lex-bad-char-literals-6.rs:15:20 @@ -53,7 +52,6 @@ LL | if x == z {} | ^^ no implementation for `&str == char` | = help: the trait `std::cmp::PartialEq` is not implemented for `&str` - = note: `std::cmp::PartialEq` is implemented for `&mut str`, but not for `&str` error: aborting due to 6 previous errors From 4fcaa4a283faa1c5b6b18f7c1dad002dbc1f7bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 5 Oct 2019 11:37:21 -0700 Subject: [PATCH 224/545] review comments --- src/librustc/hir/mod.rs | 7 +++++ src/librustc_typeck/check/method/mod.rs | 8 +++--- src/librustc_typeck/check/method/suggest.rs | 30 +++++++++++---------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 30b050366887..3d473ec0bc7d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1053,6 +1053,13 @@ impl Mutability { MutImmutable => MutImmutable, } } + + pub fn not(self) -> Self { + match self { + MutMutable => MutImmutable, + MutImmutable => MutMutable, + } + } } #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Hash, HashStable)] diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 4522be21cab5..5851a074fa3f 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -215,10 +215,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut needs_mut = false; if let ty::Ref(region, t_type, mutability) = self_ty.kind { - let trait_type = match mutability { - hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type), - hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type), - }; + let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { + ty: t_type, + mutbl: mutability.not(), + }); match self.lookup_probe( span, segment.ident, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 0ffccc03e041..c3ca58c834db 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -564,24 +564,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let msg = format!("the `{}` method cannot be invoked on a trait object", item_name); let mut err = self.sess().struct_span_err(span, &msg); if !candidates.is_empty() { - let help = format!("{an}other candidate{s} {were} found in the following \ - trait{s}, perhaps add a `use` for {one_of_them}:", - an = if candidates.len() == 1 {"an" } else { "" }, - s = pluralise!(candidates.len()), - were = if candidates.len() == 1 { "was" } else { "were" }, - one_of_them = if candidates.len() == 1 { - "it" - } else { - "one_of_them" - }); + let help = format!( + "{an}other candidate{s} {were} found in the following trait{s}, perhaps \ + add a `use` for {one_of_them}:", + an = if candidates.len() == 1 {"an" } else { "" }, + s = pluralise!(candidates.len()), + were = if candidates.len() == 1 { "was" } else { "were" }, + one_of_them = if candidates.len() == 1 { + "it" + } else { + "one_of_them" + }, + ); self.suggest_use_candidates(&mut err, help, candidates); } if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind { - let trait_type = match mutability { - hir::Mutability::MutMutable => self.tcx.mk_imm_ref(region, t_type), - hir::Mutability::MutImmutable => self.tcx.mk_mut_ref(region, t_type), - }; if needs_mut { + let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { + ty: t_type, + mutbl: mutability.not(), + }); err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty)); } } From 2c6bcac535942533489bccdd39515babd0ebb15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 6 Oct 2019 18:38:15 -0700 Subject: [PATCH 225/545] review comments --- src/librustc/hir/mod.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3d473ec0bc7d..6a43fa8da16d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1054,7 +1054,7 @@ impl Mutability { } } - pub fn not(self) -> Self { + pub fn invert(self) -> Self { match self { MutMutable => MutImmutable, MutImmutable => MutMutable, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 5851a074fa3f..434ead50e042 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -217,7 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::Ref(region, t_type, mutability) = self_ty.kind { let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { ty: t_type, - mutbl: mutability.not(), + mutbl: mutability.invert(), }); match self.lookup_probe( span, diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index c3ca58c834db..c19ea5780236 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -582,7 +582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if needs_mut { let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { ty: t_type, - mutbl: mutability.not(), + mutbl: mutability.invert(), }); err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty)); } From faf8a2af7aab765c832c9045f08421e42ddb0b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 9 Oct 2019 11:42:29 -0700 Subject: [PATCH 226/545] Only suggest change mut if vars are resolved --- src/librustc/traits/error_reporting.rs | 6 ++++++ src/test/ui/suggestions/suggest-remove-refs-1.stderr | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 1e8f699b520f..9eb91569ed5c 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1134,6 +1134,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { { // Do not suggest removal of borrow from type arguments. return; } + let trait_ref = self.resolve_vars_if_possible(trait_ref); + if trait_ref.has_infer_types() { + // Do not ICE while trying to find if a reborrow would succeed on a trait with + // unresolved bindings. + return; + } if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind { let trait_type = match mutability { diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr index 04d17a16cc35..bfc313cabdc4 100644 --- a/src/test/ui/suggestions/suggest-remove-refs-1.stderr +++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr @@ -8,7 +8,6 @@ LL | for (i, n) in &v.iter().enumerate() { | help: consider removing 1 leading `&`-references | = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate>` - = note: `std::iter::Iterator` is implemented for `&mut std::iter::Enumerate>`, but not for `&std::iter::Enumerate>` = note: required by `std::iter::IntoIterator::into_iter` error: aborting due to previous error From 89cc0467a2a5af872f05830be68b60adf4669e01 Mon Sep 17 00:00:00 2001 From: ben Date: Thu, 10 Oct 2019 08:11:31 +1300 Subject: [PATCH 227/545] Pretty print raw pointers in consts as '{pointer}'. --- src/librustc/ty/print/pretty.rs | 1 + src/test/ui/const-generics/raw-ptr-const-param.stderr | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 8cd637468ccd..c4967f8d66da 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -919,6 +919,7 @@ pub trait PrettyPrinter<'tcx>: }, (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Char) => p!(write("{:?}", ::std::char::from_u32(data as u32).unwrap())), + (ConstValue::Scalar(_), ty::RawPtr(_)) => p!(write("{{pointer}}")), (ConstValue::Scalar(Scalar::Ptr(ptr)), ty::FnPtr(_)) => { let instance = { let alloc_map = self.tcx().alloc_map.lock(); diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index 31db64d30a7d..75b4c0a0a3de 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -10,10 +10,10 @@ error[E0308]: mismatched types --> $DIR/raw-ptr-const-param.rs:7:38 | LL | let _: Const<{15 as *const _}> = Const::<{10 as *const _}>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Scalar(0x000000000000000f) : *const u32`, found `Scalar(0x000000000000000a) : *const u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `{pointer}`, found `{pointer}` | - = note: expected type `Const` - found type `Const` + = note: expected type `Const<{pointer}>` + found type `Const<{pointer}>` error: aborting due to previous error From 4bb1592402003184cd73c6ee5b135df084ea5abc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 9 Oct 2019 12:25:48 -0700 Subject: [PATCH 228/545] Suggest `if let` on `let` refutable binding --- src/librustc_mir/hair/pattern/check_match.rs | 36 ++++++++++++++----- .../ui/consts/const-match-check.eval1.stderr | 7 ++++ .../ui/consts/const-match-check.eval2.stderr | 7 ++++ .../consts/const-match-check.matchck.stderr | 28 +++++++++++++++ src/test/ui/empty/empty-never-array.stderr | 7 ++++ src/test/ui/error-codes/E0005.stderr | 7 ++++ ...eature-gate-exhaustive-patterns.nll.stderr | 16 +++++++++ .../feature-gate-exhaustive-patterns.stderr | 7 ++++ src/test/ui/issues/issue-31561.stderr | 7 ++++ .../match/non-exhaustive-defined-here.stderr | 28 +++++++++++++++ ...recursive-types-are-not-uninhabited.stderr | 7 ++++ src/test/ui/refutable-pattern-errors.stderr | 7 ++++ .../uninhabited-irrefutable.stderr | 7 ++++ .../uninhabited-matches-feature-gated.stderr | 7 ++++ 14 files changed, 169 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index c521b7352214..9bed4fb66ea9 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -62,12 +62,13 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { fn visit_local(&mut self, loc: &'tcx hir::Local) { intravisit::walk_local(self, loc); - self.check_irrefutable(&loc.pat, match loc.source { - hir::LocalSource::Normal => "local binding", - hir::LocalSource::ForLoopDesugar => "`for` loop binding", - hir::LocalSource::AsyncFn => "async fn binding", - hir::LocalSource::AwaitDesugar => "`await` future binding", - }); + let (msg, sp) = match loc.source { + hir::LocalSource::Normal => ("local binding", Some(loc.span)), + hir::LocalSource::ForLoopDesugar => ("`for` loop binding", None), + hir::LocalSource::AsyncFn => ("async fn binding", None), + hir::LocalSource::AwaitDesugar => ("`await` future binding", None), + }; + self.check_irrefutable(&loc.pat, msg, sp); // Check legality of move bindings and `@` patterns. self.check_patterns(false, &loc.pat); @@ -77,7 +78,7 @@ impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { intravisit::walk_body(self, body); for param in &body.params { - self.check_irrefutable(¶m.pat, "function argument"); + self.check_irrefutable(¶m.pat, "function argument", None); self.check_patterns(false, ¶m.pat); } } @@ -242,7 +243,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { }) } - fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) { + fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str, sp: Option) { let module = self.tcx.hir().get_module_parent(pat.hir_id); MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |ref mut cx| { let mut patcx = PatCtxt::new(self.tcx, @@ -266,18 +267,35 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { "refutable pattern in {}: {} not covered", origin, joined_patterns ); - match &pat.kind { + let suggest_if_let = match &pat.kind { hir::PatKind::Path(hir::QPath::Resolved(None, path)) if path.segments.len() == 1 && path.segments[0].args.is_none() => { const_not_var(&mut err, cx.tcx, pat, path); + false } _ => { err.span_label( pat.span, pattern_not_covered_label(&witnesses, &joined_patterns), ); + true } + }; + + if let (Some(span), true) = (sp, suggest_if_let) { + err.note("`let` bindings require an \"irrefutable pattern\", like a `struct` or \ + an `enum` with only one variant"); + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + err.span_suggestion( + span, + "you might want to use `if let` to ignore the variant that isn't matched", + format!("if {} {{ /* */ }}", &snippet[..snippet.len() - 1]), + Applicability::HasPlaceholders, + ); + } + err.note("for more information, visit \ + https://doc.rust-lang.org/book/ch18-02-refutability.html"); } adt_defined_here(cx, &mut err, pattern_ty, &witnesses); diff --git a/src/test/ui/consts/const-match-check.eval1.stderr b/src/test/ui/consts/const-match-check.eval1.stderr index 24d2e3ce5393..087cc3c86a68 100644 --- a/src/test/ui/consts/const-match-check.eval1.stderr +++ b/src/test/ui/consts/const-match-check.eval1.stderr @@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1 | LL | A = { let 0 = 0; 0 }, | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | A = { if let 0 = 0 { /* */ } 0 }, + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.eval2.stderr b/src/test/ui/consts/const-match-check.eval2.stderr index 5d59d06f7982..80d9f794bc1d 100644 --- a/src/test/ui/consts/const-match-check.eval2.stderr +++ b/src/test/ui/consts/const-match-check.eval2.stderr @@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1 | LL | let x: [i32; { let 0 = 0; 0 }] = []; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | let x: [i32; { if let 0 = 0 { /* */ } 0 }] = []; + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/consts/const-match-check.matchck.stderr b/src/test/ui/consts/const-match-check.matchck.stderr index 6d74c26f9f7a..e6b2f212bb43 100644 --- a/src/test/ui/consts/const-match-check.matchck.stderr +++ b/src/test/ui/consts/const-match-check.matchck.stderr @@ -3,24 +3,52 @@ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1 | LL | const X: i32 = { let 0 = 0; 0 }; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered --> $DIR/const-match-check.rs:8:23 | LL | static Y: i32 = { let 0 = 0; 0 }; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | static Y: i32 = { if let 0 = 0 { /* */ } 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered --> $DIR/const-match-check.rs:13:26 | LL | const X: i32 = { let 0 = 0; 0 }; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^ error[E0005]: refutable pattern in local binding: `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered --> $DIR/const-match-check.rs:19:26 | LL | const X: i32 = { let 0 = 0; 0 }; | ^ patterns `std::i32::MIN..=-1i32` and `1i32..=std::i32::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | const X: i32 = { if let 0 = 0 { /* */ } 0 }; + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/empty/empty-never-array.stderr b/src/test/ui/empty/empty-never-array.stderr index 7d59d553d88f..d865b59f0b94 100644 --- a/src/test/ui/empty/empty-never-array.stderr +++ b/src/test/ui/empty/empty-never-array.stderr @@ -11,6 +11,13 @@ LL | | } ... LL | let Helper::U(u) = Helper::T(t, []); | ^^^^^^^^^^^^ pattern `T(_, _)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Helper::U(u) = Helper::T(t, []) { /* */ } + | error[E0381]: use of possibly-uninitialized variable: `u` --> $DIR/empty-never-array.rs:12:5 diff --git a/src/test/ui/error-codes/E0005.stderr b/src/test/ui/error-codes/E0005.stderr index 56a4bcffc81a..577c6e886d52 100644 --- a/src/test/ui/error-codes/E0005.stderr +++ b/src/test/ui/error-codes/E0005.stderr @@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `None` not covered | LL | let Some(y) = x; | ^^^^^^^ pattern `None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Some(y) = x { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr new file mode 100644 index 000000000000..d77fbc1e8239 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr @@ -0,0 +1,16 @@ +error[E0005]: refutable pattern in local binding: `Err(_)` not covered + --> $DIR/feature-gate-exhaustive-patterns.rs:7:9 + | +LL | let Ok(_x) = foo(); + | ^^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Ok(_x) = foo() { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0005`. diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr index dd4ca1f67e33..d77fbc1e8239 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered | LL | let Ok(_x) = foo(); | ^^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Ok(_x) = foo() { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31561.stderr b/src/test/ui/issues/issue-31561.stderr index 9ec26b024bce..d3c8e876b8a8 100644 --- a/src/test/ui/issues/issue-31561.stderr +++ b/src/test/ui/issues/issue-31561.stderr @@ -12,6 +12,13 @@ LL | | } ... LL | let Thing::Foo(y) = Thing::Foo(1); | ^^^^^^^^^^^^^ patterns `Bar` and `Baz` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Thing::Foo(y) = Thing::Foo(1) { /* */ } + | error: aborting due to previous error diff --git a/src/test/ui/match/non-exhaustive-defined-here.stderr b/src/test/ui/match/non-exhaustive-defined-here.stderr index 25b8bbdab2d8..e5f01174ac1b 100644 --- a/src/test/ui/match/non-exhaustive-defined-here.stderr +++ b/src/test/ui/match/non-exhaustive-defined-here.stderr @@ -41,6 +41,13 @@ LL | | } ... LL | let E::A = e; | ^^^^ patterns `B` and `C` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let E::A = e { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `&B` and `&C` not covered --> $DIR/non-exhaustive-defined-here.rs:40:11 @@ -85,6 +92,13 @@ LL | | } ... LL | let E::A = e; | ^^^^ patterns `&B` and `&C` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let E::A = e { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `&&mut &B` and `&&mut &C` not covered --> $DIR/non-exhaustive-defined-here.rs:48:11 @@ -129,6 +143,13 @@ LL | | } ... LL | let E::A = e; | ^^^^ patterns `&&mut &B` and `&&mut &C` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let E::A = e { /* */ } + | error[E0004]: non-exhaustive patterns: `None` not covered --> $DIR/non-exhaustive-defined-here.rs:65:11 @@ -163,6 +184,13 @@ LL | | } ... LL | let Opt::Some(ref _x) = e; | ^^^^^^^^^^^^^^^^^ pattern `None` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Opt::Some(ref _x) = e { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr index b9385952fafa..f9ae75b18317 100644 --- a/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr +++ b/src/test/ui/recursion/recursive-types-are-not-uninhabited.stderr @@ -3,6 +3,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered | LL | let Ok(x) = res; | ^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Ok(x) = res { /* */ } + | error[E0381]: use of possibly-uninitialized variable: `x` --> $DIR/recursive-types-are-not-uninhabited.rs:8:5 diff --git a/src/test/ui/refutable-pattern-errors.stderr b/src/test/ui/refutable-pattern-errors.stderr index 3b13e25293d5..0cf5d9cd5f12 100644 --- a/src/test/ui/refutable-pattern-errors.stderr +++ b/src/test/ui/refutable-pattern-errors.stderr @@ -9,6 +9,13 @@ error[E0005]: refutable pattern in local binding: `(std::i32::MIN..=0i32, _)` an | LL | let (1, (Some(1), 2..=3)) = (1, (None, 2)); | ^^^^^^^^^^^^^^^^^^^^^ patterns `(std::i32::MIN..=0i32, _)` and `(2i32..=std::i32::MAX, _)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { /* */ } + | error: aborting due to 2 previous errors diff --git a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr index 29ff1dc37608..26e1be34ea75 100644 --- a/src/test/ui/uninhabited/uninhabited-irrefutable.stderr +++ b/src/test/ui/uninhabited/uninhabited-irrefutable.stderr @@ -12,6 +12,13 @@ LL | | } ... LL | let Foo::D(_y) = x; | ^^^^^^^^^^ pattern `A(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Foo::D(_y) = x { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr index 25519ab2d6a7..a49344e45cec 100644 --- a/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr +++ b/src/test/ui/uninhabited/uninhabited-matches-feature-gated.stderr @@ -51,6 +51,13 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered | LL | let Ok(x) = x; | ^^^^^ pattern `Err(_)` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html +help: you might want to use `if let` to ignore the variant that isn't matched + | +LL | if let Ok(x) = x { /* */ } + | error: aborting due to 7 previous errors From a0342c896597e66f8f3c5dbe22850ec6b5003698 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 9 Oct 2019 20:06:15 +0100 Subject: [PATCH 229/545] Revert "Make `into` schedule drop for the destination" This reverts commit 37026837a3f23486d3cf1009d9136927168ddb33. --- src/librustc_mir/build/block.rs | 70 ++--- src/librustc_mir/build/expr/as_rvalue.rs | 7 +- src/librustc_mir/build/expr/as_temp.rs | 11 +- src/librustc_mir/build/expr/into.rs | 46 +--- src/librustc_mir/build/into.rs | 25 +- src/librustc_mir/build/matches/mod.rs | 20 +- src/librustc_mir/build/mod.rs | 10 +- src/librustc_mir/build/scope.rs | 14 +- src/test/mir-opt/box_expr.rs | 21 +- src/test/mir-opt/issue-62289.rs | 45 ++- .../async-fn-size-uninit-locals.rs | 2 +- src/test/ui/drop/dynamic-drop-async.rs | 149 ++++------ src/test/ui/drop/dynamic-drop.rs | 259 +++++++----------- 13 files changed, 230 insertions(+), 449 deletions(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index f9440866e492..7353ca9285dd 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -1,22 +1,18 @@ use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::build::ForGuard::OutsideGuard; use crate::build::matches::ArmHasGuard; -use crate::build::scope::DropKind; use crate::hair::*; -use rustc::middle::region; use rustc::mir::*; use rustc::hir; use syntax_pos::Span; impl<'a, 'tcx> Builder<'a, 'tcx> { - pub fn ast_block( - &mut self, - destination: &Place<'tcx>, - scope: Option, - block: BasicBlock, - ast_block: &'tcx hir::Block, - source_info: SourceInfo, - ) -> BlockAnd<()> { + pub fn ast_block(&mut self, + destination: &Place<'tcx>, + block: BasicBlock, + ast_block: &'tcx hir::Block, + source_info: SourceInfo) + -> BlockAnd<()> { let Block { region_scope, opt_destruction_scope, @@ -25,61 +21,37 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr, targeted_by_break, safety_mode - } = self.hir.mirror(ast_block); + } = + self.hir.mirror(ast_block); self.in_opt_scope(opt_destruction_scope.map(|de|(de, source_info)), move |this| { this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| { if targeted_by_break { // This is a `break`-able block let exit_block = this.cfg.start_new_block(); - if let Some(scope) = scope { - // Breakable blocks assign to their destination on each - // `break`, as well as when they exit normally. So we - // can't schedule the drop in the last expression like - // normal blocks do. - let local = destination.as_local() - .expect("cannot schedule drop of non-Local place"); - this.schedule_drop(span, scope, local, DropKind::Value); - } let block_exit = this.in_breakable_scope( None, exit_block, destination.clone(), |this| { - this.ast_block_stmts( - destination, - None, - block, - span, - stmts, - expr, - safety_mode, - ) + this.ast_block_stmts(destination, block, span, stmts, expr, + safety_mode) }); this.cfg.terminate(unpack!(block_exit), source_info, TerminatorKind::Goto { target: exit_block }); exit_block.unit() } else { - this.ast_block_stmts( - destination, - scope, - block, - span, - stmts, - expr, - safety_mode, - ) + this.ast_block_stmts(destination, block, span, stmts, expr, + safety_mode) } }) }) } - fn ast_block_stmts( - &mut self, - destination: &Place<'tcx>, - scope: Option, - mut block: BasicBlock, - span: Span, - stmts: Vec>, - expr: Option>, - safety_mode: BlockSafety, - ) -> BlockAnd<()> { + fn ast_block_stmts(&mut self, + destination: &Place<'tcx>, + mut block: BasicBlock, + span: Span, + stmts: Vec>, + expr: Option>, + safety_mode: BlockSafety) + -> BlockAnd<()> { let this = self; // This convoluted structure is to avoid using recursion as we walk down a list @@ -205,7 +177,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.block_context.currently_ignores_tail_results(); this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored }); - unpack!(block = this.into(destination, scope, block, expr)); + unpack!(block = this.into(destination, block, expr)); let popped = this.block_context.pop(); assert!(popped.map_or(false, |bf|bf.is_tail_expr())); diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index bd9edc56872b..87d95a751534 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -136,14 +136,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg .push_assign(block, source_info, &Place::from(result), box_); - // Initialize the box contents. No scope is needed since the - // `Box` is already scheduled to be dropped. + // initialize the box contents: unpack!( block = this.into( &Place::from(result).deref(), - None, - block, - value + block, value ) ); block.and(Rvalue::Use(Operand::Move(Place::from(result)))) diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs index bd20f27c945c..18332ed68f8b 100644 --- a/src/librustc_mir/build/expr/as_temp.rs +++ b/src/librustc_mir/build/expr/as_temp.rs @@ -109,7 +109,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - unpack!(block = this.into(temp_place, temp_lifetime, block, expr)); + unpack!(block = this.into(temp_place, block, expr)); + + if let Some(temp_lifetime) = temp_lifetime { + this.schedule_drop( + expr_span, + temp_lifetime, + temp, + DropKind::Value, + ); + } block.and(temp) } diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index c262215ab9be..8a6bc5a2a764 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -2,9 +2,7 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; -use crate::build::scope::DropKind; use crate::hair::*; -use rustc::middle::region; use rustc::mir::*; use rustc::ty; @@ -13,18 +11,15 @@ use rustc_target::spec::abi::Abi; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which /// is assumed to be uninitialized. - /// If a `drop_scope` is provided, `destination` is scheduled to be dropped - /// in `scope` once it has been initialized. pub fn into_expr( &mut self, destination: &Place<'tcx>, - scope: Option, mut block: BasicBlock, expr: Expr<'tcx>, ) -> BlockAnd<()> { debug!( - "into_expr(destination={:?}, scope={:?}, block={:?}, expr={:?})", - destination, scope, block, expr + "into_expr(destination={:?}, block={:?}, expr={:?})", + destination, block, expr ); // since we frequently have to reference `self` from within a @@ -40,14 +35,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => false, }; - let schedule_drop = move |this: &mut Self| { - if let Some(drop_scope) = scope { - let local = destination.as_local() - .expect("cannot schedule drop of non-Local place"); - this.schedule_drop(expr_span, drop_scope, local, DropKind::Value); - } - }; - if !expr_is_block_or_scope { this.block_context.push(BlockFrame::SubExpr); } @@ -60,14 +47,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } => { let region_scope = (region_scope, source_info); this.in_scope(region_scope, lint_level, |this| { - this.into(destination, scope, block, value) + this.into(destination, block, value) }) } ExprKind::Block { body: ast_block } => { - this.ast_block(destination, scope, block, ast_block, source_info) + this.ast_block(destination, block, ast_block, source_info) } ExprKind::Match { scrutinee, arms } => { - this.match_expr(destination, scope, expr_span, block, scrutinee, arms) + this.match_expr(destination, expr_span, block, scrutinee, arms) } ExprKind::NeverToAny { source } => { let source = this.hir.mirror(source); @@ -80,7 +67,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This is an optimization. If the expression was a call then we already have an // unreachable block. Don't bother to terminate it and create a new one. - schedule_drop(this); if is_call { block.unit() } else { @@ -178,9 +164,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TerminatorKind::Goto { target: loop_block }, ); - // Loops assign to their destination on each `break`. Since we - // can't easily unschedule drops, we schedule the drop now. - schedule_drop(this); this.in_breakable_scope( Some(loop_block), exit_block, @@ -202,8 +185,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // introduce a unit temporary as the destination for the loop body. let tmp = this.get_unit_temp(); // Execute the body, branching back to the test. - // No scope is provided, since we've scheduled the drop above. - let body_block_end = unpack!(this.into(&tmp, None, body_block, body)); + let body_block_end = unpack!(this.into(&tmp, body_block, body)); this.cfg.terminate( body_block_end, source_info, @@ -252,14 +234,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { is_block_tail: None, }); let ptr_temp = Place::from(ptr_temp); - // No need for a scope, ptr_temp doesn't need drop - let block = unpack!(this.into(&ptr_temp, None, block, ptr)); - // Maybe we should provide a scope here so that - // `move_val_init` wouldn't leak on panic even with an - // arbitrary `val` expression, but `schedule_drop`, - // borrowck and drop elaboration all prevent us from - // dropping `ptr_temp.deref()`. - this.into(&ptr_temp.deref(), None, block, val) + let block = unpack!(this.into(&ptr_temp, block, ptr)); + this.into(&ptr_temp.deref(), block, val) } else { let args: Vec<_> = args .into_iter() @@ -289,12 +265,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { from_hir_call, }, ); - schedule_drop(this); success.unit() } } ExprKind::Use { source } => { - this.into(destination, scope, block, source) + this.into(destination, block, source) } // These cases don't actually need a destination @@ -321,7 +296,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); this.cfg .push_assign(block, source_info, destination, rvalue); - schedule_drop(this); block.unit() } ExprKind::Index { .. } | ExprKind::Deref { .. } | ExprKind::Field { .. } => { @@ -341,7 +315,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let rvalue = Rvalue::Use(this.consume_by_copy_or_move(place)); this.cfg .push_assign(block, source_info, destination, rvalue); - schedule_drop(this); block.unit() } @@ -373,7 +346,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let rvalue = unpack!(block = this.as_local_rvalue(block, expr)); this.cfg.push_assign(block, source_info, destination, rvalue); - schedule_drop(this); block.unit() } }; diff --git a/src/librustc_mir/build/into.rs b/src/librustc_mir/build/into.rs index e57f10f0b14e..077840c9ccf1 100644 --- a/src/librustc_mir/build/into.rs +++ b/src/librustc_mir/build/into.rs @@ -6,7 +6,6 @@ use crate::build::{BlockAnd, Builder}; use crate::hair::*; -use rustc::middle::region; use rustc::mir::*; pub(in crate::build) trait EvalInto<'tcx> { @@ -14,23 +13,19 @@ pub(in crate::build) trait EvalInto<'tcx> { self, builder: &mut Builder<'_, 'tcx>, destination: &Place<'tcx>, - scope: Option, block: BasicBlock, ) -> BlockAnd<()>; } impl<'a, 'tcx> Builder<'a, 'tcx> { - pub fn into( - &mut self, - destination: &Place<'tcx>, - scope: Option, - block: BasicBlock, - expr: E, - ) -> BlockAnd<()> - where - E: EvalInto<'tcx>, + pub fn into(&mut self, + destination: &Place<'tcx>, + block: BasicBlock, + expr: E) + -> BlockAnd<()> + where E: EvalInto<'tcx> { - expr.eval_into(self, destination, scope, block) + expr.eval_into(self, destination, block) } } @@ -39,11 +34,10 @@ impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> { self, builder: &mut Builder<'_, 'tcx>, destination: &Place<'tcx>, - scope: Option, block: BasicBlock, ) -> BlockAnd<()> { let expr = builder.hir.mirror(self); - builder.into_expr(destination, scope, block, expr) + builder.into_expr(destination, block, expr) } } @@ -52,9 +46,8 @@ impl<'tcx> EvalInto<'tcx> for Expr<'tcx> { self, builder: &mut Builder<'_, 'tcx>, destination: &Place<'tcx>, - scope: Option, block: BasicBlock, ) -> BlockAnd<()> { - builder.into_expr(destination, scope, block, self) + builder.into_expr(destination, block, self) } } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index e8cf827aa900..2e451fc88d95 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -102,7 +102,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pub fn match_expr( &mut self, destination: &Place<'tcx>, - destination_scope: Option, span: Span, mut block: BasicBlock, scrutinee: ExprRef<'tcx>, @@ -229,14 +228,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; // Step 5. Create everything else: the guards and the arms. - if let Some(scope) = destination_scope { - // `match` assigns to its destination in each arm. Since we can't - // easily unschedule drops, we schedule the drop now. - let local = destination.as_local() - .expect("cannot schedule drop of non-Local place"); - self.schedule_drop(span, scope, local, DropKind::Value); - } - let match_scope = self.scopes.topmost(); let arm_end_blocks: Vec<_> = arm_candidates.into_iter().map(|(arm, mut candidates)| { @@ -284,8 +275,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.source_scope = source_scope; } - // No scope is provided, since we've scheduled the drop above. - this.into(destination, None, arm_block, body) + this.into(destination, arm_block, body) }) }).collect(); @@ -321,9 +311,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } => { let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); - let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); + unpack!(block = self.into(&place, block, initializer)); - unpack!(block = self.into(&place, Some(region_scope), block, initializer)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. let source_info = self.source_info(irrefutable_pat.span); @@ -335,6 +324,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } @@ -362,10 +352,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { user_ty_span, }, } => { - let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); - unpack!(block = self.into(&place, Some(region_scope), block, initializer)); + unpack!(block = self.into(&place, block, initializer)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. let pattern_source_info = self.source_info(irrefutable_pat.span); @@ -411,6 +400,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }, ); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 9a98cf1cb88c..8c35342d324b 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -616,7 +616,6 @@ where let source_info = builder.source_info(span); let call_site_s = (call_site_scope, source_info); unpack!(block = builder.in_scope(call_site_s, LintLevel::Inherited, |builder| { - builder.schedule_drop(span, call_site_scope, RETURN_PLACE, DropKind::Value); if should_abort_on_panic(tcx, fn_def_id, abi) { builder.schedule_abort(); } @@ -647,7 +646,6 @@ where builder.cfg.terminate(unreachable_block, source_info, TerminatorKind::Unreachable); } - builder.unschedule_return_place_drop(); return_block.unit() })); assert_eq!(block, builder.return_block()); @@ -689,9 +687,7 @@ fn construct_const<'a, 'tcx>( let mut block = START_BLOCK; let ast_expr = &tcx.hir().body(body_id).value; let expr = builder.hir.mirror(ast_expr); - // We don't provide a scope because we can't unwind in constants, so won't - // need to drop the return place. - unpack!(block = builder.into_expr(&Place::return_place(), None, block, expr)); + unpack!(block = builder.into_expr(&Place::return_place(), block, expr)); let source_info = builder.source_info(span); builder.cfg.terminate(block, source_info, TerminatorKind::Return); @@ -892,9 +888,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } let body = self.hir.mirror(ast_body); - // No scope is provided, since we've scheduled the drop of the return - // place. - self.into(&Place::return_place(), None, block, body) + self.into(&Place::return_place(), block, body) } fn set_correct_source_scope_for_arg( diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 6206bfd9f3ea..a749b4263ea6 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -513,7 +513,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(value) = value { debug!("stmt_expr Break val block_context.push(SubExpr)"); self.block_context.push(BlockFrame::SubExpr); - unpack!(block = self.into(&destination, None, block, value)); + unpack!(block = self.into(&destination, block, value)); self.block_context.pop(); } else { self.cfg.push_assign_unit(block, source_info, &destination) @@ -1070,18 +1070,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { success_block } - /// Unschedules the drop of the return place. - /// - /// If the return type of a function requires drop, then we schedule it - /// in the outermost scope so that it's dropped if there's a panic while - /// we drop any local variables. But we don't want to drop it if we - /// return normally. - crate fn unschedule_return_place_drop(&mut self) { - assert_eq!(self.scopes.len(), 1); - assert!(self.scopes.scopes[0].drops.len() <= 1); - self.scopes.scopes[0].drops.clear(); - } - // `match` arm scopes // ================== /// Unschedules any drops in the top scope. diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs index 76098731947f..8dc6b73edf6d 100644 --- a/src/test/mir-opt/box_expr.rs +++ b/src/test/mir-opt/box_expr.rs @@ -41,36 +41,33 @@ impl Drop for S { // // bb2: { // _1 = move _2; -// drop(_2) -> [return: bb5, unwind: bb4]; +// drop(_2) -> bb4; // } // // bb3 (cleanup): { // drop(_2) -> bb1; // } // -// bb4 (cleanup): { -// drop(_1) -> bb1; -// } -// -// bb5: { +// bb4: { // StorageDead(_2); // StorageLive(_3); // StorageLive(_4); // _4 = move _1; -// _3 = const std::mem::drop::>(move _4) -> [return: bb6, unwind: bb7]; +// _3 = const std::mem::drop::>(move _4) -> [return: bb5, unwind: bb7]; // } // -// bb6: { +// bb5: { // StorageDead(_4); // StorageDead(_3); // _0 = (); // drop(_1) -> bb8; // } -// -// bb7 (cleanup): { -// drop(_4) -> bb4; +// bb6 (cleanup): { +// drop(_1) -> bb1; +// } +// bb7 (cleanup): { +// drop(_4) -> bb6; // } -// // bb8: { // StorageDead(_1); // return; diff --git a/src/test/mir-opt/issue-62289.rs b/src/test/mir-opt/issue-62289.rs index e8dd56cbbae2..a3b517e9bca8 100644 --- a/src/test/mir-opt/issue-62289.rs +++ b/src/test/mir-opt/issue-62289.rs @@ -24,7 +24,7 @@ fn main() { // StorageLive(_3); // StorageLive(_4); // _4 = std::option::Option::::None; -// _3 = const as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb4]; +// _3 = const as std::ops::Try>::into_result(move _4) -> [return: bb2, unwind: bb3]; // } // bb1 (cleanup): { // resume; @@ -32,63 +32,60 @@ fn main() { // bb2: { // StorageDead(_4); // _5 = discriminant(_3); -// switchInt(move _5) -> [0isize: bb11, 1isize: bb6, otherwise: bb5]; +// switchInt(move _5) -> [0isize: bb10, 1isize: bb5, otherwise: bb4]; // } // bb3 (cleanup): { -// drop(_0) -> bb1; +// drop(_2) -> bb1; // } -// bb4 (cleanup): { -// drop(_2) -> bb3; -// } -// bb5: { +// bb4: { // unreachable; // } -// bb6: { +// bb5: { // StorageLive(_6); // _6 = ((_3 as Err).0: std::option::NoneError); // StorageLive(_8); // StorageLive(_9); // _9 = _6; -// _8 = const >::from(move _9) -> [return: bb8, unwind: bb4]; +// _8 = const >::from(move _9) -> [return: bb7, unwind: bb3]; // } -// bb7: { +// bb6: { // return; // } -// bb8: { +// bb7: { // StorageDead(_9); -// _0 = const > as std::ops::Try>::from_error(move _8) -> [return: bb9, unwind: bb4]; +// _0 = const > as std::ops::Try>::from_error(move _8) -> [return: bb8, unwind: bb3]; // } -// bb9: { +// bb8: { // StorageDead(_8); // StorageDead(_6); -// drop(_2) -> [return: bb10, unwind: bb3]; +// drop(_2) -> bb9; // } -// bb10: { +// bb9: { // StorageDead(_2); // StorageDead(_1); // StorageDead(_3); -// goto -> bb7; +// goto -> bb6; // } -// bb11: { +// bb10: { // StorageLive(_10); // _10 = ((_3 as Ok).0: u32); // (*_2) = _10; // StorageDead(_10); // _1 = move _2; -// drop(_2) -> [return: bb13, unwind: bb12]; +// drop(_2) -> [return: bb12, unwind: bb11]; // } -// bb12 (cleanup): { -// drop(_1) -> bb3; +// bb11 (cleanup): { +// drop(_1) -> bb1; // } -// bb13: { +// bb12: { // StorageDead(_2); // _0 = std::option::Option::>::Some(move _1,); -// drop(_1) -> [return: bb14, unwind: bb3]; +// drop(_1) -> bb13; // } -// bb14: { +// bb13: { // StorageDead(_1); // StorageDead(_3); -// goto -> bb7; +// goto -> bb6; // } // } // END rustc.test.ElaborateDrops.before.mir diff --git a/src/test/ui/async-await/async-fn-size-uninit-locals.rs b/src/test/ui/async-await/async-fn-size-uninit-locals.rs index a489fb11630c..ad20237981c3 100644 --- a/src/test/ui/async-await/async-fn-size-uninit-locals.rs +++ b/src/test/ui/async-await/async-fn-size-uninit-locals.rs @@ -99,5 +99,5 @@ fn main() { assert_eq!(12, std::mem::size_of_val(&single_with_noop())); assert_eq!(3084, std::mem::size_of_val(&joined())); assert_eq!(3084, std::mem::size_of_val(&joined_with_noop())); - assert_eq!(3084, std::mem::size_of_val(&join_retval())); + assert_eq!(3080, std::mem::size_of_val(&join_retval())); } diff --git a/src/test/ui/drop/dynamic-drop-async.rs b/src/test/ui/drop/dynamic-drop-async.rs index 398bcb7ec0e8..91063edf0f6c 100644 --- a/src/test/ui/drop/dynamic-drop-async.rs +++ b/src/test/ui/drop/dynamic-drop-async.rs @@ -7,7 +7,7 @@ // edition:2018 // ignore-wasm32-bare compiled with panic=abort by default -#![feature(slice_patterns, arbitrary_self_types)] +#![feature(slice_patterns)] #![allow(unused)] use std::{ @@ -45,7 +45,6 @@ impl Future for Defer { /// The `failing_op`-th operation will panic. struct Allocator { data: RefCell>, - name: &'static str, failing_op: usize, cur_ops: Cell, } @@ -57,28 +56,23 @@ impl Drop for Allocator { fn drop(&mut self) { let data = self.data.borrow(); if data.iter().any(|d| *d) { - panic!("missing free in {:?}: {:?}", self.name, data); + panic!("missing free: {:?}", data); } } } impl Allocator { - fn new(failing_op: usize, name: &'static str) -> Self { - Allocator { - failing_op, - name, - cur_ops: Cell::new(0), - data: RefCell::new(vec![]), - } + fn new(failing_op: usize) -> Self { + Allocator { failing_op, cur_ops: Cell::new(0), data: RefCell::new(vec![]) } } - fn alloc(self: &Rc) -> impl Future + 'static { + fn alloc(&self) -> impl Future> + '_ { self.fallible_operation(); let mut data = self.data.borrow_mut(); let addr = data.len(); data.push(true); - Defer { ready: false, value: Some(Ptr(addr, self.clone())) } + Defer { ready: false, value: Some(Ptr(addr, self)) } } fn fallible_operation(&self) { self.cur_ops.set(self.cur_ops.get() + 1); @@ -91,11 +85,11 @@ impl Allocator { // Type that tracks whether it was dropped and can panic when it's created or // destroyed. -struct Ptr(usize, Rc); -impl Drop for Ptr { +struct Ptr<'a>(usize, &'a Allocator); +impl<'a> Drop for Ptr<'a> { fn drop(&mut self) { match self.1.data.borrow_mut()[self.0] { - false => panic!("double free in {:?} at index {:?}", self.1.name, self.0), + false => panic!("double free at index {:?}", self.0), ref mut d => *d = false, } @@ -119,7 +113,7 @@ async fn dynamic_drop(a: Rc, c: bool) { }; } -struct TwoPtrs(Ptr, Ptr); +struct TwoPtrs<'a>(Ptr<'a>, Ptr<'a>); async fn struct_dynamic_drop(a: Rc, c0: bool, c1: bool, c: bool) { for i in 0..2 { let x; @@ -234,62 +228,21 @@ async fn subslice_pattern_reassign(a: Rc) { a.alloc().await; } -async fn panic_after_return(a: Rc, c: bool) -> (Ptr,) { - a.alloc().await; - let p = a.alloc().await; - if c { - a.alloc().await; - let q = a.alloc().await; - // We use a return type that isn't used anywhere else to make sure that - // the return place doesn't incorrectly end up in the generator state. - return (a.alloc().await,); - } - (a.alloc().await,) -} - - -async fn panic_after_init_by_loop(a: Rc) { - a.alloc().await; - let p = a.alloc().await; - let q = loop { - a.alloc().await; - let r = a.alloc().await; - break a.alloc().await; - }; -} - -async fn panic_after_init_by_match_with_bindings_and_guard(a: Rc, b: bool) { - a.alloc().await; - let p = a.alloc().await; - let q = match a.alloc().await { - ref _x if b => { - a.alloc().await; - let r = a.alloc().await; - a.alloc().await - } - _x => { - a.alloc().await; - let r = a.alloc().await; - a.alloc().await - }, - }; -} - -fn run_test(cx: &mut Context<'_>, ref f: F, name: &'static str) +fn run_test(cx: &mut Context<'_>, ref f: F) where F: Fn(Rc) -> G, - G: Future, + G: Future, { for polls in 0.. { // Run without any panics to find which operations happen after the // penultimate `poll`. - let first_alloc = Rc::new(Allocator::new(usize::MAX, name)); + let first_alloc = Rc::new(Allocator::new(usize::MAX)); let mut fut = Box::pin(f(first_alloc.clone())); let mut ops_before_last_poll = 0; let mut completed = false; for _ in 0..polls { ops_before_last_poll = first_alloc.cur_ops.get(); - if let Poll::Ready(_) = fut.as_mut().poll(cx) { + if let Poll::Ready(()) = fut.as_mut().poll(cx) { completed = true; } } @@ -298,7 +251,7 @@ where // Start at `ops_before_last_poll` so that we will always be able to // `poll` the expected number of times. for failing_op in ops_before_last_poll..first_alloc.cur_ops.get() { - let alloc = Rc::new(Allocator::new(failing_op + 1, name)); + let alloc = Rc::new(Allocator::new(failing_op + 1)); let f = &f; let cx = &mut *cx; let result = panic::catch_unwind(panic::AssertUnwindSafe(move || { @@ -328,56 +281,46 @@ fn clone_waker(data: *const ()) -> RawWaker { RawWaker::new(data, &RawWakerVTable::new(clone_waker, drop, drop, drop)) } -macro_rules! run_test { - ($ctxt:expr, $e:expr) => { run_test($ctxt, $e, stringify!($e)); }; -} - fn main() { let waker = unsafe { Waker::from_raw(clone_waker(ptr::null())) }; let context = &mut Context::from_waker(&waker); - run_test!(context, |a| dynamic_init(a, false)); - run_test!(context, |a| dynamic_init(a, true)); - run_test!(context, |a| dynamic_drop(a, false)); - run_test!(context, |a| dynamic_drop(a, true)); + run_test(context, |a| dynamic_init(a, false)); + run_test(context, |a| dynamic_init(a, true)); + run_test(context, |a| dynamic_drop(a, false)); + run_test(context, |a| dynamic_drop(a, true)); - run_test!(context, |a| assignment(a, false, false)); - run_test!(context, |a| assignment(a, false, true)); - run_test!(context, |a| assignment(a, true, false)); - run_test!(context, |a| assignment(a, true, true)); + run_test(context, |a| assignment(a, false, false)); + run_test(context, |a| assignment(a, false, true)); + run_test(context, |a| assignment(a, true, false)); + run_test(context, |a| assignment(a, true, true)); - run_test!(context, |a| array_simple(a)); - run_test!(context, |a| vec_simple(a)); - run_test!(context, |a| vec_unreachable(a)); + run_test(context, |a| array_simple(a)); + run_test(context, |a| vec_simple(a)); + run_test(context, |a| vec_unreachable(a)); - run_test!(context, |a| struct_dynamic_drop(a, false, false, false)); - run_test!(context, |a| struct_dynamic_drop(a, false, false, true)); - run_test!(context, |a| struct_dynamic_drop(a, false, true, false)); - run_test!(context, |a| struct_dynamic_drop(a, false, true, true)); - run_test!(context, |a| struct_dynamic_drop(a, true, false, false)); - run_test!(context, |a| struct_dynamic_drop(a, true, false, true)); - run_test!(context, |a| struct_dynamic_drop(a, true, true, false)); - run_test!(context, |a| struct_dynamic_drop(a, true, true, true)); + run_test(context, |a| struct_dynamic_drop(a, false, false, false)); + run_test(context, |a| struct_dynamic_drop(a, false, false, true)); + run_test(context, |a| struct_dynamic_drop(a, false, true, false)); + run_test(context, |a| struct_dynamic_drop(a, false, true, true)); + run_test(context, |a| struct_dynamic_drop(a, true, false, false)); + run_test(context, |a| struct_dynamic_drop(a, true, false, true)); + run_test(context, |a| struct_dynamic_drop(a, true, true, false)); + run_test(context, |a| struct_dynamic_drop(a, true, true, true)); - run_test!(context, |a| field_assignment(a, false)); - run_test!(context, |a| field_assignment(a, true)); + run_test(context, |a| field_assignment(a, false)); + run_test(context, |a| field_assignment(a, true)); - run_test!(context, |a| mixed_drop_and_nondrop(a)); + run_test(context, |a| mixed_drop_and_nondrop(a)); - run_test!(context, |a| slice_pattern_one_of(a, 0)); - run_test!(context, |a| slice_pattern_one_of(a, 1)); - run_test!(context, |a| slice_pattern_one_of(a, 2)); - run_test!(context, |a| slice_pattern_one_of(a, 3)); + run_test(context, |a| slice_pattern_one_of(a, 0)); + run_test(context, |a| slice_pattern_one_of(a, 1)); + run_test(context, |a| slice_pattern_one_of(a, 2)); + run_test(context, |a| slice_pattern_one_of(a, 3)); - run_test!(context, |a| subslice_pattern_from_end_with_drop(a, true, true)); - run_test!(context, |a| subslice_pattern_from_end_with_drop(a, true, false)); - run_test!(context, |a| subslice_pattern_from_end_with_drop(a, false, true)); - run_test!(context, |a| subslice_pattern_from_end_with_drop(a, false, false)); - run_test!(context, |a| subslice_pattern_reassign(a)); - - run_test!(context, |a| panic_after_return(a, false)); - run_test!(context, |a| panic_after_return(a, true)); - run_test!(context, |a| panic_after_init_by_loop(a)); - run_test!(context, |a| panic_after_init_by_match_with_bindings_and_guard(a, false)); - run_test!(context, |a| panic_after_init_by_match_with_bindings_and_guard(a, true)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, true)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, true, false)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, true)); + run_test(context, |a| subslice_pattern_from_end_with_drop(a, false, false)); + run_test(context, |a| subslice_pattern_reassign(a)); } diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 6f9112ae0060..8516bc3d9642 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -17,7 +17,6 @@ struct InjectedFailure; struct Allocator { data: RefCell>, - name: &'static str, failing_op: usize, cur_ops: Cell, } @@ -29,18 +28,17 @@ impl Drop for Allocator { fn drop(&mut self) { let data = self.data.borrow(); if data.iter().any(|d| *d) { - panic!("missing free in {:?}: {:?}", self.name, data); + panic!("missing free: {:?}", data); } } } impl Allocator { - fn new(failing_op: usize, name: &'static str) -> Self { + fn new(failing_op: usize) -> Self { Allocator { failing_op: failing_op, cur_ops: Cell::new(0), - data: RefCell::new(vec![]), - name, + data: RefCell::new(vec![]) } } fn alloc(&self) -> Ptr<'_> { @@ -55,6 +53,20 @@ impl Allocator { data.push(true); Ptr(addr, self) } + // FIXME(#47949) Any use of this indicates a bug in rustc: we should never + // be leaking values in the cases here. + // + // Creates a `Ptr<'_>` and checks that the allocated value is leaked if the + // `failing_op` is in the list of exception. + fn alloc_leaked(&self, exceptions: Vec) -> Ptr<'_> { + let ptr = self.alloc(); + + if exceptions.iter().any(|operation| *operation == self.failing_op) { + let mut data = self.data.borrow_mut(); + data[ptr.0] = false; + } + ptr + } } struct Ptr<'a>(usize, &'a Allocator); @@ -62,7 +74,7 @@ impl<'a> Drop for Ptr<'a> { fn drop(&mut self) { match self.1.data.borrow_mut()[self.0] { false => { - panic!("double free in {:?} at index {:?}", self.1.name, self.0) + panic!("double free at index {:?}", self.0) } ref mut d => *d = false } @@ -258,148 +270,79 @@ fn subslice_pattern_reassign(a: &Allocator) { } fn panic_after_return(a: &Allocator) -> Ptr<'_> { + // Panic in the drop of `p` or `q` can leak + let exceptions = vec![8, 9]; a.alloc(); let p = a.alloc(); { a.alloc(); let p = a.alloc(); - a.alloc() + // FIXME (#47949) We leak values when we panic in a destructor after + // evaluating an expression with `rustc_mir::build::Builder::into`. + a.alloc_leaked(exceptions) } } fn panic_after_return_expr(a: &Allocator) -> Ptr<'_> { + // Panic in the drop of `p` or `q` can leak + let exceptions = vec![8, 9]; a.alloc(); let p = a.alloc(); { a.alloc(); let q = a.alloc(); - return a.alloc(); + // FIXME (#47949) + return a.alloc_leaked(exceptions); } } fn panic_after_init(a: &Allocator) { + // Panic in the drop of `r` can leak + let exceptions = vec![8]; a.alloc(); let p = a.alloc(); let q = { a.alloc(); let r = a.alloc(); - a.alloc() + // FIXME (#47949) + a.alloc_leaked(exceptions) }; } fn panic_after_init_temp(a: &Allocator) { + // Panic in the drop of `r` can leak + let exceptions = vec![8]; a.alloc(); let p = a.alloc(); { a.alloc(); let r = a.alloc(); - a.alloc() + // FIXME (#47949) + a.alloc_leaked(exceptions) }; } fn panic_after_init_by_loop(a: &Allocator) { + // Panic in the drop of `r` can leak + let exceptions = vec![8]; a.alloc(); let p = a.alloc(); let q = loop { a.alloc(); let r = a.alloc(); - break a.alloc(); + // FIXME (#47949) + break a.alloc_leaked(exceptions); }; } -fn panic_after_init_by_match(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - loop { - let q = match b { - true => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - false => { - a.alloc(); - let r = a.alloc(); - break a.alloc(); - } - }; - return; - }; -} - -fn panic_after_init_by_match_with_guard(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = match a.alloc() { - _ if b => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - _ => { - a.alloc(); - let r = a.alloc(); - a.alloc() - }, - }; -} - -fn panic_after_init_by_match_with_bindings_and_guard(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = match a.alloc() { - _x if b => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - _x => { - a.alloc(); - let r = a.alloc(); - a.alloc() - }, - }; -} - -fn panic_after_init_by_match_with_ref_bindings_and_guard(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = match a.alloc() { - ref _x if b => { - a.alloc(); - let r = a.alloc(); - a.alloc() - } - ref _x => { - a.alloc(); - let r = a.alloc(); - a.alloc() - }, - }; -} - -fn panic_after_init_by_break_if(a: &Allocator, b: bool) { - a.alloc(); - let p = a.alloc(); - let q = loop { - let r = a.alloc(); - break if b { - let s = a.alloc(); - a.alloc() - } else { - a.alloc() - }; - }; -} - -fn run_test(mut f: F, name: &'static str) +fn run_test(mut f: F) where F: FnMut(&Allocator) { - let first_alloc = Allocator::new(usize::MAX, name); + let first_alloc = Allocator::new(usize::MAX); f(&first_alloc); for failing_op in 1..first_alloc.cur_ops.get()+1 { - let alloc = Allocator::new(failing_op, name); + let alloc = Allocator::new(failing_op); let alloc = &alloc; let f = panic::AssertUnwindSafe(&mut f); let result = panic::catch_unwind(move || { @@ -417,91 +360,77 @@ fn run_test(mut f: F, name: &'static str) } } -fn run_test_nopanic(mut f: F, name: &'static str) +fn run_test_nopanic(mut f: F) where F: FnMut(&Allocator) { - let first_alloc = Allocator::new(usize::MAX, name); + let first_alloc = Allocator::new(usize::MAX); f(&first_alloc); } -macro_rules! run_test { - ($e:expr) => { run_test($e, stringify!($e)); } -} - fn main() { - run_test!(|a| dynamic_init(a, false)); - run_test!(|a| dynamic_init(a, true)); - run_test!(|a| dynamic_drop(a, false)); - run_test!(|a| dynamic_drop(a, true)); + run_test(|a| dynamic_init(a, false)); + run_test(|a| dynamic_init(a, true)); + run_test(|a| dynamic_drop(a, false)); + run_test(|a| dynamic_drop(a, true)); - run_test!(|a| assignment2(a, false, false)); - run_test!(|a| assignment2(a, false, true)); - run_test!(|a| assignment2(a, true, false)); - run_test!(|a| assignment2(a, true, true)); + run_test(|a| assignment2(a, false, false)); + run_test(|a| assignment2(a, false, true)); + run_test(|a| assignment2(a, true, false)); + run_test(|a| assignment2(a, true, true)); - run_test!(|a| assignment1(a, false)); - run_test!(|a| assignment1(a, true)); + run_test(|a| assignment1(a, false)); + run_test(|a| assignment1(a, true)); - run_test!(|a| array_simple(a)); - run_test!(|a| vec_simple(a)); - run_test!(|a| vec_unreachable(a)); + run_test(|a| array_simple(a)); + run_test(|a| vec_simple(a)); + run_test(|a| vec_unreachable(a)); - run_test!(|a| struct_dynamic_drop(a, false, false, false)); - run_test!(|a| struct_dynamic_drop(a, false, false, true)); - run_test!(|a| struct_dynamic_drop(a, false, true, false)); - run_test!(|a| struct_dynamic_drop(a, false, true, true)); - run_test!(|a| struct_dynamic_drop(a, true, false, false)); - run_test!(|a| struct_dynamic_drop(a, true, false, true)); - run_test!(|a| struct_dynamic_drop(a, true, true, false)); - run_test!(|a| struct_dynamic_drop(a, true, true, true)); + run_test(|a| struct_dynamic_drop(a, false, false, false)); + run_test(|a| struct_dynamic_drop(a, false, false, true)); + run_test(|a| struct_dynamic_drop(a, false, true, false)); + run_test(|a| struct_dynamic_drop(a, false, true, true)); + run_test(|a| struct_dynamic_drop(a, true, false, false)); + run_test(|a| struct_dynamic_drop(a, true, false, true)); + run_test(|a| struct_dynamic_drop(a, true, true, false)); + run_test(|a| struct_dynamic_drop(a, true, true, true)); - run_test!(|a| field_assignment(a, false)); - run_test!(|a| field_assignment(a, true)); + run_test(|a| field_assignment(a, false)); + run_test(|a| field_assignment(a, true)); - run_test!(|a| generator(a, 0)); - run_test!(|a| generator(a, 1)); - run_test!(|a| generator(a, 2)); - run_test!(|a| generator(a, 3)); + run_test(|a| generator(a, 0)); + run_test(|a| generator(a, 1)); + run_test(|a| generator(a, 2)); + run_test(|a| generator(a, 3)); - run_test!(|a| mixed_drop_and_nondrop(a)); + run_test(|a| mixed_drop_and_nondrop(a)); - run_test!(|a| slice_pattern_first(a)); - run_test!(|a| slice_pattern_middle(a)); - run_test!(|a| slice_pattern_two(a)); - run_test!(|a| slice_pattern_last(a)); - run_test!(|a| slice_pattern_one_of(a, 0)); - run_test!(|a| slice_pattern_one_of(a, 1)); - run_test!(|a| slice_pattern_one_of(a, 2)); - run_test!(|a| slice_pattern_one_of(a, 3)); + run_test(|a| slice_pattern_first(a)); + run_test(|a| slice_pattern_middle(a)); + run_test(|a| slice_pattern_two(a)); + run_test(|a| slice_pattern_last(a)); + run_test(|a| slice_pattern_one_of(a, 0)); + run_test(|a| slice_pattern_one_of(a, 1)); + run_test(|a| slice_pattern_one_of(a, 2)); + run_test(|a| slice_pattern_one_of(a, 3)); - run_test!(|a| subslice_pattern_from_end(a, true)); - run_test!(|a| subslice_pattern_from_end(a, false)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, true, true)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, true, false)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, false, true)); - run_test!(|a| subslice_pattern_from_end_with_drop(a, false, false)); - run_test!(|a| slice_pattern_reassign(a)); - run_test!(|a| subslice_pattern_reassign(a)); + run_test(|a| subslice_pattern_from_end(a, true)); + run_test(|a| subslice_pattern_from_end(a, false)); + run_test(|a| subslice_pattern_from_end_with_drop(a, true, true)); + run_test(|a| subslice_pattern_from_end_with_drop(a, true, false)); + run_test(|a| subslice_pattern_from_end_with_drop(a, false, true)); + run_test(|a| subslice_pattern_from_end_with_drop(a, false, false)); + run_test(|a| slice_pattern_reassign(a)); + run_test(|a| subslice_pattern_reassign(a)); - run_test!(|a| { + run_test(|a| { panic_after_return(a); }); - run_test!(|a| { + run_test(|a| { panic_after_return_expr(a); }); - run_test!(|a| panic_after_init(a)); - run_test!(|a| panic_after_init_temp(a)); - run_test!(|a| panic_after_init_by_loop(a)); - run_test!(|a| panic_after_init_by_match(a, false)); - run_test!(|a| panic_after_init_by_match(a, true)); - run_test!(|a| panic_after_init_by_match_with_guard(a, false)); - run_test!(|a| panic_after_init_by_match_with_guard(a, true)); - run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, false)); - run_test!(|a| panic_after_init_by_match_with_bindings_and_guard(a, true)); - run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, false)); - run_test!(|a| panic_after_init_by_match_with_ref_bindings_and_guard(a, true)); - run_test!(|a| panic_after_init_by_break_if(a, false)); - run_test!(|a| panic_after_init_by_break_if(a, true)); + run_test(|a| panic_after_init(a)); + run_test(|a| panic_after_init_temp(a)); + run_test(|a| panic_after_init_by_loop(a)); - run_test_nopanic(|a| union1(a), "|a| union1(a)"); + run_test_nopanic(|a| union1(a)); } From 959a6c1ca8dad937fe9653e4a7acd3108199b92e Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Thu, 10 Oct 2019 00:24:45 +1000 Subject: [PATCH 230/545] move debug_map assertions after check for err --- src/libcore/fmt/builders.rs | 16 +++++++------ src/libcore/tests/fmt/builders.rs | 40 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/libcore/fmt/builders.rs b/src/libcore/fmt/builders.rs index 15ce2277fa00..e6e3454b36f8 100644 --- a/src/libcore/fmt/builders.rs +++ b/src/libcore/fmt/builders.rs @@ -775,10 +775,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { reason = "recently added", issue = "62482")] pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> { - assert!(!self.has_key, "attempted to begin a new map entry \ - without completing the previous one"); - self.result = self.result.and_then(|_| { + assert!(!self.has_key, "attempted to begin a new map entry \ + without completing the previous one"); + if self.is_pretty() { if !self.has_fields { self.fmt.write_str("\n")?; @@ -839,9 +839,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { reason = "recently added", issue = "62482")] pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut DebugMap<'a, 'b> { - assert!(self.has_key, "attempted to format a map value before its key"); - self.result = self.result.and_then(|_| { + assert!(self.has_key, "attempted to format a map value before its key"); + if self.is_pretty() { let mut slot = None; let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut self.state); @@ -924,9 +924,11 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ``` #[stable(feature = "debug_builders", since = "1.2.0")] pub fn finish(&mut self) -> fmt::Result { - assert!(!self.has_key, "attempted to finish a map with a partial entry"); + self.result.and_then(|_| { + assert!(!self.has_key, "attempted to finish a map with a partial entry"); - self.result.and_then(|_| self.fmt.write_str("}")) + self.fmt.write_str("}") + }) } fn is_pretty(&self) -> bool { diff --git a/src/libcore/tests/fmt/builders.rs b/src/libcore/tests/fmt/builders.rs index 200659b91bb4..255724432816 100644 --- a/src/libcore/tests/fmt/builders.rs +++ b/src/libcore/tests/fmt/builders.rs @@ -319,6 +319,46 @@ mod debug_map { format!("{:#?}", Bar)); } + #[test] + fn test_entry_err() { + // Ensure errors in a map entry don't trigger panics (#65231) + use std::fmt::Write; + + struct ErrorFmt; + + impl fmt::Debug for ErrorFmt { + fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { + Err(fmt::Error) + } + } + + struct KeyValue(usize, K, V); + + impl fmt::Debug for KeyValue + where + K: fmt::Debug, + V: fmt::Debug, + { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut map = fmt.debug_map(); + + for _ in 0..self.0 { + map.entry(&self.1, &self.2); + } + + map.finish() + } + } + + let mut buf = String::new(); + + assert!(write!(&mut buf, "{:?}", KeyValue(1, ErrorFmt, "bar")).is_err()); + assert!(write!(&mut buf, "{:?}", KeyValue(1, "foo", ErrorFmt)).is_err()); + + assert!(write!(&mut buf, "{:?}", KeyValue(2, ErrorFmt, "bar")).is_err()); + assert!(write!(&mut buf, "{:?}", KeyValue(2, "foo", ErrorFmt)).is_err()); + } + #[test] #[should_panic] fn test_invalid_key_when_entry_is_incomplete() { From 012116f860eb5b859218640e963ba32545311a24 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 3 Oct 2019 19:10:34 -0700 Subject: [PATCH 231/545] Add InstanceDef::ReifyShim for track_caller functions. --- src/librustc/mir/mono.rs | 1 + src/librustc/ty/instance.rs | 7 +++++++ src/librustc/ty/mod.rs | 1 + src/librustc/ty/structural_impls.rs | 5 ++++- src/librustc_mir/interpret/terminator.rs | 1 + src/librustc_mir/monomorphize/collector.rs | 2 ++ src/librustc_mir/monomorphize/partitioning.rs | 2 ++ src/librustc_mir/shim.rs | 9 +++++++++ 8 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 313b2a5d50a3..265ac975ed7a 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -386,6 +386,7 @@ impl<'tcx> CodegenUnit<'tcx> { tcx.hir().as_local_hir_id(def_id) } InstanceDef::VtableShim(..) | + InstanceDef::ReifyShim(..) | InstanceDef::Intrinsic(..) | InstanceDef::FnPtrShim(..) | InstanceDef::Virtual(..) | diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 93a8341e7462..e13e097b482f 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -25,6 +25,9 @@ pub enum InstanceDef<'tcx> { /// `::method` where `method` receives unsizeable `self: Self`. VtableShim(DefId), + /// `fn()` where the function is annotated with `#[track_caller]`. + ReifyShim(DefId), + /// `::call_*` /// `DefId` is `FnTrait::call_*` FnPtrShim(DefId, Ty<'tcx>), @@ -123,6 +126,7 @@ impl<'tcx> InstanceDef<'tcx> { match *self { InstanceDef::Item(def_id) | InstanceDef::VtableShim(def_id) | + InstanceDef::ReifyShim(def_id) | InstanceDef::FnPtrShim(def_id, _) | InstanceDef::Virtual(def_id, _) | InstanceDef::Intrinsic(def_id, ) | @@ -178,6 +182,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> { InstanceDef::VtableShim(_) => { write!(f, " - shim(vtable)") } + InstanceDef::ReifyShim(_) => { + write!(f, " - shim(reify)") + } InstanceDef::Intrinsic(_) => { write!(f, " - intrinsic") } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index cfd859c33c2e..3692caada577 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3026,6 +3026,7 @@ impl<'tcx> TyCtxt<'tcx> { self.optimized_mir(did) } ty::InstanceDef::VtableShim(..) | + ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::Intrinsic(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::Virtual(..) | diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 5aa59cc309fc..8945e1a1debd 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -761,6 +761,8 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { Some(ty::InstanceDef::Item(def_id)), ty::InstanceDef::VtableShim(def_id) => Some(ty::InstanceDef::VtableShim(def_id)), + ty::InstanceDef::ReifyShim(def_id) => + Some(ty::InstanceDef::ReifyShim(def_id)), ty::InstanceDef::Intrinsic(def_id) => Some(ty::InstanceDef::Intrinsic(def_id)), ty::InstanceDef::FnPtrShim(def_id, ref ty) => @@ -966,6 +968,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { def: match self.def { Item(did) => Item(did.fold_with(folder)), VtableShim(did) => VtableShim(did.fold_with(folder)), + ReifyShim(did) => ReifyShim(did.fold_with(folder)), Intrinsic(did) => Intrinsic(did.fold_with(folder)), FnPtrShim(did, ty) => FnPtrShim( did.fold_with(folder), @@ -994,7 +997,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::instance::Instance<'tcx> { use crate::ty::InstanceDef::*; self.substs.visit_with(visitor) || match self.def { - Item(did) | VtableShim(did) | Intrinsic(did) | Virtual(did, _) => { + Item(did) | VtableShim(did) | ReifyShim(did) | Intrinsic(did) | Virtual(did, _) => { did.visit_with(visitor) }, FnPtrShim(did, ty) | CloneShim(did, ty) => { diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index ef6b7d626e7a..11c7cd0d901d 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -263,6 +263,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(()) } ty::InstanceDef::VtableShim(..) | + ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::DropGlue(..) | diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 3f0a2674305d..07ae4837d1cb 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -747,6 +747,7 @@ fn visit_instance_use<'tcx>( } } ty::InstanceDef::VtableShim(..) | + ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::Virtual(..) | ty::InstanceDef::DropGlue(_, None) => { // don't need to emit shim if we are calling directly. @@ -773,6 +774,7 @@ fn should_monomorphize_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx let def_id = match instance.def { ty::InstanceDef::Item(def_id) => def_id, ty::InstanceDef::VtableShim(..) | + ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::Virtual(..) | ty::InstanceDef::FnPtrShim(..) | diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 6d9dae7214cc..b9d38028b72a 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -339,6 +339,7 @@ fn mono_item_visibility( // These are all compiler glue and such, never exported, always hidden. InstanceDef::VtableShim(..) | + InstanceDef::ReifyShim(..) | InstanceDef::FnPtrShim(..) | InstanceDef::Virtual(..) | InstanceDef::Intrinsic(..) | @@ -677,6 +678,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( let def_id = match instance.def { ty::InstanceDef::Item(def_id) => def_id, ty::InstanceDef::VtableShim(..) | + ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::Intrinsic(..) | diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 78008e2fcd36..10240271eb8e 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -41,6 +41,15 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx None, ) } + ty::InstanceDef::ReifyShim(def_id) => { + build_call_shim( + tcx, + def_id, + Adjustment::DerefMove, + CallKind::Direct(def_id), + None, + ) + } ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); let adjustment = match tcx.lang_items().fn_trait_kind(trait_) { From f5f67e78bb3bfbc391699021c89b07f1aff3aa26 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 5 Oct 2019 14:24:07 -0700 Subject: [PATCH 232/545] Add Instance::resolve_for_fn_ptr --- src/librustc/ty/instance.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index e13e097b482f..f547da00b1ad 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -25,7 +25,7 @@ pub enum InstanceDef<'tcx> { /// `::method` where `method` receives unsizeable `self: Self`. VtableShim(DefId), - /// `fn()` where the function is annotated with `#[track_caller]`. + /// `fn()` pointer where the function is annotated with `#[track_caller]`. ReifyShim(DefId), /// `::call_*` @@ -297,6 +297,28 @@ impl<'tcx> Instance<'tcx> { result } + pub fn resolve_for_fn_ptr( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + ) -> Option> { + debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); + let fn_sig = tcx.fn_sig(def_id); + // let is_reify_shim = fn_sig.inputs().skip_binder().len() > 0 + // && fn_sig.input(0).skip_binder().is_param(0) + // && tcx.generics_of(def_id).has_self; + if is_reify_shim { + debug!(" => fn ptr with implicit caller location"); + Some(Instance { + def: InstanceDef::ReifyShim(def_id), + substs, + }) + } else { + Instance::resolve(tcx, param_env, def_id, substs) + } + } + pub fn resolve_for_vtable( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, From 01327384370b81e3a155dc70a2533935c4495db8 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 9 Oct 2019 06:05:49 -0700 Subject: [PATCH 233/545] Reifying callers of Instance::resolve use resolve_for_fn_ptr. --- src/librustc/ty/instance.rs | 9 +++------ src/librustc_codegen_ssa/callee.rs | 17 +++++++++++++++++ src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 10 ++++++---- src/librustc_mir/shim.rs | 2 +- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index f547da00b1ad..471bd1637546 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,3 +1,4 @@ +// use crate::hir::CodegenFnAttrFlags; use crate::hir::Unsafety; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; @@ -304,12 +305,8 @@ impl<'tcx> Instance<'tcx> { substs: SubstsRef<'tcx>, ) -> Option> { debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); - let fn_sig = tcx.fn_sig(def_id); - // let is_reify_shim = fn_sig.inputs().skip_binder().len() > 0 - // && fn_sig.input(0).skip_binder().is_param(0) - // && tcx.generics_of(def_id).has_self; - if is_reify_shim { - debug!(" => fn ptr with implicit caller location"); + if false { + debug!(" => fn pointer created for function with #[track_caller]"); Some(Instance { def: InstanceDef::ReifyShim(def_id), substs, diff --git a/src/librustc_codegen_ssa/callee.rs b/src/librustc_codegen_ssa/callee.rs index 4744dd6302fb..6ba6774cbf88 100644 --- a/src/librustc_codegen_ssa/callee.rs +++ b/src/librustc_codegen_ssa/callee.rs @@ -18,6 +18,23 @@ pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>( ) } +pub fn resolve_and_get_fn_for_ptr<'tcx, + Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx> +>( + cx: &Cx, + def_id: DefId, + substs: SubstsRef<'tcx>, +) -> Cx::Value { + cx.get_fn( + ty::Instance::resolve_for_fn_ptr( + cx.tcx(), + ty::ParamEnv::reveal_all(), + def_id, + substs + ).unwrap() + ) +} + pub fn resolve_and_get_fn_for_vtable<'tcx, Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx> >( diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 6ffa561f3fec..978e7218aa74 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -190,7 +190,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("reifying a fn ptr that requires const arguments"); } OperandValue::Immediate( - callee::resolve_and_get_fn(bx.cx(), def_id, substs)) + callee::resolve_and_get_fn_for_ptr(bx.cx(), def_id, substs)) } _ => { bug!("{} cannot be reified to a fn ptr", operand.layout.ty) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 07ae4837d1cb..a1f5562035c6 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -721,10 +721,12 @@ fn visit_fn_use<'tcx>( output: &mut Vec>, ) { if let ty::FnDef(def_id, substs) = ty.kind { - let instance = ty::Instance::resolve(tcx, - ty::ParamEnv::reveal_all(), - def_id, - substs).unwrap(); + let resolver = if is_direct_call { + ty::Instance::resolve + } else { + ty::Instance::resolve_for_fn_ptr + }; + let instance = resolver(tcx, ty::ParamEnv::reveal_all(), def_id, substs).unwrap(); visit_instance_use(tcx, instance, is_direct_call, output); } } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 10240271eb8e..eced7eb09ae8 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -45,7 +45,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx build_call_shim( tcx, def_id, - Adjustment::DerefMove, + Adjustment::Identity, // TODO(anp) is this the right kind of adjustment? CallKind::Direct(def_id), None, ) From b8414c13abf9dc994f9c0dccee848a8b0fb1b061 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 9 Oct 2019 06:20:23 -0700 Subject: [PATCH 234/545] Return ReifyShim from Instance::resolve_for_fn_ptr when track_caller present. This ICEs in MIR currently, which I think is to be expected since none of the MIR plumbing is set up. I added a test which confirms that the shim is being used for reifying a track_caller function. --- src/librustc/ty/instance.rs | 4 ++-- .../taking-fn-pointer.rs | 16 ++++++++++++++ .../taking-fn-pointer.stderr | 21 +++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs create mode 100644 src/test/ui/rfc-2091-track-caller/taking-fn-pointer.stderr diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 471bd1637546..18b625984e1a 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,4 +1,4 @@ -// use crate::hir::CodegenFnAttrFlags; +use crate::hir::CodegenFnAttrFlags; use crate::hir::Unsafety; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; @@ -305,7 +305,7 @@ impl<'tcx> Instance<'tcx> { substs: SubstsRef<'tcx>, ) -> Option> { debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); - if false { + if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) { debug!(" => fn pointer created for function with #[track_caller]"); Some(Instance { def: InstanceDef::ReifyShim(def_id), diff --git a/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs b/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs new file mode 100644 index 000000000000..df3893f2a6a1 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs @@ -0,0 +1,16 @@ +// failure-status: 101 +// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" +// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" + +#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete + +#[track_caller] +fn f() {} + +fn call_it(x: fn()) { + x(); +} + +fn main() { + call_it(f); +} \ No newline at end of file diff --git a/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.stderr b/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.stderr new file mode 100644 index 000000000000..fb625ae116e7 --- /dev/null +++ b/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.stderr @@ -0,0 +1,21 @@ +warning: the feature `track_caller` is incomplete and may cause the compiler to crash + --> $DIR/taking-fn-pointer.rs:5:12 + | +LL | #![feature(track_caller)] + | ^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +thread 'rustc' panicked at 'index out of bounds: the len is 1 but the index is 1', $SRC_DIR/libcore/slice/mod.rs:LL:COL +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports + +note: rustc VERSION running on TARGET + +note: compiler flags: FLAGS + From 8a097f26198d9979d88e7c0cd0a3bce283ff038a Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 9 Oct 2019 21:02:54 -0700 Subject: [PATCH 235/545] Clarify comment, dedupe match arms in shim.rs. Also add a missing terminal newline to a test. --- src/librustc/ty/instance.rs | 4 +++- src/librustc_mir/shim.rs | 17 +++++------------ .../rfc-2091-track-caller/taking-fn-pointer.rs | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 18b625984e1a..2b9d09b20ccf 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -26,7 +26,9 @@ pub enum InstanceDef<'tcx> { /// `::method` where `method` receives unsizeable `self: Self`. VtableShim(DefId), - /// `fn()` pointer where the function is annotated with `#[track_caller]`. + /// `fn()` pointer where the function itself cannot be turned into a pointer. + /// + /// One example in the compiler today is functions annotated with `#[track_caller]`. ReifyShim(DefId), /// `::call_*` diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index eced7eb09ae8..0d13daa26430 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -41,15 +41,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx None, ) } - ty::InstanceDef::ReifyShim(def_id) => { - build_call_shim( - tcx, - def_id, - Adjustment::Identity, // TODO(anp) is this the right kind of adjustment? - CallKind::Direct(def_id), - None, - ) - } ty::InstanceDef::FnPtrShim(def_id, ty) => { let trait_ = tcx.trait_of_item(def_id).unwrap(); let adjustment = match tcx.lang_items().fn_trait_kind(trait_) { @@ -75,9 +66,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx Some(arg_tys) ) } - ty::InstanceDef::Virtual(def_id, _) => { - // We are generating a call back to our def-id, which the - // codegen backend knows to turn to an actual virtual call. + // We are generating a call back to our def-id, which the + // codegen backend knows to turn to an actual virtual call. + ty::InstanceDef::Virtual(def_id, _) | + // ...or we are generating a call to the inner closure defined by #[track_caller] + ty::InstanceDef::ReifyShim(def_id) => { build_call_shim( tcx, def_id, diff --git a/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs b/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs index df3893f2a6a1..2882d2d83ff8 100644 --- a/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs +++ b/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs @@ -13,4 +13,4 @@ fn call_it(x: fn()) { fn main() { call_it(f); -} \ No newline at end of file +} From ea3ecf22ae911b7e32b889b636bce86c165908c4 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Wed, 9 Oct 2019 21:13:08 -0700 Subject: [PATCH 236/545] miri calls resolve_for_fn_ptr when reifying. --- src/librustc_mir/interpret/cast.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index d120412c901a..9ab347957f97 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -44,7 +44,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if self.tcx.has_attr(def_id, sym::rustc_args_required_const) { bug!("reifying a fn ptr that requires const arguments"); } - let instance = self.resolve(def_id, substs)?; + + let instance = ty::Instance::resolve_for_fn_ptr( + *self.tcx, + self.param_env, + def_id, + substs, + ).ok_or_else(|| err_inval!(TooGeneric))?; + let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance)); self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?; } From 53e739305a34ed42198b5f595fa549223a29814d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2019 07:05:19 +1100 Subject: [PATCH 237/545] Tweak `tcx` usage in `lub_concrete_regions()`. Some places use the local `tcx` variable, some use `self.tcx()`. This commit removes the local variable so that all places use `self.tcx()`, for consistency. --- src/librustc/infer/lexical_region_resolve/mod.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index f11f94c428e8..84960d149d0f 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -407,8 +407,6 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { /// Returns the smallest region `c` such that `a <= c` and `b <= c`. fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'tcx> { - let tcx = self.tcx(); - match (a, b) { (&ty::ReClosureBound(..), _) | (_, &ty::ReClosureBound(..)) @@ -468,7 +466,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // otherwise, we don't know what the free region is, // so we must conservatively say the LUB is static: - tcx.lifetimes.re_static + self.tcx().lifetimes.re_static } (&ReScope(a_id), &ReScope(b_id)) => { @@ -476,7 +474,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { // subtype of the region corresponding to an inner // block. let lub = self.region_rels.region_scope_tree.nearest_common_ancestor(a_id, b_id); - tcx.mk_region(ReScope(lub)) + self.tcx().mk_region(ReScope(lub)) } (&ReEarlyBound(_), &ReEarlyBound(_)) @@ -490,7 +488,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { if a == b { a } else { - tcx.lifetimes.re_static + self.tcx().lifetimes.re_static } } } From 59e41edcc15ed07de604c61876ea091900f73649 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2019 13:06:12 +1100 Subject: [PATCH 238/545] Special-case `ReEmpty` in `expand_node()`. This wins 6% on `unicode_normalization`, by avoiding a call to `lub_concrete_regions()` and a `Region` equality test. --- src/librustc/infer/lexical_region_resolve/mod.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 84960d149d0f..94ec3b981a47 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -360,13 +360,21 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { match *b_data { VarValue::Value(cur_region) => { // Identical scopes can show up quite often, if the fixed point - // iteration converges slowly, skip them + // iteration converges slowly. Skip them. This is purely an + // optimization. if let (ReScope(a_scope), ReScope(cur_scope)) = (a_region, cur_region) { if a_scope == cur_scope { return false; } } + // This is a specialized version of the `lub_concrete_regions` + // check below for a common case, here purely as an + // optimization. + if let ReEmpty = a_region { + return false; + } + let mut lub = self.lub_concrete_regions(a_region, cur_region); if lub == cur_region { return false; From 8cd25e72459a6ab25407e1fa30c4d6d42422ff3e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2019 16:06:24 +1100 Subject: [PATCH 239/545] Remove `tag` from `iterate_until_fixed_point()`. The function only has one call site, so we don't need a tag argument. --- src/librustc/infer/lexical_region_resolve/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 94ec3b981a47..6f55ade1e861 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -304,7 +304,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) { - self.iterate_until_fixed_point("Expansion", |constraint| { + self.iterate_until_fixed_point(|constraint| { debug!("expansion: constraint={:?}", constraint); let (a_region, b_vid, b_data, retain) = match *constraint { Constraint::RegSubVar(a_region, b_vid) => { @@ -866,7 +866,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } - fn iterate_until_fixed_point(&self, tag: &str, mut body: F) + fn iterate_until_fixed_point(&self, mut body: F) where F: FnMut(&Constraint<'tcx>) -> (bool, bool), { @@ -876,7 +876,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { while changed { changed = false; iteration += 1; - debug!("---- {} Iteration {}{}", "#", tag, iteration); + debug!("---- Expansion iteration {}", iteration); constraints.retain(|constraint| { let (edge_changed, retain) = body(constraint); if edge_changed { @@ -886,7 +886,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { retain }); } - debug!("---- {} Complete after {} iteration(s)", tag, iteration); + debug!("---- Expansion complete after {} iteration(s)", iteration); } fn bound_is_met( From af3f8dec5988930645bc2fbb77605965028c8032 Mon Sep 17 00:00:00 2001 From: Matt Stavola Date: Wed, 9 Oct 2019 22:37:05 -0700 Subject: [PATCH 240/545] Delegate is_{freeze,copy,sized}_raw to is_item_raw --- src/librustc/ty/util.rs | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index d0e95a18c59f..e5885ce3fa3b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -1017,34 +1017,25 @@ impl<'tcx> ty::TyS<'tcx> { } fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::CopyTraitLangItem, None); - tcx.infer_ctxt() - .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( - &infcx, - param_env, - ty, - trait_def_id, - DUMMY_SP, - )) + is_item_raw(tcx, query, lang_items::CopyTraitLangItem) } fn is_sized_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::SizedTraitLangItem, None); - tcx.infer_ctxt() - .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( - &infcx, - param_env, - ty, - trait_def_id, - DUMMY_SP, - )) + is_item_raw(tcx, query, lang_items::SizedTraitLangItem) + } fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { + is_item_raw(tcx, query, lang_items::FreezeTraitLangItem) +} + +fn is_item_raw<'tcx>( + tcx: TyCtxt<'tcx>, + query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, + item: LangItem +) -> bool { let (param_env, ty) = query.into_parts(); - let trait_def_id = tcx.require_lang_item(lang_items::FreezeTraitLangItem, None); + let trait_def_id = tcx.require_lang_item(item, None); tcx.infer_ctxt() .enter(|infcx| traits::type_known_to_meet_bound_modulo_regions( &infcx, From ee081145ac417b244e513580e15195c864763a6e Mon Sep 17 00:00:00 2001 From: Matt Stavola Date: Wed, 9 Oct 2019 23:10:35 -0700 Subject: [PATCH 241/545] Qualify LangItem --- src/librustc/ty/util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index e5885ce3fa3b..5ddf15317a31 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -1032,7 +1032,7 @@ fn is_freeze_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>> fn is_item_raw<'tcx>( tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, - item: LangItem + item: lang_items::LangItem, ) -> bool { let (param_env, ty) = query.into_parts(); let trait_def_id = tcx.require_lang_item(item, None); From a9853fce25723cbcb96380c3881fadb234530410 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 10 Oct 2019 09:42:06 +0200 Subject: [PATCH 242/545] Add 'unlikely' annotation to branch in crate DepNodeIndex caching. --- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/lib.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ce66534e5659..6f5280843489 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1372,7 +1372,7 @@ impl<'a, 'tcx> CrateMetadata { pub(super) fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex { let mut dep_node_index = self.dep_node_index.load(); - if dep_node_index == DepNodeIndex::INVALID { + 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. diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 9273b064ba9c..6aa684b1c3d0 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -1,6 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(box_patterns)] +#![feature(core_intrinsics)] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] #![feature(in_band_lifetimes)] @@ -11,6 +12,7 @@ #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(specialization)] +#![feature(stmt_expr_attributes)] #![recursion_limit="256"] From 8569dd1db985509cd235fafdd962aa52ced68e35 Mon Sep 17 00:00:00 2001 From: ben Date: Thu, 10 Oct 2019 22:01:55 +1300 Subject: [PATCH 243/545] Preserve output of raw pointers in mir dump. --- src/librustc/mir/mod.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 2b5212cb7efa..9ac1465cb0ba 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2602,7 +2602,14 @@ impl<'tcx> Debug for Constant<'tcx> { impl<'tcx> Display for Constant<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { write!(fmt, "const ")?; - write!(fmt, "{}", self.literal) + // FIXME make the default pretty printing of raw pointers more detailed. Here we output the + // debug representation of raw pointers, so that the raw pointers in the mir dump output are + // detailed and just not '{pointer}'. + if let ty::RawPtr(_) = self.literal.ty.kind { + write!(fmt, "{:?} : {}", self.literal.val, self.literal.ty) + } else { + write!(fmt, "{}", self.literal) + } } } From 169a1cac8de7d25ad70f71373224f56483333c2e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 7 Oct 2019 23:08:54 +0200 Subject: [PATCH 244/545] Don't pass doctest feature by default --- src/librustdoc/config.rs | 5 +---- src/librustdoc/test.rs | 1 + src/test/rustdoc-ui/cfg-test.stdout | 5 ++--- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index fe4e2bd09151..1c0d1b327373 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -343,10 +343,7 @@ impl Options { let output = matches.opt_str("o") .map(|s| PathBuf::from(&s)) .unwrap_or_else(|| PathBuf::from("doc")); - let mut cfgs = matches.opt_strs("cfg"); - if should_test { - cfgs.push("doctest".to_string()); - } + let cfgs = matches.opt_strs("cfg"); let extension_css = matches.opt_str("e").map(|s| PathBuf::from(&s)); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 3e77ca47e8a6..6f805a949afd 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -64,6 +64,7 @@ pub fn run(options: Options) -> i32 { let mut cfgs = options.cfgs.clone(); cfgs.push("rustdoc".to_owned()); + cfgs.push("doctest".to_owned()); let config = interface::Config { opts: sessopts, crate_cfg: config::parse_cfgspecs(cfgs), diff --git a/src/test/rustdoc-ui/cfg-test.stdout b/src/test/rustdoc-ui/cfg-test.stdout index 86141aed5c3f..582344bc81fb 100644 --- a/src/test/rustdoc-ui/cfg-test.stdout +++ b/src/test/rustdoc-ui/cfg-test.stdout @@ -1,7 +1,6 @@ -running 2 tests -test $DIR/cfg-test.rs - Bar (line 28) ... ok +running 1 test test $DIR/cfg-test.rs - Foo (line 20) ... ok -test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out From 3e376f5c1fd0f4f9ad2762115e281b31bf67819f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Oct 2019 10:26:31 +0200 Subject: [PATCH 245/545] Add and update rustdoc ui test --- src/test/rustdoc-ui/cfg-test.stdout | 5 +++-- src/test/rustdoc-ui/doc-test-doctest-feature.rs | 15 +++++++++++++++ .../rustdoc-ui/doc-test-doctest-feature.stdout | 6 ++++++ 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 src/test/rustdoc-ui/doc-test-doctest-feature.rs create mode 100644 src/test/rustdoc-ui/doc-test-doctest-feature.stdout diff --git a/src/test/rustdoc-ui/cfg-test.stdout b/src/test/rustdoc-ui/cfg-test.stdout index 582344bc81fb..86141aed5c3f 100644 --- a/src/test/rustdoc-ui/cfg-test.stdout +++ b/src/test/rustdoc-ui/cfg-test.stdout @@ -1,6 +1,7 @@ -running 1 test +running 2 tests +test $DIR/cfg-test.rs - Bar (line 28) ... ok test $DIR/cfg-test.rs - Foo (line 20) ... ok -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out +test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out diff --git a/src/test/rustdoc-ui/doc-test-doctest-feature.rs b/src/test/rustdoc-ui/doc-test-doctest-feature.rs new file mode 100644 index 000000000000..984d49b43efd --- /dev/null +++ b/src/test/rustdoc-ui/doc-test-doctest-feature.rs @@ -0,0 +1,15 @@ +// build-pass +// compile-flags:--test +// normalize-stdout-test: "src/test/rustdoc-ui" -> "$$DIR" + +#![feature(cfg_doctest)] + +// Make sure `cfg(doctest)` is set when finding doctests but not inside +// the doctests. + +/// ``` +/// #![feature(cfg_doctest)] +/// assert!(!cfg!(doctest)); +/// ``` +#[cfg(doctest)] +pub struct Foo; diff --git a/src/test/rustdoc-ui/doc-test-doctest-feature.stdout b/src/test/rustdoc-ui/doc-test-doctest-feature.stdout new file mode 100644 index 000000000000..75d29fab17d0 --- /dev/null +++ b/src/test/rustdoc-ui/doc-test-doctest-feature.stdout @@ -0,0 +1,6 @@ + +running 1 test +test $DIR/doc-test-doctest-feature.rs - Foo (line 10) ... ok + +test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out + From 19bc0a8c674788539e0d93d072517ea3d7d9a998 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 10 Oct 2019 12:42:04 +0300 Subject: [PATCH 246/545] Mark Path::join as must_use I've accidentally did `mut_path_buf.jon(a_path);`, expecting this to be an in-place modification. Seems like we can easily warn in such cases? --- src/libstd/path.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index fd6ff1032bb8..c8487ad75fe5 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -2219,6 +2219,7 @@ impl Path { /// assert_eq!(Path::new("/etc").join("passwd"), PathBuf::from("/etc/passwd")); /// ``` #[stable(feature = "rust1", since = "1.0.0")] + #[must_use] pub fn join>(&self, path: P) -> PathBuf { self._join(path.as_ref()) } From 847ad6a2ee8088dc802460e6497d1c5c96de823b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Oct 2019 13:51:44 +0200 Subject: [PATCH 247/545] Add long error explanation for E0568 --- src/librustc_passes/error_codes.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/librustc_passes/error_codes.rs b/src/librustc_passes/error_codes.rs index e460e9813b3e..a2626617afec 100644 --- a/src/librustc_passes/error_codes.rs +++ b/src/librustc_passes/error_codes.rs @@ -359,6 +359,35 @@ fn main() {} ``` "##, +E0568: r##" +A super trait has been added to an auto trait. + +Erroneous code example: + +```compile_fail,E0568 +#![feature(optin_builtin_traits)] + +auto trait Bound : Copy {} // error! + +fn main() {} +``` + +Since an auto trait is implemented on all existing types, adding a super trait +would filter out a lot of those types. In the current example, almost none of +all the existing types could implement `Bound` because very few of them have the +`Copy` trait. + +To fix this issue, just remove the super trait: + +``` +#![feature(optin_builtin_traits)] + +auto trait Bound {} // ok! + +fn main() {} +``` +"##, + E0571: r##" A `break` statement with an argument appeared in a non-`loop` loop. @@ -576,7 +605,6 @@ Switch to the Rust 2018 edition to use `async fn`. ; E0226, // only a single explicit lifetime bound is permitted E0472, // asm! is unsupported on this target - E0568, // auto traits can not have super traits E0666, // nested `impl Trait` is illegal E0667, // `impl Trait` in projections E0696, // `continue` pointing to a labeled block From 3c62bdcf6b370460db9dceb0cffef06b2558e0b0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 8 Oct 2019 13:51:58 +0200 Subject: [PATCH 248/545] Update ui tests --- src/test/ui/auto-trait-validation.stderr | 2 +- .../traits/traits-inductive-overflow-supertrait-oibit.stderr | 3 ++- src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr | 1 + src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-trait-validation.stderr index d797f30a2fc8..51422fab81fd 100644 --- a/src/test/ui/auto-trait-validation.stderr +++ b/src/test/ui/auto-trait-validation.stderr @@ -18,5 +18,5 @@ LL | auto trait MyTrait { fn foo() {} } error: aborting due to 3 previous errors -Some errors have detailed explanations: E0380, E0567. +Some errors have detailed explanations: E0380, E0567, E0568. For more information about an error, try `rustc --explain E0380`. 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 40c2c2e4c9d1..63182a6bd958 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr @@ -17,4 +17,5 @@ LL | let (a, b) = copy(NoClone); error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0277`. +Some errors have detailed explanations: E0277, E0568. +For more information about an error, try `rustc --explain E0277`. 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 1184e30749fe..8755bcded9d2 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 @@ -6,3 +6,4 @@ LL | auto trait Magic : Sized where Option : Magic {} error: aborting due to previous error +For more information about this error, try `rustc --explain E0568`. 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 7b45ca07b35c..5a3888349095 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr @@ -6,3 +6,4 @@ LL | auto trait Magic: Copy {} error: aborting due to previous error +For more information about this error, try `rustc --explain E0568`. From 1cdd5d099d3a8da42db6fbd259d3f757bccb961f Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 10 Oct 2019 07:25:54 -0700 Subject: [PATCH 249/545] Improve docs for InstanceDef::ReifyShim. --- src/librustc/ty/instance.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 2b9d09b20ccf..b35b577ddf71 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -28,7 +28,10 @@ pub enum InstanceDef<'tcx> { /// `fn()` pointer where the function itself cannot be turned into a pointer. /// - /// One example in the compiler today is functions annotated with `#[track_caller]`. + /// One example in the compiler today is functions annotated with `#[track_caller]`, which + /// must have their implicit caller location argument populated for a call. Because this is a + /// required part of the function's ABI but can't be tracked as a property of the function + /// pointer, we create a single "caller location" at the site where the function is reified. ReifyShim(DefId), /// `::call_*` From 407d1d5fd4a81b2bc717fc86475209eb59d50fb8 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 10 Oct 2019 07:31:22 -0700 Subject: [PATCH 250/545] Instance::resolve_for_fn_ptr unconditionally resolves first. Per review feedback. --- src/librustc/ty/instance.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index b35b577ddf71..0a86b0b41480 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -310,15 +310,19 @@ impl<'tcx> Instance<'tcx> { substs: SubstsRef<'tcx>, ) -> Option> { debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); - if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::TRACK_CALLER) { - debug!(" => fn pointer created for function with #[track_caller]"); - Some(Instance { - def: InstanceDef::ReifyShim(def_id), - substs, - }) - } else { - Instance::resolve(tcx, param_env, def_id, substs) - } + Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| { + let resolved_def = resolved.def_id(); + let codegen_attrs = tcx.codegen_fn_attrs(resolved_def); + if codegen_attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) { + debug!(" => fn pointer created for function with #[track_caller]"); + Instance { + def: InstanceDef::ReifyShim(resolved_def), + substs, + } + } else { + resolved + } + }) } pub fn resolve_for_vtable( From 2dbc62b56a1ce0457108c86156a6ab357d870f08 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Thu, 10 Oct 2019 07:50:33 -0700 Subject: [PATCH 251/545] Clarify shim implementation comment. --- src/librustc_mir/shim.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 0d13daa26430..c4d66ee7dbd7 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -69,7 +69,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx // We are generating a call back to our def-id, which the // codegen backend knows to turn to an actual virtual call. ty::InstanceDef::Virtual(def_id, _) | - // ...or we are generating a call to the inner closure defined by #[track_caller] + // ...or we are generating a direct call to our #[track_caller] function which + // requires an implicit caller location that the virtual call won't pass ty::InstanceDef::ReifyShim(def_id) => { build_call_shim( tcx, From 6afc5091b91c357285f224564d9f8416f52041b1 Mon Sep 17 00:00:00 2001 From: BaoshanPang Date: Wed, 9 Oct 2019 09:10:24 -0700 Subject: [PATCH 252/545] vxWorks: implement get_path() and get_mode() for File fmt::Debug --- src/libstd/sys/vxworks/fs.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/src/libstd/sys/vxworks/fs.rs b/src/libstd/sys/vxworks/fs.rs index 51fdb1c0e55e..adb08d8005ad 100644 --- a/src/libstd/sys/vxworks/fs.rs +++ b/src/libstd/sys/vxworks/fs.rs @@ -400,13 +400,27 @@ impl FromInner for File { impl fmt::Debug for File { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fn get_path(_fd: c_int) -> Option { - // FIXME(#:(): implement this for VxWorks - None + fn get_path(fd: c_int) -> Option { + let mut buf = vec![0;libc::PATH_MAX as usize]; + let n = unsafe { libc::ioctl(fd, libc::FIOGETNAME, buf.as_ptr()) }; + if n == -1 { + return None; + } + let l = buf.iter().position(|&c| c == 0).unwrap(); + buf.truncate(l as usize); + Some(PathBuf::from(OsString::from_vec(buf))) } - fn get_mode(_fd: c_int) -> Option<(bool, bool)> { - // FIXME(#:(): implement this for VxWorks - None + fn get_mode(fd: c_int) -> Option<(bool, bool)> { + let mode = unsafe { libc::fcntl(fd, libc::F_GETFL) }; + if mode == -1 { + return None; + } + match mode & libc::O_ACCMODE { + libc::O_RDONLY => Some((true, false)), + libc::O_RDWR => Some((true, true)), + libc::O_WRONLY => Some((false, true)), + _ => None + } } let fd = self.0.raw(); From 373c362b7ed0df2dfbc21853e53d5082f20d3de8 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Thu, 10 Oct 2019 18:21:34 +0200 Subject: [PATCH 253/545] Check that we don't access nonexisting union fields --- src/librustc_target/abi/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 26d37f196bef..fde5c5bed4d9 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -738,7 +738,11 @@ impl FieldPlacement { pub fn offset(&self, i: usize) -> Size { match *self { - FieldPlacement::Union(_) => Size::ZERO, + FieldPlacement::Union(count) => { + assert!(i < count, + "Tried to access field {} of union with {} fields", i, count); + Size::ZERO + }, FieldPlacement::Array { stride, count } => { let i = i as u64; assert!(i < count); From fb392c5ed638db9955a0323bb127c8c21b3db350 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 10 Oct 2019 17:23:28 +0100 Subject: [PATCH 254/545] Don't cc rust-lang/compiler for toolstate changes --- src/tools/publish_toolstate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 7cf3cc7663b4..4383cd9d5be4 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -143,7 +143,7 @@ def issue( cc @{}, do you think you would have time to do the follow-up work? If so, that would be great! - cc @{}, the PR reviewer, and @rust-lang/compiler -- nominating for prioritization. + cc @{}, the PR reviewer, and nominating for compiler team prioritization. ''').format( relevant_pr_number, tool, status_description, From 9f6942066bd86a55baf56455a2c53d7d79b6038e Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 10 Oct 2019 22:20:57 +0800 Subject: [PATCH 255/545] query generator kind for error reporting --- src/librustc/hir/mod.rs | 4 ++ .../borrow_check/conflict_errors.rs | 30 +++++++++---- .../borrow_check/error_reporting.rs | 45 ++++++++++++------- ...async-borrowck-escaping-block-error.stderr | 2 +- 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e72f46682cee..7350f89018be 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1366,6 +1366,10 @@ impl Body { hir_id: self.value.hir_id, } } + + pub fn generator_kind(&self) -> Option { + self.generator_kind + } } /// The type of source expression that caused this generator to be created. diff --git a/src/librustc_mir/borrow_check/conflict_errors.rs b/src/librustc_mir/borrow_check/conflict_errors.rs index 2f9df7bd77e8..098258994f4e 100644 --- a/src/librustc_mir/borrow_check/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/conflict_errors.rs @@ -1,5 +1,6 @@ use rustc::hir; use rustc::hir::def_id::DefId; +use rustc::hir::{AsyncGeneratorKind, GeneratorKind}; use rustc::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, Local, LocalDecl, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, @@ -788,7 +789,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .. }, ) if borrow_spans.for_closure() => self.report_escaping_closure_capture( - borrow_spans.args_or_use(), + borrow_spans, borrow_span, region_name, category, @@ -806,7 +807,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }, ) if borrow_spans.for_generator() => self.report_escaping_closure_capture( - borrow_spans.args_or_use(), + borrow_spans, borrow_span, region_name, category, @@ -1195,7 +1196,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn report_escaping_closure_capture( &mut self, - args_span: Span, + use_span: UseSpans, var_span: Span, fr_name: &RegionName, category: ConstraintCategory, @@ -1203,7 +1204,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { captured_var: &str, ) -> DiagnosticBuilder<'cx> { let tcx = self.infcx.tcx; - + let args_span = use_span.args_or_use(); let mut err = self.cannot_capture_in_long_lived_closure( args_span, captured_var, @@ -1223,12 +1224,25 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }, Err(_) => "move || ".to_string() }; - + let kind = match use_span.generator_kind() { + Some(generator_kind) => match generator_kind { + GeneratorKind::Async(async_kind) => match async_kind { + AsyncGeneratorKind::Block => "async block", + AsyncGeneratorKind::Closure => "async closure", + _ => bug!("async block/closure expected, but async funtion found."), + }, + GeneratorKind::Gen => "generator", + } + None => "closure", + }; err.span_suggestion( args_span, - &format!("to force the closure to take ownership of {} (and any \ - other referenced variables), use the `move` keyword", - captured_var), + &format!( + "to force the {} to take ownership of {} (and any \ + other referenced variables), use the `move` keyword", + kind, + captured_var + ), suggestion, Applicability::MachineApplicable, ); diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index dc7e4b220658..5e0727d51579 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1,6 +1,7 @@ use rustc::hir; use rustc::hir::def::Namespace; use rustc::hir::def_id::DefId; +use rustc::hir::GeneratorKind; use rustc::mir::{ AggregateKind, Constant, Field, Local, LocalKind, Location, Operand, Place, PlaceBase, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, @@ -14,7 +15,7 @@ use syntax_pos::Span; use syntax::symbol::sym; use super::borrow_set::BorrowData; -use super::{MirBorrowckCtxt}; +use super::MirBorrowckCtxt; use crate::dataflow::move_paths::{InitLocation, LookupResult}; pub(super) struct IncludingDowncast(pub(super) bool); @@ -604,7 +605,7 @@ pub(super) enum UseSpans { // The access is caused by capturing a variable for a closure. ClosureUse { // This is true if the captured variable was from a generator. - is_generator: bool, + generator_kind: Option, // The span of the args of the closure, including the `move` keyword if // it's present. args_span: Span, @@ -631,6 +632,13 @@ impl UseSpans { } } + pub(super) fn generator_kind(self) -> Option { + match self { + UseSpans::ClosureUse { generator_kind, .. } => generator_kind, + _ => None, + } + } + // Add a span label to the arguments of the closure, if it exists. pub(super) fn args_span_label( self, @@ -656,7 +664,7 @@ impl UseSpans { /// Returns `false` if this place is not used in a closure. pub(super) fn for_closure(&self) -> bool { match *self { - UseSpans::ClosureUse { is_generator, .. } => !is_generator, + UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_none(), _ => false, } } @@ -664,7 +672,7 @@ impl UseSpans { /// Returns `false` if this place is not used in a generator. pub(super) fn for_generator(&self) -> bool { match *self { - UseSpans::ClosureUse { is_generator, .. } => is_generator, + UseSpans::ClosureUse { generator_kind, .. } => generator_kind.is_some(), _ => false, } } @@ -672,7 +680,7 @@ impl UseSpans { /// Describe the span associated with a use of a place. pub(super) fn describe(&self) -> String { match *self { - UseSpans::ClosureUse { is_generator, .. } => if is_generator { + UseSpans::ClosureUse { generator_kind, .. } => if generator_kind.is_some() { " in generator".to_string() } else { " in closure".to_string() @@ -794,19 +802,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let StatementKind::Assign( box(_, Rvalue::Aggregate(ref kind, ref places)) ) = stmt.kind { - let (def_id, is_generator) = match kind { - box AggregateKind::Closure(def_id, _) => (def_id, false), - box AggregateKind::Generator(def_id, _, _) => (def_id, true), + let def_id = match kind { + box AggregateKind::Closure(def_id, _) + | box AggregateKind::Generator(def_id, _, _) => def_id, _ => return OtherUse(stmt.source_info.span), }; debug!( - "move_spans: def_id={:?} is_generator={:?} places={:?}", - def_id, is_generator, places + "move_spans: def_id={:?} places={:?}", + def_id, places ); - if let Some((args_span, var_span)) = self.closure_span(*def_id, moved_place, places) { + if let Some((args_span, generator_kind, var_span)) + = self.closure_span(*def_id, moved_place, places) { return ClosureUse { - is_generator, + generator_kind, args_span, var_span, }; @@ -857,11 +866,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "borrow_spans: def_id={:?} is_generator={:?} places={:?}", def_id, is_generator, places ); - if let Some((args_span, var_span)) = self.closure_span( + if let Some((args_span, generator_kind, var_span)) = self.closure_span( *def_id, Place::from(target).as_ref(), places ) { return ClosureUse { - is_generator, + generator_kind, args_span, var_span, }; @@ -884,7 +893,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { def_id: DefId, target_place: PlaceRef<'cx, 'tcx>, places: &Vec>, - ) -> Option<(Span, Span)> { + ) -> Option<(Span, Option, Span)> { debug!( "closure_span: def_id={:?} target_place={:?} places={:?}", def_id, target_place, places @@ -893,14 +902,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind; debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr); if let hir::ExprKind::Closure( - .., args_span, _ + .., body_id, args_span, _ ) = expr { for (upvar, place) in self.infcx.tcx.upvars(def_id)?.values().zip(places) { match place { Operand::Copy(place) | Operand::Move(place) if target_place == place.as_ref() => { debug!("closure_span: found captured local {:?}", place); - return Some((*args_span, upvar.span)); + let body = self.infcx.tcx.hir().body(*body_id); + let generator_kind = body.generator_kind(); + return Some((*args_span, generator_kind, upvar.span)); }, _ => {} } diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr index af17ecc86fbf..0eb3971d14a3 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -12,7 +12,7 @@ note: generator is returned here | LL | fn foo() -> Box> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword +help: to force the async block to take ownership of `x` (and any other referenced variables), use the `move` keyword | LL | Box::new(async move { x } ) | ^^^^^^^^^^ From ceb4c3fa308459fa74708d1b4f525a496e4e115e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Oct 2019 23:37:41 +0300 Subject: [PATCH 256/545] stability: Do not use `buffer_lint` after lowering to HIR --- src/librustc/middle/stability.rs | 14 +++++++++++--- src/librustc_resolve/macros.rs | 7 ++++++- src/test/ui/feature-gates/bench.rs | 4 ++++ src/test/ui/feature-gates/bench.stderr | 13 +++++++++++-- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 30a88d155f5f..302c11f309d9 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -485,7 +485,13 @@ pub fn provide(providers: &mut Providers<'_>) { } pub fn report_unstable( - sess: &Session, feature: Symbol, reason: Option, issue: u32, is_soft: bool, span: Span + sess: &Session, + feature: Symbol, + reason: Option, + issue: u32, + is_soft: bool, + span: Span, + soft_handler: impl FnOnce(&'static lint::Lint, Span, &str), ) { let msg = match reason { Some(r) => format!("use of unstable library feature '{}': {}", feature, r), @@ -511,7 +517,7 @@ pub fn report_unstable( let fresh = sess.one_time_diagnostics.borrow_mut().insert(error_id); if fresh { if is_soft { - sess.buffer_lint(lint::builtin::SOFT_UNSTABLE, CRATE_NODE_ID, span, &msg); + soft_handler(lint::builtin::SOFT_UNSTABLE, span, &msg) } else { emit_feature_err( &sess.parse_sess, feature, span, GateIssue::Library(Some(issue)), &msg @@ -779,10 +785,12 @@ impl<'tcx> TyCtxt<'tcx> { /// Additionally, this function will also check if the item is deprecated. If so, and `id` is /// not `None`, a deprecated lint attached to `id` will be emitted. pub fn check_stability(self, def_id: DefId, id: Option, span: Span) { + let soft_handler = + |lint, span, msg: &_| self.lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg); match self.eval_stability(def_id, id, span) { EvalResult::Allow => {} EvalResult::Deny { feature, reason, issue, is_soft } => - report_unstable(self.sess, feature, reason, issue, is_soft, span), + report_unstable(self.sess, feature, reason, issue, is_soft, span, soft_handler), EvalResult::Unmarked => { // The API could be uncallable for other reasons, for example when a private module // was referenced. diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index ae483354a40d..2b87bba83861 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -796,7 +796,12 @@ impl<'a> Resolver<'a> { if let StabilityLevel::Unstable { reason, issue, is_soft } = stability.level { let feature = stability.feature; if !self.active_features.contains(&feature) && !span.allows_unstable(feature) { - stability::report_unstable(self.session, feature, reason, issue, is_soft, span); + let node_id = ast::CRATE_NODE_ID; + let soft_handler = + |lint, span, msg: &_| self.session.buffer_lint(lint, node_id, span, msg); + stability::report_unstable( + self.session, feature, reason, issue, is_soft, span, soft_handler + ); } } if let Some(depr) = &stability.rustc_depr { diff --git a/src/test/ui/feature-gates/bench.rs b/src/test/ui/feature-gates/bench.rs index afe4dc7d54c9..8de390becbe7 100644 --- a/src/test/ui/feature-gates/bench.rs +++ b/src/test/ui/feature-gates/bench.rs @@ -1,5 +1,9 @@ +// edition:2018 + #[bench] //~ ERROR use of unstable library feature 'test' //~| WARN this was previously accepted fn bench() {} +use bench as _; //~ ERROR use of unstable library feature 'test' + //~| WARN this was previously accepted fn main() {} diff --git a/src/test/ui/feature-gates/bench.stderr b/src/test/ui/feature-gates/bench.stderr index b9e24e931d42..168ac9257243 100644 --- a/src/test/ui/feature-gates/bench.stderr +++ b/src/test/ui/feature-gates/bench.stderr @@ -1,5 +1,5 @@ error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable - --> $DIR/bench.rs:1:3 + --> $DIR/bench.rs:3:3 | LL | #[bench] | ^^^^^ @@ -8,5 +8,14 @@ LL | #[bench] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #64266 -error: aborting due to previous error +error: use of unstable library feature 'test': `bench` is a part of custom test frameworks which are unstable + --> $DIR/bench.rs:7:5 + | +LL | use bench as _; + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #64266 + +error: aborting due to 2 previous errors From e0ef7767cab847f73e145d3f2eb99aef02c94067 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 9 Oct 2019 01:59:14 +0900 Subject: [PATCH 257/545] Add long error explanation for E0697 --- src/librustc/error_codes.rs | 19 ++++++++++++++++++- src/test/ui/static/static-closures.stderr | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index e208e25f6ea9..a4c1afc4f1da 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2001,6 +2001,24 @@ a (non-transparent) struct containing a single float, while `Grams` is a transparent wrapper around a float. This can make a difference for the ABI. "##, +E0697: r##" +A closure has been used as `static`. + +Erroneous code example: + +```compile_fail,E0697 +fn main() { + static || {}; // used as `static` +} +``` + +Closures cannot be used as `static`. They "save" the environment. +Therefore, having a static closure with a static environment doesn't +really make sense since all you can capture inside it would be variables +with static lifetime. In this condition, better use a function directly. +The easiest fix is to remove `static` keyword. +"##, + E0698: r##" When using generators (or async) all type variables must be bound so a generator can be constructed. @@ -2187,7 +2205,6 @@ See [RFC 2091] for details on this and other limitations. E0657, // `impl Trait` can only capture lifetimes bound at the fn level E0687, // in-band lifetimes cannot be used in `fn`/`Fn` syntax E0688, // in-band lifetimes cannot be mixed with explicit lifetime binders - E0697, // closures cannot be static // E0707, // multiple elided lifetimes used in arguments of `async fn` E0708, // `async` non-`move` closures with parameters are not currently // supported diff --git a/src/test/ui/static/static-closures.stderr b/src/test/ui/static/static-closures.stderr index ced78c03e09d..99235e26e15e 100644 --- a/src/test/ui/static/static-closures.stderr +++ b/src/test/ui/static/static-closures.stderr @@ -6,3 +6,4 @@ LL | static || {}; error: aborting due to previous error +For more information about this error, try `rustc --explain E0697`. From c97d71538a3f91cad1c530d7ba4456aa595122aa Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 11 Oct 2019 00:51:36 +0100 Subject: [PATCH 258/545] Fix issue 65284 --- src/librustc_typeck/check/method/suggest.rs | 36 ++++++++----------- ...issue-65284-suggest-generic-trait-bound.rs | 11 ++++++ ...e-65284-suggest-generic-trait-bound.stderr | 15 ++++++++ 3 files changed, 41 insertions(+), 21 deletions(-) create mode 100644 src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs create mode 100644 src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index b4b84b61fd62..80cdcf566be6 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -785,31 +785,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Get the `hir::Param` to verify whether it already has any bounds. // We do this to avoid suggesting code that ends up as `T: FooBar`, // instead we suggest `T: Foo + Bar` in that case. - let mut has_bounds = false; + let mut has_bounds = None; let mut impl_trait = false; if let Node::GenericParam(ref param) = hir.get(id) { - match param.kind { - hir::GenericParamKind::Type { synthetic: Some(_), .. } => { - // We've found `fn foo(x: impl Trait)` instead of - // `fn foo(x: T)`. We want to suggest the correct - // `fn foo(x: impl Trait + TraitBound)` instead of - // `fn foo(x: T)`. (#63706) - impl_trait = true; - has_bounds = param.bounds.len() > 1; - } - _ => { - has_bounds = !param.bounds.is_empty(); - } + let kind = ¶m.kind; + if let hir::GenericParamKind::Type { synthetic: Some(_), .. } = kind { + // We've found `fn foo(x: impl Trait)` instead of + // `fn foo(x: T)`. We want to suggest the correct + // `fn foo(x: impl Trait + TraitBound)` instead of + // `fn foo(x: T)`. (See #63706.) + impl_trait = true; + has_bounds = param.bounds.get(1); + } else { + has_bounds = param.bounds.get(0); } } let sp = hir.span(id); - // `sp` only covers `T`, change it so that it covers - // `T:` when appropriate - let sp = if has_bounds { - sp.to(self.tcx - .sess - .source_map() - .next_point(self.tcx.sess.source_map().next_point(sp))) + // `sp` only covers `T`, change it so that it covers `T:` when appropriate. + let sp = if let Some(first_bound) = has_bounds { + sp.until(first_bound.span()) } else { sp }; @@ -825,7 +819,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { param, if impl_trait { " +" } else { ":" }, self.tcx.def_path_str(t.def_id), - if has_bounds { " +"} else { "" }, + if has_bounds.is_some() { " + " } else { "" }, )), Applicability::MaybeIncorrect, ); diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs new file mode 100644 index 000000000000..e0eaafdfc2f2 --- /dev/null +++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.rs @@ -0,0 +1,11 @@ +trait Foo { + fn foo(&self); +} + +trait Bar {} + +fn do_stuff(t : T) { + t.foo() //~ ERROR no method named `foo` found for type `T` in the current scope +} + +fn main() {} diff --git a/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr new file mode 100644 index 000000000000..24bf60abf6a7 --- /dev/null +++ b/src/test/ui/issues/issue-65284-suggest-generic-trait-bound.stderr @@ -0,0 +1,15 @@ +error[E0599]: no method named `foo` found for type `T` in the current scope + --> $DIR/issue-65284-suggest-generic-trait-bound.rs:8:7 + | +LL | t.foo() + | ^^^ method not found in `T` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `foo`, perhaps you need to restrict type parameter `T` with it: + | +LL | fn do_stuff(t : T) { + | ^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 5bb0a03fa77e3f08724e9a4745703a1774f43921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Oct 2019 19:34:56 -0700 Subject: [PATCH 259/545] Move diagnostics code out of the critical path --- src/librustc_typeck/check/method/mod.rs | 41 +++++++++++++------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 434ead50e042..e57cc809c347 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -213,27 +213,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { segment, ); - let mut needs_mut = false; - if let ty::Ref(region, t_type, mutability) = self_ty.kind { - let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { - ty: t_type, - mutbl: mutability.invert(), - }); - match self.lookup_probe( - span, - segment.ident, - trait_type, - call_expr, - ProbeScope::TraitsInScope - ) { - Ok(ref new_pick) if *new_pick != pick => { - needs_mut = true; - } - _ => {} - } - } - if result.illegal_sized_bound { + let mut needs_mut = false; + if let ty::Ref(region, t_type, mutability) = self_ty.kind { + let trait_type = self.tcx.mk_ref(region, ty::TypeAndMut { + ty: t_type, + mutbl: mutability.invert(), + }); + // We probe again to see if there might be a borrow mutability discrepancy. + match self.lookup_probe( + span, + segment.ident, + trait_type, + call_expr, + ProbeScope::TraitsInScope + ) { + Ok(ref new_pick) if *new_pick != pick => { + needs_mut = true; + } + _ => {} + } + } + // We probe again, taking all traits into account (not only those in scope). let candidates = match self.lookup_probe( span, From 91cf02cfa773d7b7612f3e20d5361f36f17d047b Mon Sep 17 00:00:00 2001 From: Charles Gleason Date: Thu, 3 Oct 2019 15:03:59 -0400 Subject: [PATCH 260/545] Implement Clone::clone_from for VecDeque --- src/liballoc/collections/vec_deque.rs | 81 ++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index a4a0fbb194dd..42c00fd121dd 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -10,8 +10,8 @@ use core::array::LengthAtMost32; use core::cmp::{self, Ordering}; use core::fmt; -use core::iter::{repeat_with, FromIterator, FusedIterator}; -use core::mem; +use core::iter::{once, repeat_with, FromIterator, FusedIterator}; +use core::mem::{self, replace}; use core::ops::Bound::{Excluded, Included, Unbounded}; use core::ops::{Index, IndexMut, RangeBounds, Try}; use core::ptr::{self, NonNull}; @@ -57,11 +57,88 @@ pub struct VecDeque { buf: RawVec, } +/// PairSlices pairs up equal length slice parts of two deques +/// +/// For example, given deques "A" and "B" with the following division into slices: +/// +/// A: [0 1 2] [3 4 5] +/// B: [a b] [c d e] +/// +/// It produces the following sequence of matching slices: +/// +/// ([0 1], [a b]) +/// ([2], [c]) +/// ([3 4], [d e]) +/// +/// and the uneven remainder of either A or B is skipped. +struct PairSlices<'a, 'b, T> { + a0: &'a mut [T], + a1: &'a mut [T], + b0: &'b [T], + b1: &'b [T], +} + +impl<'a, 'b, T> PairSlices<'a, 'b, T> { + fn from(to: &'a mut VecDeque, from: &'b VecDeque) -> Self { + let (a0, a1) = to.as_mut_slices(); + let (b0, b1) = from.as_slices(); + PairSlices { a0, a1, b0, b1 } + } + + fn has_remainder(&self) -> bool { + !self.b0.is_empty() + } + + fn remainder(self) -> impl Iterator { + once(self.b0).chain(once(self.b1)) + } +} + +impl<'a, 'b, T> Iterator for PairSlices<'a, 'b, T> +{ + type Item = (&'a mut [T], &'b [T]); + fn next(&mut self) -> Option { + // Get next part length + let part = cmp::min(self.a0.len(), self.b0.len()); + if part == 0 { + return None; + } + let (p0, p1) = replace(&mut self.a0, &mut []).split_at_mut(part); + let (q0, q1) = self.b0.split_at(part); + + // Move a1 into a0, if it's empty (and b1, b0 the same way). + self.a0 = p1; + self.b0 = q1; + if self.a0.is_empty() { + self.a0 = replace(&mut self.a1, &mut []); + } + if self.b0.is_empty() { + self.b0 = replace(&mut self.b1, &[]); + } + Some((p0, q0)) + } +} + #[stable(feature = "rust1", since = "1.0.0")] impl Clone for VecDeque { fn clone(&self) -> VecDeque { self.iter().cloned().collect() } + + fn clone_from(&mut self, other: &Self) { + self.truncate(other.len()); + + let mut iter = PairSlices::from(self, other); + while let Some((dst, src)) = iter.next() { + dst.clone_from_slice(&src); + } + + if iter.has_remainder() { + for remainder in iter.remainder() { + self.extend(remainder.iter().cloned()); + } + } + } } #[stable(feature = "rust1", since = "1.0.0")] From 10671f10c3559f6b96593149dce5467b0feccab6 Mon Sep 17 00:00:00 2001 From: Charles Gleason Date: Thu, 3 Oct 2019 15:04:35 -0400 Subject: [PATCH 261/545] Add tests for VecDeque clone_from --- src/liballoc/collections/vec_deque/tests.rs | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/liballoc/collections/vec_deque/tests.rs b/src/liballoc/collections/vec_deque/tests.rs index d25352399796..d578ee0dac49 100644 --- a/src/liballoc/collections/vec_deque/tests.rs +++ b/src/liballoc/collections/vec_deque/tests.rs @@ -361,6 +361,29 @@ fn test_vec_from_vecdeque() { } } +#[test] +fn test_clone_from() { + let m = vec![1; 8]; + let n = vec![2; 12]; + for pfv in 0..8 { + for pfu in 0..8 { + for longer in 0..2 { + let (vr, ur) = if longer == 0 { (&m, &n) } else { (&n, &m) }; + let mut v = VecDeque::from(vr.clone()); + for _ in 0..pfv { + v.push_front(1); + } + let mut u = VecDeque::from(ur.clone()); + for _ in 0..pfu { + u.push_front(2); + } + v.clone_from(&u); + assert_eq!(&v, &u); + } + } + } +} + #[test] fn issue_53529() { use crate::boxed::Box; From d21eeb110c64d677652a03e858db1833ddf7761b Mon Sep 17 00:00:00 2001 From: Charles Gleason Date: Fri, 4 Oct 2019 19:07:13 -0400 Subject: [PATCH 262/545] Override nth for VecDeque Iter and IterMut --- src/liballoc/collections/vec_deque.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 42c00fd121dd..0bf573f5e253 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -2286,6 +2286,16 @@ impl<'a, T> Iterator for Iter<'a, T> { final_res } + fn nth(&mut self, n: usize) -> Option { + if n >= count(self.tail, self.head, self.ring.len()) { + self.tail = self.head; + None + } else { + self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); + self.next() + } + } + #[inline] fn last(mut self) -> Option<&'a T> { self.next_back() @@ -2404,6 +2414,16 @@ impl<'a, T> Iterator for IterMut<'a, T> { back.iter_mut().fold(accum, &mut f) } + fn nth(&mut self, n: usize) -> Option { + if n >= count(self.tail, self.head, self.ring.len()) { + self.tail = self.head; + None + } else { + self.tail = wrap_index(self.tail.wrapping_add(n), self.ring.len()); + self.next() + } + } + #[inline] fn last(mut self) -> Option<&'a mut T> { self.next_back() From 2ae5e3421d986339b53792157c45cb2e98374027 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 11 Oct 2019 08:58:35 +0900 Subject: [PATCH 263/545] Print lifetimes with backticks --- src/librustc/infer/error_reporting/mod.rs | 6 ++--- ...ssociated-const-impl-wrong-lifetime.stderr | 2 +- ...ject-fn-ret-contravariant.transmute.stderr | 2 +- .../project-fn-ret-invariant.transmute.stderr | 2 +- .../async-await/issues/issue-63388-2.stderr | 4 ++-- ...regions-bound-missing-bound-in-impl.stderr | 4 ++-- src/test/ui/c-variadic/variadic-ffi-4.stderr | 2 +- .../expect-fn-supply-fn.stderr | 4 ++-- .../expect-region-supply-region.stderr | 4 ++-- src/test/ui/error-codes/E0478.stderr | 4 ++-- .../explicit-self-lifetime-mismatch.stderr | 8 +++---- ...hr-subtype.free_inv_x_vs_free_inv_y.stderr | 8 +++---- .../hr-subtype.free_x_vs_free_y.stderr | 4 ++-- .../dyn-trait.stderr | 2 +- .../ui/impl-trait/hidden-lifetimes.stderr | 4 ++-- .../must_outlive_least_region_or_bound.stderr | 8 +++---- .../impl-trait/region-escape-via-bound.stderr | 2 +- .../static-return-lifetime-infered.stderr | 4 ++-- .../mismatched_trait_impl.nll.stderr | 2 +- .../mismatched_trait_impl.stderr | 2 +- src/test/ui/issues/issue-10291.stderr | 2 +- src/test/ui/issues/issue-16683.stderr | 2 +- src/test/ui/issues/issue-17740.stderr | 4 ++-- src/test/ui/issues/issue-17758.stderr | 2 +- src/test/ui/issues/issue-17905-2.stderr | 4 ++-- .../ui/issues/issue-20831-debruijn.stderr | 6 ++--- src/test/ui/issues/issue-27942.stderr | 4 ++-- src/test/ui/issues/issue-28848.stderr | 4 ++-- src/test/ui/issues/issue-37884.stderr | 2 +- src/test/ui/issues/issue-52213.stderr | 4 ++-- src/test/ui/issues/issue-55796.stderr | 4 ++-- .../lifetime-bound-will-change-warning.stderr | 4 ++-- src/test/ui/lub-if.stderr | 4 ++-- src/test/ui/lub-match.stderr | 4 ++-- .../ui/match/match-ref-mut-invariance.stderr | 4 ++-- .../match/match-ref-mut-let-invariance.stderr | 4 ++-- src/test/ui/nll/issue-50716.stderr | 2 +- src/test/ui/nll/issue-52742.stderr | 2 +- src/test/ui/nll/issue-55394.stderr | 2 +- src/test/ui/nll/issue-55401.stderr | 2 +- .../ui/nll/normalization-bounds-error.stderr | 4 ++-- .../ui/nll/trait-associated-constant.stderr | 4 ++-- .../ui/nll/type-alias-free-regions.stderr | 4 ++-- .../constant-in-expr-inherent-1.stderr | 2 +- .../constant-in-expr-normalize.stderr | 2 +- .../constant-in-expr-trait-item-1.stderr | 2 +- .../constant-in-expr-trait-item-2.stderr | 2 +- .../constant-in-expr-trait-item-3.stderr | 2 +- .../object-lifetime-default-elision.stderr | 8 +++---- ...ifetime-default-from-rptr-box-error.stderr | 2 +- ...time-default-from-rptr-struct-error.stderr | 2 +- .../object-lifetime-default-mybox.stderr | 2 +- ...unds-on-objects-and-type-parameters.stderr | 4 ++-- ...region-invariant-static-error-reporting.rs | 2 +- ...on-invariant-static-error-reporting.stderr | 2 +- .../regions/region-object-lifetime-2.stderr | 4 ++-- .../regions/region-object-lifetime-4.stderr | 4 ++-- .../region-object-lifetime-in-coercion.stderr | 4 ++-- .../regions/regions-addr-of-upvar-self.stderr | 2 +- ...pertrait-outlives-container.migrate.stderr | 4 ++-- ...-type-region-bound-in-trait-not-met.stderr | 6 ++--- ...-type-static-bound-in-trait-not-met.stderr | 2 +- src/test/ui/regions/regions-bounds.stderr | 8 +++---- .../regions-close-object-into-object-2.stderr | 2 +- .../regions-close-object-into-object-4.stderr | 2 +- ...-close-over-type-parameter-multiple.stderr | 4 ++-- .../ui/regions/regions-creating-enums4.stderr | 4 ++-- .../regions-early-bound-error-method.stderr | 4 ++-- .../regions/regions-early-bound-error.stderr | 4 ++-- ...gions-free-region-ordering-callee-4.stderr | 4 ++-- ...ions-free-region-ordering-incorrect.stderr | 4 ++-- ...-implied-bounds-projection-gap-hr-1.stderr | 4 ++-- ...egions-infer-invariance-due-to-decl.stderr | 2 +- ...nfer-invariance-due-to-mutability-3.stderr | 2 +- ...nfer-invariance-due-to-mutability-4.stderr | 2 +- .../ui/regions/regions-infer-not-param.stderr | 12 +++++----- .../regions-infer-paramd-indirect.stderr | 2 +- src/test/ui/regions/regions-nested-fns.stderr | 2 +- ...ions-normalize-in-where-clause-list.stderr | 4 ++-- ...s-projection-container-hrtb.migrate.stderr | 8 +++---- ...ves-projection-container-wc.migrate.stderr | 4 ++-- ...gions-outlives-projection-container.stderr | 16 ++++++------- .../ui/regions/regions-ret-borrowed-1.stderr | 2 +- .../ui/regions/regions-ret-borrowed.stderr | 2 +- ...ons-return-ref-to-upvar-issue-17403.stderr | 2 +- .../regions-static-bound.migrate.stderr | 2 +- src/test/ui/regions/regions-trait-1.stderr | 2 +- .../regions-trait-object-subtyping.stderr | 12 +++++----- ...ns-variance-invariant-use-covariant.stderr | 2 +- .../ui/regions/regions-wf-trait-object.stderr | 4 ++-- .../ui/reject-specialized-drops-8142.stderr | 6 ++--- ...ns-outlives-nominal-type-region-rev.stderr | 4 ++-- ...egions-outlives-nominal-type-region.stderr | 4 ++-- ...ions-outlives-nominal-type-type-rev.stderr | 4 ++-- .../regions-outlives-nominal-type-type.stderr | 4 ++-- .../regions-struct-not-wf.stderr | 4 ++-- ...types_pin_lifetime_impl_trait-async.stderr | 4 ++-- src/test/ui/static/static-lifetime.stderr | 2 +- ...trait-has-wrong-lifetime-parameters.stderr | 4 ++-- .../ui/traits/trait-matching-lifetimes.stderr | 8 +++---- .../ui/ufcs/ufcs-explicit-self-bad.stderr | 8 +++---- .../variance-btree-invariant-types.stderr | 24 +++++++++---------- .../variance-contravariant-arg-object.stderr | 8 +++---- ...iance-contravariant-arg-trait-match.stderr | 8 +++---- ...ance-contravariant-self-trait-match.stderr | 8 +++---- .../variance-covariant-arg-object.stderr | 8 +++---- .../variance-covariant-arg-trait-match.stderr | 8 +++---- ...variance-covariant-self-trait-match.stderr | 8 +++---- .../variance-invariant-arg-object.stderr | 8 +++---- .../variance-invariant-arg-trait-match.stderr | 8 +++---- ...variance-invariant-self-trait-match.stderr | 8 +++---- ...variance-use-contravariant-struct-1.stderr | 4 ++-- .../variance-use-covariant-struct-1.stderr | 4 ++-- .../variance-use-invariant-struct-1.stderr | 8 +++---- src/test/ui/wf/wf-static-method.stderr | 20 ++++++++-------- 115 files changed, 260 insertions(+), 260 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index f1192c7ce10a..f6068855e630 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -200,7 +200,7 @@ impl<'tcx> TyCtxt<'tcx> { { sp = param.span; } - (format!("the lifetime {} as defined on", br.name), sp) + (format!("the lifetime `{}` as defined on", br.name), sp) } ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), @@ -213,7 +213,7 @@ impl<'tcx> TyCtxt<'tcx> { { sp = param.span; } - (format!("the lifetime {} as defined on", name), sp) + (format!("the lifetime `{}` as defined on", name), sp) } ty::ReFree(ref fr) => match fr.bound_region { ty::BrAnon(idx) => ( @@ -221,7 +221,7 @@ impl<'tcx> TyCtxt<'tcx> { self.hir().span(node), ), _ => ( - format!("the lifetime {} as defined on", region), + format!("the lifetime `{}` as defined on", region), cm.def_span(self.hir().span(node)), ), }, diff --git a/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.stderr b/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.stderr index c213cfeeafa1..2ceab394e955 100644 --- a/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.stderr +++ b/src/test/ui/associated-const/associated-const-impl-wrong-lifetime.stderr @@ -6,7 +6,7 @@ LL | const NAME: &'a str = "unit"; | = note: expected type `&'static str` found type `&'a str` -note: the lifetime 'a as defined on the impl at 6:6... +note: the lifetime `'a` as defined on the impl at 6:6... --> $DIR/associated-const-impl-wrong-lifetime.rs:6:6 | LL | impl<'a> Foo for &'a () { diff --git a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr index 4309373f123f..5ea98dcd4a97 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-contravariant.transmute.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | bar(foo, x) | ^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 37:8... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 37:8... --> $DIR/project-fn-ret-contravariant.rs:37:8 | LL | fn baz<'a,'b>(x: &'a u32) -> &'static u32 { diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr index b8b1a979c363..627609c4a9c0 100644 --- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr +++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | bar(foo, x) | ^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 44:8... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 44:8... --> $DIR/project-fn-ret-invariant.rs:44:8 | LL | fn baz<'a,'b>(x: Type<'a>) -> Type<'static> { diff --git a/src/test/ui/async-await/issues/issue-63388-2.stderr b/src/test/ui/async-await/issues/issue-63388-2.stderr index 5099297fbeb1..efec160588fc 100644 --- a/src/test/ui/async-await/issues/issue-63388-2.stderr +++ b/src/test/ui/async-await/issues/issue-63388-2.stderr @@ -15,12 +15,12 @@ LL | foo: &dyn Foo, bar: &'a dyn Foo LL | foo | --- this return type evaluates to the `'static` lifetime... | -note: ...can't outlive the lifetime '_ as defined on the method body at 11:14 +note: ...can't outlive the lifetime `'_` as defined on the method body at 11:14 --> $DIR/issue-63388-2.rs:11:14 | LL | foo: &dyn Foo, bar: &'a dyn Foo | ^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 11:14 +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'_` as defined on the method body at 11:14 | LL | foo + '_ | diff --git a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr index 4c7c0d1a0dfa..52d43eae658a 100644 --- a/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr +++ b/src/test/ui/borrowck/regions-bound-missing-bound-in-impl.stderr @@ -24,12 +24,12 @@ LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d | = note: expected type `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'d>)` found type `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'d>)` -note: the lifetime 'c as defined on the method body at 27:24... +note: the lifetime `'c` as defined on the method body at 27:24... --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { | ^^ -note: ...does not necessarily outlive the lifetime 'c as defined on the method body at 27:24 +note: ...does not necessarily outlive the lifetime `'c` as defined on the method body at 27:24 --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24 | LL | fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { diff --git a/src/test/ui/c-variadic/variadic-ffi-4.stderr b/src/test/ui/c-variadic/variadic-ffi-4.stderr index 3d552f88ba66..05535659161b 100644 --- a/src/test/ui/c-variadic/variadic-ffi-4.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-4.stderr @@ -14,7 +14,7 @@ LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl< LL | | ap LL | | } | |_^ -note: ...does not necessarily outlive the lifetime 'f as defined on the function body at 7:37 +note: ...does not necessarily outlive the lifetime `'f` as defined on the function body at 7:37 --> $DIR/variadic-ffi-4.rs:7:37 | LL | pub unsafe extern "C" fn no_escape0<'f>(_: usize, ap: ...) -> VaListImpl<'f> { diff --git a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr index ac4666fe36de..8af7f882cc29 100644 --- a/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr +++ b/src/test/ui/closure-expected-type/expect-fn-supply-fn.stderr @@ -11,7 +11,7 @@ note: the anonymous lifetime #2 defined on the body at 14:48... | LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | ^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 11:36 +note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 11:36 --> $DIR/expect-fn-supply-fn.rs:11:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { @@ -25,7 +25,7 @@ LL | with_closure_expecting_fn_with_free_region(|x: fn(&'x u32), y| {}); | = note: expected type `fn(&u32)` found type `fn(&'x u32)` -note: the lifetime 'x as defined on the function body at 11:36... +note: the lifetime `'x` as defined on the function body at 11:36... --> $DIR/expect-fn-supply-fn.rs:11:36 | LL | fn expect_free_supply_free_from_fn<'x>(x: &'x u32) { diff --git a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr index e3b623d55248..9f74738315a0 100644 --- a/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr +++ b/src/test/ui/closures/closure-expected-type/expect-region-supply-region.stderr @@ -38,7 +38,7 @@ LL | | LL | | LL | | }); | |_____^ -note: ...does not necessarily outlive the lifetime 'x as defined on the function body at 32:30 +note: ...does not necessarily outlive the lifetime `'x` as defined on the function body at 32:30 --> $DIR/expect-region-supply-region.rs:32:30 | LL | fn expect_bound_supply_named<'x>() { @@ -52,7 +52,7 @@ LL | closure_expecting_bound(|x: &'x u32| { | = note: expected type `&u32` found type `&'x u32` -note: the lifetime 'x as defined on the function body at 32:30... +note: the lifetime `'x` as defined on the function body at 32:30... --> $DIR/expect-region-supply-region.rs:32:30 | LL | fn expect_bound_supply_named<'x>() { diff --git a/src/test/ui/error-codes/E0478.stderr b/src/test/ui/error-codes/E0478.stderr index 587125fdc336..1380840e0db2 100644 --- a/src/test/ui/error-codes/E0478.stderr +++ b/src/test/ui/error-codes/E0478.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | child: Box + 'SnowWhite>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime 'SnowWhite as defined on the struct at 3:22 +note: lifetime parameter instantiated with the lifetime `'SnowWhite` as defined on the struct at 3:22 --> $DIR/E0478.rs:3:22 | LL | struct Prince<'kiss, 'SnowWhite> { | ^^^^^^^^^^ -note: but lifetime parameter must outlive the lifetime 'kiss as defined on the struct at 3:15 +note: but lifetime parameter must outlive the lifetime `'kiss` as defined on the struct at 3:15 --> $DIR/E0478.rs:3:15 | LL | struct Prince<'kiss, 'SnowWhite> { diff --git a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr index 4bf2d573d4f9..cbd6422e5df7 100644 --- a/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr +++ b/src/test/ui/explicit/explicit-self-lifetime-mismatch.stderr @@ -6,12 +6,12 @@ LL | Foo<'b,'a> | = note: expected type `Foo<'a, 'b>` found type `Foo<'b, 'a>` -note: the lifetime 'b as defined on the impl at 6:9... +note: the lifetime `'b` as defined on the impl at 6:9... --> $DIR/explicit-self-lifetime-mismatch.rs:6:9 | LL | impl<'a,'b> Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 6:6 +note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 6:6 --> $DIR/explicit-self-lifetime-mismatch.rs:6:6 | LL | impl<'a,'b> Foo<'a,'b> { @@ -25,12 +25,12 @@ LL | Foo<'b,'a> | = note: expected type `Foo<'a, 'b>` found type `Foo<'b, 'a>` -note: the lifetime 'a as defined on the impl at 6:6... +note: the lifetime `'a` as defined on the impl at 6:6... --> $DIR/explicit-self-lifetime-mismatch.rs:6:6 | LL | impl<'a,'b> Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 6:9 +note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 6:9 --> $DIR/explicit-self-lifetime-mismatch.rs:6:9 | LL | impl<'a,'b> Foo<'a,'b> { diff --git a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr index 979f64fcd90a..76d97dd2f585 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr @@ -10,7 +10,7 @@ LL | | fn(Inv<'y>)) } | = note: expected type `std::option::Option)>` found type `std::option::Option)>` -note: the lifetime 'x as defined on the function body at 32:20... +note: the lifetime `'x` as defined on the function body at 32:20... --> $DIR/hr-subtype.rs:32:20 | LL | fn subtype<'x,'y:'x,'z:'y>() { @@ -19,7 +19,7 @@ LL | fn subtype<'x,'y:'x,'z:'y>() { LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), LL | | fn(Inv<'y>)) } | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 32:23 +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 32:23 --> $DIR/hr-subtype.rs:32:23 | LL | fn subtype<'x,'y:'x,'z:'y>() { @@ -41,7 +41,7 @@ LL | | fn(Inv<'y>)) } | = note: expected type `std::option::Option)>` found type `std::option::Option)>` -note: the lifetime 'x as defined on the function body at 38:22... +note: the lifetime `'x` as defined on the function body at 38:22... --> $DIR/hr-subtype.rs:38:22 | LL | fn supertype<'x,'y:'x,'z:'y>() { @@ -50,7 +50,7 @@ LL | fn supertype<'x,'y:'x,'z:'y>() { LL | / check! { free_inv_x_vs_free_inv_y: (fn(Inv<'x>), LL | | fn(Inv<'y>)) } | |__________________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 38:25 +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 --> $DIR/hr-subtype.rs:38:25 | LL | fn supertype<'x,'y:'x,'z:'y>() { diff --git a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr index 3b6aff521698..74f4212b2468 100644 --- a/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr +++ b/src/test/ui/hr-subtype/hr-subtype.free_x_vs_free_y.stderr @@ -10,7 +10,7 @@ LL | | fn(&'y u32)) } | = note: expected type `std::option::Option` found type `std::option::Option` -note: the lifetime 'x as defined on the function body at 38:22... +note: the lifetime `'x` as defined on the function body at 38:22... --> $DIR/hr-subtype.rs:38:22 | LL | fn supertype<'x,'y:'x,'z:'y>() { @@ -19,7 +19,7 @@ LL | fn supertype<'x,'y:'x,'z:'y>() { LL | / check! { free_x_vs_free_y: (fn(&'x u32), LL | | fn(&'y u32)) } | |__________________________________________- in this macro invocation -note: ...does not necessarily outlive the lifetime 'y as defined on the function body at 38:25 +note: ...does not necessarily outlive the lifetime `'y` as defined on the function body at 38:25 --> $DIR/hr-subtype.rs:38:25 | LL | fn supertype<'x,'y:'x,'z:'y>() { diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr index af120fa977ca..5e80c673258b 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | static_val(x); | ^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 19:26... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 19:26... --> $DIR/dyn-trait.rs:19:26 | LL | fn with_dyn_debug_static<'a>(x: Box) { diff --git a/src/test/ui/impl-trait/hidden-lifetimes.stderr b/src/test/ui/impl-trait/hidden-lifetimes.stderr index 650161753d1e..956ac1f1a116 100644 --- a/src/test/ui/impl-trait/hidden-lifetimes.stderr +++ b/src/test/ui/impl-trait/hidden-lifetimes.stderr @@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { | ^^^^^^^^^^^^^^ | -note: hidden type `&'a mut &'b T` captures the lifetime 'b as defined on the function body at 28:17 +note: hidden type `&'a mut &'b T` captures the lifetime `'b` as defined on the function body at 28:17 --> $DIR/hidden-lifetimes.rs:28:17 | LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a { @@ -16,7 +16,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { | ^^^^^^^^^^^^^^ | -note: hidden type `std::rc::Rc>` captures the lifetime 'b as defined on the function body at 45:24 +note: hidden type `std::rc::Rc>` captures the lifetime `'b` as defined on the function body at 45:24 --> $DIR/hidden-lifetimes.rs:45:24 | LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc>) -> impl Swap + 'a { 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 a6ea7837678e..2ffb94348616 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 @@ -24,12 +24,12 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | | | this return type evaluates to the `'static` lifetime... | -note: ...can't outlive the lifetime 'a as defined on the function body at 6:13 +note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13 --> $DIR/must_outlive_least_region_or_bound.rs:6:13 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x } | ^^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the function body at 6:13 +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13 | LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x } | ^^^^^^^^^^^^^^ @@ -42,12 +42,12 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | | | this return type evaluates to the `'static` lifetime... | -note: ...can't outlive the lifetime 'a as defined on the function body at 12:15 +note: ...can't outlive the lifetime `'a` as defined on the function body at 12:15 --> $DIR/must_outlive_least_region_or_bound.rs:12:15 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } | ^^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the function body at 12:15 +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15 | LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/region-escape-via-bound.stderr b/src/test/ui/impl-trait/region-escape-via-bound.stderr index 5c8e322f712d..894a65ff3899 100644 --- a/src/test/ui/impl-trait/region-escape-via-bound.stderr +++ b/src/test/ui/impl-trait/region-escape-via-bound.stderr @@ -4,7 +4,7 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea LL | fn foo(x: Cell<&'x u32>) -> impl Trait<'y> | ^^^^^^^^^^^^^^ | -note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime 'x as defined on the function body at 17:7 +note: hidden type `std::cell::Cell<&'x u32>` captures the lifetime `'x` as defined on the function body at 17:7 --> $DIR/region-escape-via-bound.rs:17:7 | LL | where 'x: 'y diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr index 0bc0180e78a4..1d6b5f56aa0c 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr @@ -30,12 +30,12 @@ LL | self.x.iter().map(|a| a.0) | | | ...but this borrow... | -note: ...can't outlive the lifetime 'a as defined on the method body at 10:20 +note: ...can't outlive the lifetime `'a` as defined on the method body at 10:20 --> $DIR/static-return-lifetime-infered.rs:10:20 | LL | fn iter_values<'a>(&'a self) -> impl Iterator { | ^^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the method body at 10:20 +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20 | LL | fn iter_values<'a>(&'a self) -> impl Iterator + 'a { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr index a80ebaf8dd29..b5287f32a504 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr @@ -11,7 +11,7 @@ LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { LL | | x LL | | } | |_____^ -note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 9:32... +note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32... --> $DIR/mismatched_trait_impl.rs:9:32 | LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr index 4dee83d6eefe..734ca0819e41 100644 --- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr +++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr @@ -11,7 +11,7 @@ LL | / fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { LL | | x LL | | } | |_____^ -note: ...but the lifetime must also be valid for the lifetime 'a as defined on the method body at 9:32... +note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the method body at 9:32... --> $DIR/mismatched_trait_impl.rs:9:32 | LL | fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 { diff --git a/src/test/ui/issues/issue-10291.stderr b/src/test/ui/issues/issue-10291.stderr index a836593e0da1..4fff4ee866c3 100644 --- a/src/test/ui/issues/issue-10291.stderr +++ b/src/test/ui/issues/issue-10291.stderr @@ -12,7 +12,7 @@ LL | drop:: FnMut(&'z isize) -> &'z isize>>(Box::new(|z| { LL | | x LL | | })); | |_____^ -note: ...but the borrowed content is only valid for the lifetime 'x as defined on the function body at 1:9 +note: ...but the borrowed content is only valid for the lifetime `'x` as defined on the function body at 1:9 --> $DIR/issue-10291.rs:1:9 | LL | fn test<'x>(x: &'x isize) { diff --git a/src/test/ui/issues/issue-16683.stderr b/src/test/ui/issues/issue-16683.stderr index a047893a168a..b663e213ed05 100644 --- a/src/test/ui/issues/issue-16683.stderr +++ b/src/test/ui/issues/issue-16683.stderr @@ -16,7 +16,7 @@ note: ...so that reference does not outlive borrowed content | LL | self.a(); | ^^^^ -note: but, the lifetime must be valid for the lifetime 'a as defined on the trait at 1:9... +note: but, the lifetime must be valid for the lifetime `'a` as defined on the trait at 1:9... --> $DIR/issue-16683.rs:1:9 | LL | trait T<'a> { diff --git a/src/test/ui/issues/issue-17740.stderr b/src/test/ui/issues/issue-17740.stderr index b8a0a0676319..d392ea3c1b86 100644 --- a/src/test/ui/issues/issue-17740.stderr +++ b/src/test/ui/issues/issue-17740.stderr @@ -17,7 +17,7 @@ LL | | LL | | LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 5:7 +note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 5:7 --> $DIR/issue-17740.rs:5:7 | LL | impl <'a> Foo<'a>{ @@ -31,7 +31,7 @@ LL | fn bar(self: &mut Foo) { | = note: expected type `Foo<'a>` found type `Foo<'_>` -note: the lifetime 'a as defined on the impl at 5:7... +note: the lifetime `'a` as defined on the impl at 5:7... --> $DIR/issue-17740.rs:5:7 | LL | impl <'a> Foo<'a>{ diff --git a/src/test/ui/issues/issue-17758.stderr b/src/test/ui/issues/issue-17758.stderr index 28a1be59840a..adcbb62e3d5b 100644 --- a/src/test/ui/issues/issue-17758.stderr +++ b/src/test/ui/issues/issue-17758.stderr @@ -17,7 +17,7 @@ note: ...so that reference does not outlive borrowed content | LL | self.foo(); | ^^^^ -note: but, the lifetime must be valid for the lifetime 'a as defined on the trait at 4:11... +note: but, the lifetime must be valid for the lifetime `'a` as defined on the trait at 4:11... --> $DIR/issue-17758.rs:4:11 | LL | trait Foo<'a> { diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr index 585bc9c14883..04be62dc661b 100644 --- a/src/test/ui/issues/issue-17905-2.stderr +++ b/src/test/ui/issues/issue-17905-2.stderr @@ -15,7 +15,7 @@ LL | | LL | | println!("{:?}", self); LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime '_ as defined on the impl at 5:5 +note: ...does not necessarily outlive the lifetime `'_` as defined on the impl at 5:5 --> $DIR/issue-17905-2.rs:5:5 | LL | &str, @@ -29,7 +29,7 @@ LL | fn say(self: &Pair<&str, isize>) { | = note: expected type `Pair<&str, _>` found type `Pair<&str, _>` -note: the lifetime '_ as defined on the impl at 5:5... +note: the lifetime `'_` as defined on the impl at 5:5... --> $DIR/issue-17905-2.rs:5:5 | LL | &str, diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index dd895985c143..13c9c09461ea 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -23,7 +23,7 @@ LL | | LL | | self.sub = t; LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 26:6 +note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 26:6 --> $DIR/issue-20831-debruijn.rs:26:6 | LL | impl<'a> Publisher<'a> for MyStruct<'a> { @@ -43,7 +43,7 @@ LL | | } | = note: expected type `'a` found type `'_` -note: the lifetime 'a as defined on the impl at 26:6... +note: the lifetime `'a` as defined on the impl at 26:6... --> $DIR/issue-20831-debruijn.rs:26:6 | LL | impl<'a> Publisher<'a> for MyStruct<'a> { @@ -83,7 +83,7 @@ LL | | LL | | self.sub = t; LL | | } | |_____^ -note: ...but the lifetime must also be valid for the lifetime 'a as defined on the impl at 26:6... +note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the impl at 26:6... --> $DIR/issue-20831-debruijn.rs:26:6 | LL | impl<'a> Publisher<'a> for MyStruct<'a> { diff --git a/src/test/ui/issues/issue-27942.stderr b/src/test/ui/issues/issue-27942.stderr index e03959598b8b..d290b176161b 100644 --- a/src/test/ui/issues/issue-27942.stderr +++ b/src/test/ui/issues/issue-27942.stderr @@ -11,7 +11,7 @@ note: the anonymous lifetime #1 defined on the method body at 5:5... | LL | fn select(&self) -> BufferViewHandle; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime 'a as defined on the trait at 3:18 +note: ...does not necessarily outlive the lifetime `'a` as defined on the trait at 3:18 --> $DIR/issue-27942.rs:3:18 | LL | pub trait Buffer<'a, R: Resources<'a>> { @@ -25,7 +25,7 @@ LL | fn select(&self) -> BufferViewHandle; | = note: expected type `Resources<'_>` found type `Resources<'a>` -note: the lifetime 'a as defined on the trait at 3:18... +note: the lifetime `'a` as defined on the trait at 3:18... --> $DIR/issue-27942.rs:3:18 | LL | pub trait Buffer<'a, R: Resources<'a>> { diff --git a/src/test/ui/issues/issue-28848.stderr b/src/test/ui/issues/issue-28848.stderr index 5f0f202c0b27..726844a31841 100644 --- a/src/test/ui/issues/issue-28848.stderr +++ b/src/test/ui/issues/issue-28848.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | Foo::<'a, 'b>::xmute(u) | ^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime 'b as defined on the function body at 9:16 +note: lifetime parameter instantiated with the lifetime `'b` as defined on the function body at 9:16 --> $DIR/issue-28848.rs:9:16 | LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { | ^^ -note: but lifetime parameter must outlive the lifetime 'a as defined on the function body at 9:12 +note: but lifetime parameter must outlive the lifetime `'a` as defined on the function body at 9:12 --> $DIR/issue-28848.rs:9:12 | LL | pub fn foo<'a, 'b>(u: &'b ()) -> &'a () { diff --git a/src/test/ui/issues/issue-37884.stderr b/src/test/ui/issues/issue-37884.stderr index 9a5f659da160..8e75d7be066a 100644 --- a/src/test/ui/issues/issue-37884.stderr +++ b/src/test/ui/issues/issue-37884.stderr @@ -21,7 +21,7 @@ LL | | { LL | | Some(&mut self.0) LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 3:6 +note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 3:6 --> $DIR/issue-37884.rs:3:6 | LL | impl<'a, T: 'a> Iterator for RepeatMut<'a, T> { diff --git a/src/test/ui/issues/issue-52213.stderr b/src/test/ui/issues/issue-52213.stderr index 8d74b8ecb881..b79a5ddf3e1b 100644 --- a/src/test/ui/issues/issue-52213.stderr +++ b/src/test/ui/issues/issue-52213.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | match (&t,) { | ^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 1:23... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 1:23... --> $DIR/issue-52213.rs:1:23 | LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { @@ -12,7 +12,7 @@ LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { = note: ...so that the types are compatible: expected (&&(T,),) found (&&'a (T,),) -note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 1:27... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 1:27... --> $DIR/issue-52213.rs:1:27 | LL | fn transmute_lifetime<'a, 'b, T>(t: &'a (T,)) -> &'b T { diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr index 7cf597d3a98f..7b910f5e3e5a 100644 --- a/src/test/ui/issues/issue-55796.stderr +++ b/src/test/ui/issues/issue-55796.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(self.out_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the trait at 5:17... --> $DIR/issue-55796.rs:5:17 | LL | pub trait Graph<'a> { @@ -25,7 +25,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(self.in_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 5:17... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the trait at 5:17... --> $DIR/issue-55796.rs:5:17 | LL | pub trait Graph<'a> { diff --git a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr index 35d63c172765..b4011990b68e 100644 --- a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr +++ b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.stderr @@ -6,7 +6,7 @@ LL | ref_obj(x) | = note: expected type `&std::boxed::Box<(dyn std::ops::Fn() + 'static)>` found type `&std::boxed::Box<(dyn std::ops::Fn() + 'a)>` -note: the lifetime 'a as defined on the function body at 32:10... +note: the lifetime `'a` as defined on the function body at 32:10... --> $DIR/lifetime-bound-will-change-warning.rs:32:10 | LL | fn test2<'a>(x: &'a Box) { @@ -21,7 +21,7 @@ LL | lib::ref_obj(x) | = note: expected type `&std::boxed::Box<(dyn std::ops::Fn() + 'static)>` found type `&std::boxed::Box<(dyn std::ops::Fn() + 'a)>` -note: the lifetime 'a as defined on the function body at 37:12... +note: the lifetime `'a` as defined on the function body at 37:12... --> $DIR/lifetime-bound-will-change-warning.rs:37:12 | LL | fn test2cc<'a>(x: &'a Box) { diff --git a/src/test/ui/lub-if.stderr b/src/test/ui/lub-if.stderr index 26f756c91833..0a4744013a62 100644 --- a/src/test/ui/lub-if.stderr +++ b/src/test/ui/lub-if.stderr @@ -5,7 +5,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 23:17 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 23:17 --> $DIR/lub-if.rs:23:17 | LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { @@ -18,7 +18,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 32:17 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 32:17 --> $DIR/lub-if.rs:32:17 | LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { diff --git a/src/test/ui/lub-match.stderr b/src/test/ui/lub-match.stderr index 0cb0a23c6f2d..168a38944692 100644 --- a/src/test/ui/lub-match.stderr +++ b/src/test/ui/lub-match.stderr @@ -5,7 +5,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 25:17 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 25:17 --> $DIR/lub-match.rs:25:17 | LL | pub fn opt_str2<'a>(maybestr: &'a Option) -> &'static str { @@ -18,7 +18,7 @@ LL | s | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 35:17 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 35:17 --> $DIR/lub-match.rs:35:17 | LL | pub fn opt_str3<'a>(maybestr: &'a Option) -> &'static str { diff --git a/src/test/ui/match/match-ref-mut-invariance.stderr b/src/test/ui/match/match-ref-mut-invariance.stderr index 30bbb8d7800f..0a020989d6f3 100644 --- a/src/test/ui/match/match-ref-mut-invariance.stderr +++ b/src/test/ui/match/match-ref-mut-invariance.stderr @@ -6,12 +6,12 @@ LL | match self.0 { ref mut x => x } | = note: expected type `&'a mut &'a i32` found type `&'a mut &'b i32` -note: the lifetime 'a as defined on the method body at 9:12... +note: the lifetime `'a` as defined on the method body at 9:12... --> $DIR/match-ref-mut-invariance.rs:9:12 | LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 8:6 +note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6 --> $DIR/match-ref-mut-invariance.rs:8:6 | LL | impl<'b> S<'b> { diff --git a/src/test/ui/match/match-ref-mut-let-invariance.stderr b/src/test/ui/match/match-ref-mut-let-invariance.stderr index 6ca222d9c2ff..1bea9bce11e4 100644 --- a/src/test/ui/match/match-ref-mut-let-invariance.stderr +++ b/src/test/ui/match/match-ref-mut-let-invariance.stderr @@ -6,12 +6,12 @@ LL | x | = note: expected type `&'a mut &'a i32` found type `&'a mut &'b i32` -note: the lifetime 'a as defined on the method body at 9:12... +note: the lifetime `'a` as defined on the method body at 9:12... --> $DIR/match-ref-mut-let-invariance.rs:9:12 | LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 8:6 +note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 8:6 --> $DIR/match-ref-mut-let-invariance.rs:8:6 | LL | impl<'b> S<'b> { diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr index b19e3a9dfb34..74c33df37a09 100644 --- a/src/test/ui/nll/issue-50716.stderr +++ b/src/test/ui/nll/issue-50716.stderr @@ -6,7 +6,7 @@ LL | let _x = *s; | = note: expected type `std::marker::Sized` found type `std::marker::Sized` -note: the lifetime 'a as defined on the function body at 9:8... +note: the lifetime `'a` as defined on the function body at 9:8... --> $DIR/issue-50716.rs:9:8 | LL | fn foo<'a, T: 'static>(s: Box<<&'a T as A>::X>) diff --git a/src/test/ui/nll/issue-52742.stderr b/src/test/ui/nll/issue-52742.stderr index 90a35177f4c3..0cdc2d944392 100644 --- a/src/test/ui/nll/issue-52742.stderr +++ b/src/test/ui/nll/issue-52742.stderr @@ -4,7 +4,7 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | self.y = b.z | ^^^ | -note: ...the reference is valid for the lifetime '_ as defined on the impl at 12:10... +note: ...the reference is valid for the lifetime `'_` as defined on the impl at 12:10... --> $DIR/issue-52742.rs:12:10 | LL | impl Foo<'_, '_> { diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr index e00e6f36f1af..714a63b670c6 100644 --- a/src/test/ui/nll/issue-55394.stderr +++ b/src/test/ui/nll/issue-55394.stderr @@ -16,7 +16,7 @@ note: ...so that reference does not outlive borrowed content | LL | Foo { bar } | ^^^ -note: but, the lifetime must be valid for the lifetime '_ as defined on the impl at 7:10... +note: but, the lifetime must be valid for the lifetime `'_` as defined on the impl at 7:10... --> $DIR/issue-55394.rs:7:10 | LL | impl Foo<'_> { diff --git a/src/test/ui/nll/issue-55401.stderr b/src/test/ui/nll/issue-55401.stderr index 4ec16ba055a4..2dc7236cbc27 100644 --- a/src/test/ui/nll/issue-55401.stderr +++ b/src/test/ui/nll/issue-55401.stderr @@ -5,7 +5,7 @@ LL | *y | ^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 1:47 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 1:47 --> $DIR/issue-55401.rs:1:47 | LL | fn static_to_a_to_static_through_ref_in_tuple<'a>(x: &'a u32) -> &'static u32 { diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr index 77a372d9cf55..3a152fbc6fce 100644 --- a/src/test/ui/nll/normalization-bounds-error.stderr +++ b/src/test/ui/nll/normalization-bounds-error.stderr @@ -4,12 +4,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` d LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'd as defined on the function body at 12:14... +note: first, the lifetime cannot outlive the lifetime `'d` as defined on the function body at 12:14... --> $DIR/normalization-bounds-error.rs:12:14 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} | ^^ -note: ...but the lifetime must also be valid for the lifetime 'a as defined on the function body at 12:18... +note: ...but the lifetime must also be valid for the lifetime `'a` as defined on the function body at 12:18... --> $DIR/normalization-bounds-error.rs:12:18 | LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {} diff --git a/src/test/ui/nll/trait-associated-constant.stderr b/src/test/ui/nll/trait-associated-constant.stderr index f39f668e2329..ecf9748af9ea 100644 --- a/src/test/ui/nll/trait-associated-constant.stderr +++ b/src/test/ui/nll/trait-associated-constant.stderr @@ -6,12 +6,12 @@ LL | const AC: Option<&'c str> = None; | = note: expected type `std::option::Option<&'b str>` found type `std::option::Option<&'c str>` -note: the lifetime 'c as defined on the impl at 20:18... +note: the lifetime `'c` as defined on the impl at 20:18... --> $DIR/trait-associated-constant.rs:20:18 | LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 20:14 +note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 20:14 --> $DIR/trait-associated-constant.rs:20:14 | LL | impl<'a: 'b, 'b, 'c> Anything<'a, 'b> for FailStruct { diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr index 746517417520..6986389af881 100644 --- a/src/test/ui/nll/type-alias-free-regions.stderr +++ b/src/test/ui/nll/type-alias-free-regions.stderr @@ -14,7 +14,7 @@ LL | | } = note: ...so that the expression is assignable: expected std::boxed::Box> found std::boxed::Box> -note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 15:6... +note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6... --> $DIR/type-alias-free-regions.rs:15:6 | LL | impl<'a> FromBox<'a> for C<'a> { @@ -39,7 +39,7 @@ LL | | } = note: ...so that the expression is assignable: expected std::boxed::Box<&isize> found std::boxed::Box<&isize> -note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 25:6... +note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 25:6... --> $DIR/type-alias-free-regions.rs:25:6 | LL | impl<'a> FromTuple<'a> for C<'a> { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr index f5657f9e4ead..4ebd99107886 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | >::C | ^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 7:8... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 7:8... --> $DIR/constant-in-expr-inherent-1.rs:7:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr index 0a8ad4221c98..4c7adf75d2fd 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-normalize.stderr @@ -5,7 +5,7 @@ LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 17:8 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 17:8 --> $DIR/constant-in-expr-normalize.rs:17:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr index d596aaf098f7..d01d022cba79 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-1.stderr @@ -5,7 +5,7 @@ LL | <() as Foo<'a>>::C | ^^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 9:8 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 9:8 --> $DIR/constant-in-expr-trait-item-1.rs:9:8 | LL | fn foo<'a>(_: &'a u32) -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr index 80ff9a043d4d..dd294280b903 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-2.stderr @@ -5,7 +5,7 @@ LL | >::C | ^^^^^^^^^^^^^^^^^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 9:8 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 9:8 --> $DIR/constant-in-expr-trait-item-2.rs:9:8 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr index f7db4038b8af..d61659e7e9af 100644 --- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr +++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | T::C | ^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:8... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:8... --> $DIR/constant-in-expr-trait-item-3.rs:9:8 | LL | fn foo<'a, T: Foo<'a>>() -> &'static u32 { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr index 217e8504aa3c..d66322c48ec9 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to LL | ss | ^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 54:10... --> $DIR/object-lifetime-default-elision.rs:54:10 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | ss | ^^ -note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 54:13... --> $DIR/object-lifetime-default-elision.rs:54:13 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { @@ -29,7 +29,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | ss | ^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 54:10... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 54:10... --> $DIR/object-lifetime-default-elision.rs:54:10 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { @@ -39,7 +39,7 @@ note: ...so that the declared lifetime parameter bounds are satisfied | LL | ss | ^^ -note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 54:13... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 54:13... --> $DIR/object-lifetime-default-elision.rs:54:13 | LL | fn load3<'a,'b>(ss: &'a dyn SomeTrait) -> &'b dyn SomeTrait { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr index 4f9cef12c5ef..99f0ce0602b1 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-box-error.stderr @@ -6,7 +6,7 @@ LL | ss.t = t; | = note: expected type `&'a std::boxed::Box<(dyn Test + 'static)>` found type `&'a std::boxed::Box<(dyn Test + 'a)>` -note: the lifetime 'a as defined on the function body at 14:6... +note: the lifetime `'a` as defined on the function body at 14:6... --> $DIR/object-lifetime-default-from-rptr-box-error.rs:14:6 | LL | fn c<'a>(t: &'a Box, mut ss: SomeStruct<'a>) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr index 3b7faee68aab..07d4d8c8ed40 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-from-rptr-struct-error.stderr @@ -6,7 +6,7 @@ LL | ss.t = t; | = note: expected type `&'a MyBox<(dyn Test + 'static)>` found type `&'a MyBox<(dyn Test + 'a)>` -note: the lifetime 'a as defined on the function body at 20:6... +note: the lifetime `'a` as defined on the function body at 20:6... --> $DIR/object-lifetime-default-from-rptr-struct-error.rs:20:6 | LL | fn c<'a>(t: &'a MyBox, mut ss: SomeStruct<'a>) { diff --git a/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr b/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr index 928b92019823..f825475b96b0 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-mybox.stderr @@ -18,7 +18,7 @@ LL | load0(ss) | = note: expected type `&MyBox<(dyn SomeTrait + 'static)>` found type `&MyBox<(dyn SomeTrait + 'a)>` -note: the lifetime 'a as defined on the function body at 30:10... +note: the lifetime `'a` as defined on the function body at 30:10... --> $DIR/object-lifetime-default-mybox.rs:30:10 | LL | fn load2<'a>(ss: &MyBox) -> MyBox { diff --git a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr index 751a4c1021eb..184cead21231 100644 --- a/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr +++ b/src/test/ui/regions/region-bounds-on-objects-and-type-parameters.stderr @@ -10,12 +10,12 @@ error[E0478]: lifetime bound not satisfied LL | z: Box+'b+'c>, | ^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime 'b as defined on the struct at 11:15 +note: lifetime parameter instantiated with the lifetime `'b` as defined on the struct at 11:15 --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:15 | LL | struct Foo<'a,'b,'c> { | ^^ -note: but lifetime parameter must outlive the lifetime 'a as defined on the struct at 11:12 +note: but lifetime parameter must outlive the lifetime `'a` as defined on the struct at 11:12 --> $DIR/region-bounds-on-objects-and-type-parameters.rs:11:12 | LL | struct Foo<'a,'b,'c> { diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.rs b/src/test/ui/regions/region-invariant-static-error-reporting.rs index df92ed51e9a9..911904813d0e 100644 --- a/src/test/ui/regions/region-invariant-static-error-reporting.rs +++ b/src/test/ui/regions/region-invariant-static-error-reporting.rs @@ -3,7 +3,7 @@ // over time, but this test used to exhibit some pretty bogus messages // that were not remotely helpful. -// error-pattern:the lifetime 'a +// error-pattern:the lifetime `'a` // error-pattern:the static lifetime struct Invariant<'a>(Option<&'a mut &'a mut ()>); diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.stderr b/src/test/ui/regions/region-invariant-static-error-reporting.stderr index 60e70ddcd970..8358a7988c80 100644 --- a/src/test/ui/regions/region-invariant-static-error-reporting.stderr +++ b/src/test/ui/regions/region-invariant-static-error-reporting.stderr @@ -13,7 +13,7 @@ LL | | }; | = note: expected type `Invariant<'a>` found type `Invariant<'static>` -note: the lifetime 'a as defined on the function body at 13:10... +note: the lifetime `'a` as defined on the function body at 13:10... --> $DIR/region-invariant-static-error-reporting.rs:13:10 | LL | fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { diff --git a/src/test/ui/regions/region-object-lifetime-2.stderr b/src/test/ui/regions/region-object-lifetime-2.stderr index cc8d150d04cc..74ea1b731e9a 100644 --- a/src/test/ui/regions/region-object-lifetime-2.stderr +++ b/src/test/ui/regions/region-object-lifetime-2.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin LL | x.borrowed() | ^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:42... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:42... --> $DIR/region-object-lifetime-2.rs:9:42 | LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | x.borrowed() | ^ -note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 9:45... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 9:45... --> $DIR/region-object-lifetime-2.rs:9:45 | LL | fn borrowed_receiver_different_lifetimes<'a,'b>(x: &'a dyn Foo) -> &'b () { diff --git a/src/test/ui/regions/region-object-lifetime-4.stderr b/src/test/ui/regions/region-object-lifetime-4.stderr index 23fd4d03628d..105321829058 100644 --- a/src/test/ui/regions/region-object-lifetime-4.stderr +++ b/src/test/ui/regions/region-object-lifetime-4.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for autoref due to conflictin LL | x.borrowed() | ^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 11:41... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 11:41... --> $DIR/region-object-lifetime-4.rs:11:41 | LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | x.borrowed() | ^ -note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 11:44... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 11:44... --> $DIR/region-object-lifetime-4.rs:11:44 | LL | fn borrowed_receiver_related_lifetimes2<'a,'b>(x: &'a (dyn Foo + 'b)) -> &'b () { diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr index 3ccb8866ca44..14934d6fa489 100644 --- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr +++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr @@ -29,7 +29,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | Box::new(v) | ^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 25:6... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 25:6... --> $DIR/region-object-lifetime-in-coercion.rs:25:6 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { @@ -37,7 +37,7 @@ LL | fn d<'a,'b>(v: &'a [u8]) -> Box { = note: ...so that the expression is assignable: expected &[u8] found &'a [u8] -note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 25:9... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 25:9... --> $DIR/region-object-lifetime-in-coercion.rs:25:9 | LL | fn d<'a,'b>(v: &'a [u8]) -> Box { diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.stderr index ac5e5e9aabc5..7a051b8ac835 100644 --- a/src/test/ui/regions/regions-addr-of-upvar-self.stderr +++ b/src/test/ui/regions/regions-addr-of-upvar-self.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | let p: &'static mut usize = &mut self.food; | ^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 9:18... +note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 9:18... --> $DIR/regions-addr-of-upvar-self.rs:9:18 | LL | let _f = || { diff --git a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr index 61be0778c99c..c0401780b8f5 100644 --- a/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr +++ b/src/test/ui/regions/regions-assoc-type-in-supertrait-outlives-container.migrate.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | let _: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 33:15 +note: the pointer is valid for the lifetime `'a` as defined on the function body at 33:15 --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 33:18 +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 33:18 --> $DIR/regions-assoc-type-in-supertrait-outlives-container.rs:33:18 | LL | fn with_assoc<'a,'b>() { diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr index d01e99110392..a636c9ef22c8 100644 --- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | impl<'a> Foo<'static> for &'a i32 { | ^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 14:6... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 14:6... --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:6 | LL | impl<'a> Foo<'static> for &'a i32 { @@ -25,7 +25,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | impl<'a,'b> Foo<'b> for &'a i64 { | ^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 19:6... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 19:6... --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:6 | LL | impl<'a,'b> Foo<'b> for &'a i64 { @@ -33,7 +33,7 @@ LL | impl<'a,'b> Foo<'b> for &'a i64 { = note: ...so that the types are compatible: expected Foo<'b> found Foo<'_> -note: but, the lifetime must be valid for the lifetime 'b as defined on the impl at 19:9... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9... --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9 | LL | impl<'a,'b> Foo<'b> for &'a i64 { diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr index 33a4ea01ce2e..81256e3b46cb 100644 --- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr +++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | impl<'a> Foo for &'a i32 { | ^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 9:6... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 9:6... --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:6 | LL | impl<'a> Foo for &'a i32 { diff --git a/src/test/ui/regions/regions-bounds.stderr b/src/test/ui/regions/regions-bounds.stderr index 27eb8891c6c0..a15710b86c06 100644 --- a/src/test/ui/regions/regions-bounds.stderr +++ b/src/test/ui/regions/regions-bounds.stderr @@ -6,12 +6,12 @@ LL | return e; | = note: expected type `TupleStruct<'b>` found type `TupleStruct<'a>` -note: the lifetime 'a as defined on the function body at 8:10... +note: the lifetime `'a` as defined on the function body at 8:10... --> $DIR/regions-bounds.rs:8:10 | LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 8:13 +note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 8:13 --> $DIR/regions-bounds.rs:8:13 | LL | fn a_fn1<'a,'b>(e: TupleStruct<'a>) -> TupleStruct<'b> { @@ -25,12 +25,12 @@ LL | return e; | = note: expected type `Struct<'b>` found type `Struct<'a>` -note: the lifetime 'a as defined on the function body at 12:10... +note: the lifetime `'a` as defined on the function body at 12:10... --> $DIR/regions-bounds.rs:12:10 | LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 12:13 +note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 12:13 --> $DIR/regions-bounds.rs:12:13 | LL | fn a_fn3<'a,'b>(e: Struct<'a>) -> Struct<'b> { diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr index 7af608d2c801..8e473dad6934 100644 --- a/src/test/ui/regions/regions-close-object-into-object-2.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | box B(&*v) as Box | ^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6... --> $DIR/regions-close-object-into-object-2.rs:9:6 | LL | fn g<'a, T: 'static>(v: Box + 'a>) -> Box { diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr index ef47db18d392..c80d13e15b14 100644 --- a/src/test/ui/regions/regions-close-object-into-object-4.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | box B(&*v) as Box | ^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 9:6... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6... --> $DIR/regions-close-object-into-object-4.rs:9:6 | LL | fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr index 6f7466a8b0ed..ef21316ea83a 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime due to conflicting requiremen LL | box v as Box | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 18:20... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 18:20... --> $DIR/regions-close-over-type-parameter-multiple.rs:18:20 | LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { @@ -14,7 +14,7 @@ note: ...so that the declared lifetime parameter bounds are satisfied | LL | box v as Box | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: but, the lifetime must be valid for the lifetime 'c as defined on the function body at 18:26... +note: but, the lifetime must be valid for the lifetime `'c` as defined on the function body at 18:26... --> $DIR/regions-close-over-type-parameter-multiple.rs:18:26 | LL | fn make_object_bad<'a,'b,'c,A:SomeTrait+'a+'b>(v: A) -> Box { diff --git a/src/test/ui/regions/regions-creating-enums4.stderr b/src/test/ui/regions/regions-creating-enums4.stderr index 4d00783d180b..12b89787d5f1 100644 --- a/src/test/ui/regions/regions-creating-enums4.stderr +++ b/src/test/ui/regions/regions-creating-enums4.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` d LL | Ast::Add(x, y) | ^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 6:16... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 6:16... --> $DIR/regions-creating-enums4.rs:6:16 | LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { @@ -12,7 +12,7 @@ LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { = note: ...so that the expression is assignable: expected &Ast<'_> found &Ast<'a> -note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 6:19... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 6:19... --> $DIR/regions-creating-enums4.rs:6:19 | LL | fn mk_add_bad2<'a,'b>(x: &'a Ast<'a>, y: &'a Ast<'a>, z: &Ast) -> Ast<'b> { diff --git a/src/test/ui/regions/regions-early-bound-error-method.stderr b/src/test/ui/regions/regions-early-bound-error-method.stderr index 7b9f2c9503b2..9095451da052 100644 --- a/src/test/ui/regions/regions-early-bound-error-method.stderr +++ b/src/test/ui/regions/regions-early-bound-error-method.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | g2.get() | ^^^^^^^^ | -note: ...the reference is valid for the lifetime 'a as defined on the impl at 18:6... +note: ...the reference is valid for the lifetime `'a` as defined on the impl at 18:6... --> $DIR/regions-early-bound-error-method.rs:18:6 | LL | impl<'a> Box<'a> { | ^^ -note: ...but the borrowed content is only valid for the lifetime 'b as defined on the method body at 19:11 +note: ...but the borrowed content is only valid for the lifetime `'b` as defined on the method body at 19:11 --> $DIR/regions-early-bound-error-method.rs:19:11 | LL | fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize { diff --git a/src/test/ui/regions/regions-early-bound-error.stderr b/src/test/ui/regions/regions-early-bound-error.stderr index a68355b78f54..162d573362d4 100644 --- a/src/test/ui/regions/regions-early-bound-error.stderr +++ b/src/test/ui/regions/regions-early-bound-error.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | g1.get() | ^^^^^^^^ | -note: ...the reference is valid for the lifetime 'b as defined on the function body at 18:11... +note: ...the reference is valid for the lifetime `'b` as defined on the function body at 18:11... --> $DIR/regions-early-bound-error.rs:18:11 | LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize { | ^^ -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 18:8 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 18:8 --> $DIR/regions-early-bound-error.rs:18:8 | LL | fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize { diff --git a/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr index 3b8f09f1ad80..ad555efadf7e 100644 --- a/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-callee-4.stderr @@ -8,12 +8,12 @@ LL | | let z: Option<&'a &'b usize> = None; LL | | } | |_^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 5:14 +note: the pointer is valid for the lifetime `'a` as defined on the function body at 5:14 --> $DIR/regions-free-region-ordering-callee-4.rs:5:14 | LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 5:18 +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 5:18 --> $DIR/regions-free-region-ordering-callee-4.rs:5:18 | LL | fn ordering4<'a, 'b, F>(a: &'a usize, b: &'b usize, x: F) where F: FnOnce(&'a &'b usize) { diff --git a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr index 676e96a038b4..10644174b9bc 100644 --- a/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-incorrect.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | None => &self.val | ^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the method body at 14:12... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the method body at 14:12... --> $DIR/regions-free-region-ordering-incorrect.rs:14:12 | LL | fn get<'a>(&'a self) -> &'b T { @@ -14,7 +14,7 @@ note: ...so that reference does not outlive borrowed content | LL | None => &self.val | ^^^^^^^^^ -note: but, the lifetime must be valid for the lifetime 'b as defined on the impl at 13:6... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 13:6... --> $DIR/regions-free-region-ordering-incorrect.rs:13:6 | LL | impl<'b, T> Node<'b, T> { diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr index b3390bcc4d50..c4ca7e970749 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr @@ -7,12 +7,12 @@ LL | | { LL | | } | |_^ | -note: the pointer is valid for the lifetime 'x as defined on the function body at 21:11 +note: the pointer is valid for the lifetime `'x` as defined on the function body at 21:11 --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:11 | LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) | ^^ -note: but the referenced data is only valid for the lifetime 'y as defined on the function body at 21:15 +note: but the referenced data is only valid for the lifetime `'y` as defined on the function body at 21:15 --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:15 | LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< >::Foo >) diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr index d31ed3ede36f..f4e223bbf6f9 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-decl.stderr @@ -6,7 +6,7 @@ LL | b_isize | = note: expected type `Invariant<'static>` found type `Invariant<'r>` -note: the lifetime 'r as defined on the function body at 11:23... +note: the lifetime `'r` as defined on the function body at 11:23... --> $DIR/regions-infer-invariance-due-to-decl.rs:11:23 | LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr index f8bdd014db7c..6322244fcf93 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-3.stderr @@ -6,7 +6,7 @@ LL | b_isize | = note: expected type `Invariant<'static>` found type `Invariant<'r>` -note: the lifetime 'r as defined on the function body at 9:23... +note: the lifetime `'r` as defined on the function body at 9:23... --> $DIR/regions-infer-invariance-due-to-mutability-3.rs:9:23 | LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { diff --git a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr index 1de6f22f08e5..7baae69945f9 100644 --- a/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr +++ b/src/test/ui/regions/regions-infer-invariance-due-to-mutability-4.stderr @@ -6,7 +6,7 @@ LL | b_isize | = note: expected type `Invariant<'static>` found type `Invariant<'r>` -note: the lifetime 'r as defined on the function body at 9:23... +note: the lifetime `'r` as defined on the function body at 9:23... --> $DIR/regions-infer-invariance-due-to-mutability-4.rs:9:23 | LL | fn to_longer_lifetime<'r>(b_isize: Invariant<'r>) -> Invariant<'static> { diff --git a/src/test/ui/regions/regions-infer-not-param.stderr b/src/test/ui/regions/regions-infer-not-param.stderr index f43ab8291218..6365769430f3 100644 --- a/src/test/ui/regions/regions-infer-not-param.stderr +++ b/src/test/ui/regions/regions-infer-not-param.stderr @@ -6,12 +6,12 @@ LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } | = note: expected type `Direct<'b>` found type `Direct<'a>` -note: the lifetime 'a as defined on the function body at 15:16... +note: the lifetime `'a` as defined on the function body at 15:16... --> $DIR/regions-infer-not-param.rs:15:16 | LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 15:19 +note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 15:19 --> $DIR/regions-infer-not-param.rs:15:19 | LL | fn take_direct<'a,'b>(p: Direct<'a>) -> Direct<'b> { p } @@ -25,12 +25,12 @@ LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | = note: expected type `Indirect2<'b>` found type `Indirect2<'a>` -note: the lifetime 'a as defined on the function body at 19:19... +note: the lifetime `'a` as defined on the function body at 19:19... --> $DIR/regions-infer-not-param.rs:19:19 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the function body at 19:22 +note: ...does not necessarily outlive the lifetime `'b` as defined on the function body at 19:22 --> $DIR/regions-infer-not-param.rs:19:22 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } @@ -44,12 +44,12 @@ LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | = note: expected type `Indirect2<'b>` found type `Indirect2<'a>` -note: the lifetime 'b as defined on the function body at 19:22... +note: the lifetime `'b` as defined on the function body at 19:22... --> $DIR/regions-infer-not-param.rs:19:22 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } | ^^ -note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 19:19 +note: ...does not necessarily outlive the lifetime `'a` as defined on the function body at 19:19 --> $DIR/regions-infer-not-param.rs:19:19 | LL | fn take_indirect2<'a,'b>(p: Indirect2<'a>) -> Indirect2<'b> { p } diff --git a/src/test/ui/regions/regions-infer-paramd-indirect.stderr b/src/test/ui/regions/regions-infer-paramd-indirect.stderr index 1b999ed059c4..b1fd337b8d04 100644 --- a/src/test/ui/regions/regions-infer-paramd-indirect.stderr +++ b/src/test/ui/regions/regions-infer-paramd-indirect.stderr @@ -17,7 +17,7 @@ LL | | LL | | LL | | } | |_____^ -note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 16:6 +note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 16:6 --> $DIR/regions-infer-paramd-indirect.rs:16:6 | LL | impl<'a> SetF<'a> for C<'a> { diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr index bc3c06d7ff3b..f4eb5c8644f0 100644 --- a/src/test/ui/regions/regions-nested-fns.stderr +++ b/src/test/ui/regions/regions-nested-fns.stderr @@ -49,7 +49,7 @@ LL | | if false { return ay; } LL | | return z; LL | | })); | |_____^ -note: ...but the borrowed content is only valid for the lifetime 'x as defined on the function body at 3:11 +note: ...but the borrowed content is only valid for the lifetime `'x` as defined on the function body at 3:11 --> $DIR/regions-nested-fns.rs:3:11 | LL | fn nested<'x>(x: &'x isize) { diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr index c44edf1f03bc..d29fd80943f7 100644 --- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr +++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr @@ -7,12 +7,12 @@ LL | | { LL | | } | |_^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 22:8... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:8... --> $DIR/regions-normalize-in-where-clause-list.rs:22:8 | LL | fn bar<'a, 'b>() | ^^ -note: ...but the lifetime must also be valid for the lifetime 'b as defined on the function body at 22:12... +note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the function body at 22:12... --> $DIR/regions-normalize-in-where-clause-list.rs:22:12 | LL | fn bar<'a, 'b>() diff --git a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr index ed5800940ee3..0992d9bf295c 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-hrtb.migrate.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithHrAssoc>`, reference has a longer lif LL | let _: &'a WithHrAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 27:15 +note: the pointer is valid for the lifetime `'a` as defined on the function body at 27:15 --> $DIR/regions-outlives-projection-container-hrtb.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 27:18 +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 27:18 --> $DIR/regions-outlives-projection-container-hrtb.rs:27:18 | LL | fn with_assoc<'a,'b>() { @@ -21,12 +21,12 @@ error[E0491]: in type `&'a WithHrAssocSub>`, reference has a longer LL | let _: &'a WithHrAssocSub> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 46:19 +note: the pointer is valid for the lifetime `'a` as defined on the function body at 46:19 --> $DIR/regions-outlives-projection-container-hrtb.rs:46:19 | LL | fn with_assoc_sub<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 46:22 +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 46:22 --> $DIR/regions-outlives-projection-container-hrtb.rs:46:22 | LL | fn with_assoc_sub<'a,'b>() { diff --git a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr index 152e6c5600c4..49e28a14d8a4 100644 --- a/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container-wc.migrate.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | let _: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 27:15 +note: the pointer is valid for the lifetime `'a` as defined on the function body at 27:15 --> $DIR/regions-outlives-projection-container-wc.rs:27:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 27:18 +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 27:18 --> $DIR/regions-outlives-projection-container-wc.rs:27:18 | LL | fn with_assoc<'a,'b>() { diff --git a/src/test/ui/regions/regions-outlives-projection-container.stderr b/src/test/ui/regions/regions-outlives-projection-container.stderr index 3c1a98a3c018..dba15fb0576e 100644 --- a/src/test/ui/regions/regions-outlives-projection-container.stderr +++ b/src/test/ui/regions/regions-outlives-projection-container.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | let _x: &'a WithAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 28:15 +note: the pointer is valid for the lifetime `'a` as defined on the function body at 28:15 --> $DIR/regions-outlives-projection-container.rs:28:15 | LL | fn with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 28:18 +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 28:18 --> $DIR/regions-outlives-projection-container.rs:28:18 | LL | fn with_assoc<'a,'b>() { @@ -21,12 +21,12 @@ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer li LL | let _x: &'a WithoutAssoc> = loop { }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 50:18 +note: the pointer is valid for the lifetime `'a` as defined on the function body at 50:18 --> $DIR/regions-outlives-projection-container.rs:50:18 | LL | fn without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 50:21 +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 50:21 --> $DIR/regions-outlives-projection-container.rs:50:21 | LL | fn without_assoc<'a,'b>() { @@ -38,12 +38,12 @@ error[E0491]: in type `&'a WithAssoc>`, reference has a longer lifet LL | call::<&'a WithAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 58:20 +note: the pointer is valid for the lifetime `'a` as defined on the function body at 58:20 --> $DIR/regions-outlives-projection-container.rs:58:20 | LL | fn call_with_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 58:23 +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 58:23 --> $DIR/regions-outlives-projection-container.rs:58:23 | LL | fn call_with_assoc<'a,'b>() { @@ -55,12 +55,12 @@ error[E0491]: in type `&'a WithoutAssoc>`, reference has a longer li LL | call::<&'a WithoutAssoc>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the function body at 67:23 +note: the pointer is valid for the lifetime `'a` as defined on the function body at 67:23 --> $DIR/regions-outlives-projection-container.rs:67:23 | LL | fn call_without_assoc<'a,'b>() { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the function body at 67:26 +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 67:26 --> $DIR/regions-outlives-projection-container.rs:67:26 | LL | fn call_without_assoc<'a,'b>() { diff --git a/src/test/ui/regions/regions-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr index 72e47cea094c..49076673ad39 100644 --- a/src/test/ui/regions/regions-ret-borrowed-1.stderr +++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr @@ -12,7 +12,7 @@ LL | with(|o| o) = note: ...so that the expression is assignable: expected &isize found &isize -note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 9:14... +note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 9:14... --> $DIR/regions-ret-borrowed-1.rs:9:14 | LL | fn return_it<'a>() -> &'a isize { diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr index ce0c429ccb24..eb1ade27acea 100644 --- a/src/test/ui/regions/regions-ret-borrowed.stderr +++ b/src/test/ui/regions/regions-ret-borrowed.stderr @@ -12,7 +12,7 @@ LL | with(|o| o) = note: ...so that the expression is assignable: expected &isize found &isize -note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 12:14... +note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 12:14... --> $DIR/regions-ret-borrowed.rs:12:14 | LL | fn return_it<'a>() -> &'a isize { diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr index be441bc48082..946465bcb5f2 100644 --- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr +++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | let mut f = || &mut x; | ^^^^^^ | -note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 7:21... +note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 7:21... --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:21 | LL | let mut f = || &mut x; diff --git a/src/test/ui/regions/regions-static-bound.migrate.stderr b/src/test/ui/regions/regions-static-bound.migrate.stderr index 21ead8b768f4..6e631d40d450 100644 --- a/src/test/ui/regions/regions-static-bound.migrate.stderr +++ b/src/test/ui/regions/regions-static-bound.migrate.stderr @@ -5,7 +5,7 @@ LL | t | ^ | = note: ...the reference is valid for the static lifetime... -note: ...but the borrowed content is only valid for the lifetime 'a as defined on the function body at 8:24 +note: ...but the borrowed content is only valid for the lifetime `'a` as defined on the function body at 8:24 --> $DIR/regions-static-bound.rs:8:24 | LL | fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { diff --git a/src/test/ui/regions/regions-trait-1.stderr b/src/test/ui/regions/regions-trait-1.stderr index 421f826ccc54..f835c005ff96 100644 --- a/src/test/ui/regions/regions-trait-1.stderr +++ b/src/test/ui/regions/regions-trait-1.stderr @@ -6,7 +6,7 @@ LL | fn get_ctxt(&self) -> &'a Ctxt { | = note: expected type `fn(&HasCtxt<'a>) -> &Ctxt` found type `fn(&HasCtxt<'a>) -> &'a Ctxt` -note: the lifetime 'a as defined on the impl at 12:6... +note: the lifetime `'a` as defined on the impl at 12:6... --> $DIR/regions-trait-1.rs:12:6 | LL | impl<'a> GetCtxt for HasCtxt<'a> { diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr index d88be05cb87e..b7c7f93149dc 100644 --- a/src/test/ui/regions/regions-trait-object-subtyping.stderr +++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | x | ^ | -note: lifetime parameter instantiated with the lifetime 'a as defined on the function body at 13:9 +note: lifetime parameter instantiated with the lifetime `'a` as defined on the function body at 13:9 --> $DIR/regions-trait-object-subtyping.rs:13:9 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { | ^^ -note: but lifetime parameter must outlive the lifetime 'b as defined on the function body at 13:12 +note: but lifetime parameter must outlive the lifetime `'b` as defined on the function body at 13:12 --> $DIR/regions-trait-object-subtyping.rs:13:12 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { @@ -21,7 +21,7 @@ error[E0495]: cannot infer an appropriate lifetime for automatic coercion due to LL | x | ^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the function body at 13:9... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 13:9... --> $DIR/regions-trait-object-subtyping.rs:13:9 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { @@ -31,7 +31,7 @@ note: ...so that reference does not outlive borrowed content | LL | x | ^ -note: but, the lifetime must be valid for the lifetime 'b as defined on the function body at 13:12... +note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 13:12... --> $DIR/regions-trait-object-subtyping.rs:13:12 | LL | fn foo3<'a,'b>(x: &'a mut dyn Dummy) -> &'b mut dyn Dummy { @@ -48,12 +48,12 @@ LL | x | = note: expected type `Wrapper<&'b mut (dyn Dummy + 'b)>` found type `Wrapper<&'a mut (dyn Dummy + 'a)>` -note: the lifetime 'b as defined on the function body at 20:15... +note: the lifetime `'b` as defined on the function body at 20:15... --> $DIR/regions-trait-object-subtyping.rs:20:15 | LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> { | ^^ -note: ...does not necessarily outlive the lifetime 'a as defined on the function body at 20:9 +note: ...does not necessarily outlive the lifetime `'a` as defined on the function body at 20:9 --> $DIR/regions-trait-object-subtyping.rs:20:9 | LL | fn foo4<'a:'b,'b>(x: Wrapper<&'a mut dyn Dummy>) -> Wrapper<&'b mut dyn Dummy> { diff --git a/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr index 90b37ce935a6..aae519c5df2e 100644 --- a/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr +++ b/src/test/ui/regions/regions-variance-invariant-use-covariant.stderr @@ -6,7 +6,7 @@ LL | let _: Invariant<'static> = c; | = note: expected type `Invariant<'static>` found type `Invariant<'b>` -note: the lifetime 'b as defined on the function body at 11:9... +note: the lifetime `'b` as defined on the function body at 11:9... --> $DIR/regions-variance-invariant-use-covariant.rs:11:9 | LL | fn use_<'b>(c: Invariant<'b>) { diff --git a/src/test/ui/regions/regions-wf-trait-object.stderr b/src/test/ui/regions/regions-wf-trait-object.stderr index 4e12478c36da..9f3950860411 100644 --- a/src/test/ui/regions/regions-wf-trait-object.stderr +++ b/src/test/ui/regions/regions-wf-trait-object.stderr @@ -4,12 +4,12 @@ error[E0478]: lifetime bound not satisfied LL | x: Box+'b> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime 'b as defined on the struct at 6:15 +note: lifetime parameter instantiated with the lifetime `'b` as defined on the struct at 6:15 --> $DIR/regions-wf-trait-object.rs:6:15 | LL | struct Foo<'a,'b> { | ^^ -note: but lifetime parameter must outlive the lifetime 'a as defined on the struct at 6:12 +note: but lifetime parameter must outlive the lifetime `'a` as defined on the struct at 6:12 --> $DIR/regions-wf-trait-object.rs:6:12 | LL | struct Foo<'a,'b> { diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr index 16d27c9d961e..609a40163a30 100644 --- a/src/test/ui/reject-specialized-drops-8142.stderr +++ b/src/test/ui/reject-specialized-drops-8142.stderr @@ -34,7 +34,7 @@ LL | impl Drop for N<'static> { fn drop(&mut self) { } } | = note: expected type `N<'n>` found type `N<'static>` -note: the lifetime 'n as defined on the struct at 8:10... +note: the lifetime `'n` as defined on the struct at 8:10... --> $DIR/reject-specialized-drops-8142.rs:8:10 | LL | struct N<'n> { x: &'n i8 } @@ -95,12 +95,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'lw` LL | impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'l1 as defined on the struct at 17:10... +note: first, the lifetime cannot outlive the lifetime `'l1` as defined on the struct at 17:10... --> $DIR/reject-specialized-drops-8142.rs:17:10 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } | ^^^ -note: ...but the lifetime must also be valid for the lifetime 'l2 as defined on the struct at 17:15... +note: ...but the lifetime must also be valid for the lifetime `'l2` as defined on the struct at 17:15... --> $DIR/reject-specialized-drops-8142.rs:17:15 | LL | struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 } diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr index be8b5c6446ca..6efc1176d05b 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region-rev.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a rev_variant_struct_region::Foo<'b>`, reference has a LL | type Out = &'a Foo<'b>; | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10 +note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 --> $DIR/regions-outlives-nominal-type-region-rev.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr index 9a3ba2d65cad..06e5f24dec97 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-region.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a variant_struct_region::Foo<'b>`, reference has a long LL | type Out = &'a Foo<'b>; | ^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10 +note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 --> $DIR/regions-outlives-nominal-type-region.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 --> $DIR/regions-outlives-nominal-type-region.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr index 5389beea3a70..d02f7b796218 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type-rev.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a variant_struct_type::Foo<&'b i32>`, reference has a l LL | type Out = &'a Foo<&'b i32>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10 +note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 --> $DIR/regions-outlives-nominal-type-type-rev.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr index 2f3ef48a0544..40c70f53245c 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-outlives-nominal-type-type.stderr @@ -4,12 +4,12 @@ error[E0491]: in type `&'a variant_struct_type::Foo<&'b i32>`, reference has a l LL | type Out = &'a Foo<&'b i32>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the impl at 16:10 +note: the pointer is valid for the lifetime `'a` as defined on the impl at 16:10 --> $DIR/regions-outlives-nominal-type-type.rs:16:10 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 16:14 +note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 16:14 --> $DIR/regions-outlives-nominal-type-type.rs:16:14 | LL | impl<'a, 'b> Trait<'a, 'b> for usize { 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 5a11c5fb95fe..825c1015c51d 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 @@ -32,12 +32,12 @@ error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data LL | type Out = &'a &'b T; | ^^^^^^^^^^^^^^^^^^^^^ | -note: the pointer is valid for the lifetime 'a as defined on the impl at 24:6 +note: the pointer is valid for the lifetime `'a` as defined on the impl at 24:6 --> $DIR/regions-struct-not-wf.rs:24:6 | LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 { | ^^ -note: but the referenced data is only valid for the lifetime 'b as defined on the impl at 24:10 +note: but the referenced data is only valid for the lifetime `'b` as defined on the impl at 24:10 --> $DIR/regions-struct-not-wf.rs:24:10 | LL | impl<'a, 'b, T> Trait1<'a, 'b, T> for u32 { diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr index 2fb152475a1e..bce1900ca602 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr @@ -6,12 +6,12 @@ LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | | | ...but this borrow... | -note: ...can't outlive the lifetime '_ as defined on the method body at 8:26 +note: ...can't outlive the lifetime `'_` as defined on the method body at 8:26 --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:26 | LL | async fn f(self: Pin<&Self>) -> impl Clone { self } | ^ -help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime '_ as defined on the method body at 8:26 +help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime `'_` as defined on the method body at 8:26 | LL | async fn f(self: Pin<&Self>) -> impl Clone + '_ { self } | ^^^^^^^^^^^^^^^ diff --git a/src/test/ui/static/static-lifetime.stderr b/src/test/ui/static/static-lifetime.stderr index 8516ac07b6cf..bda325dc0116 100644 --- a/src/test/ui/static/static-lifetime.stderr +++ b/src/test/ui/static/static-lifetime.stderr @@ -4,7 +4,7 @@ error[E0478]: lifetime bound not satisfied LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} | ^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime 'a as defined on the impl at 3:6 +note: lifetime parameter instantiated with the lifetime `'a` as defined on the impl at 3:6 --> $DIR/static-lifetime.rs:3:6 | LL | impl<'a, A: Clone> Arbitrary for ::std::borrow::Cow<'a, A> {} diff --git a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr index 4c63d6097758..88c9c473eb0c 100644 --- a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr +++ b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr @@ -4,12 +4,12 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { | ^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 24:6... +note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 24:6... --> $DIR/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:6 | LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { | ^^ -note: ...but the lifetime must also be valid for the lifetime 'b as defined on the impl at 24:9... +note: ...but the lifetime must also be valid for the lifetime `'b` as defined on the impl at 24:9... --> $DIR/trait-impl-of-supertrait-has-wrong-lifetime-parameters.rs:24:9 | LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> { diff --git a/src/test/ui/traits/trait-matching-lifetimes.stderr b/src/test/ui/traits/trait-matching-lifetimes.stderr index 80c577674d16..e1ccde3c9d14 100644 --- a/src/test/ui/traits/trait-matching-lifetimes.stderr +++ b/src/test/ui/traits/trait-matching-lifetimes.stderr @@ -6,12 +6,12 @@ LL | fn foo(x: Foo<'b,'a>) { | = note: expected type `fn(Foo<'a, 'b>)` found type `fn(Foo<'b, 'a>)` -note: the lifetime 'b as defined on the impl at 13:9... +note: the lifetime `'b` as defined on the impl at 13:9... --> $DIR/trait-matching-lifetimes.rs:13:9 | LL | impl<'a,'b> Tr for Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 13:6 +note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 13:6 --> $DIR/trait-matching-lifetimes.rs:13:6 | LL | impl<'a,'b> Tr for Foo<'a,'b> { @@ -25,12 +25,12 @@ LL | fn foo(x: Foo<'b,'a>) { | = note: expected type `fn(Foo<'a, 'b>)` found type `fn(Foo<'b, 'a>)` -note: the lifetime 'a as defined on the impl at 13:6... +note: the lifetime `'a` as defined on the impl at 13:6... --> $DIR/trait-matching-lifetimes.rs:13:6 | LL | impl<'a,'b> Tr for Foo<'a,'b> { | ^^ -note: ...does not necessarily outlive the lifetime 'b as defined on the impl at 13:9 +note: ...does not necessarily outlive the lifetime `'b` as defined on the impl at 13:9 --> $DIR/trait-matching-lifetimes.rs:13:9 | LL | impl<'a,'b> Tr for Foo<'a,'b> { diff --git a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr index b2fe1b281fc9..de3a997a19ed 100644 --- a/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr +++ b/src/test/ui/ufcs/ufcs-explicit-self-bad.stderr @@ -38,7 +38,7 @@ note: the anonymous lifetime #1 defined on the method body at 37:5... | LL | fn dummy2(self: &Bar) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 35:6 +note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 35:6 --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { @@ -52,7 +52,7 @@ LL | fn dummy2(self: &Bar) {} | = note: expected type `&'a Bar` found type `&Bar` -note: the lifetime 'a as defined on the impl at 35:6... +note: the lifetime `'a` as defined on the impl at 35:6... --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { @@ -76,7 +76,7 @@ note: the anonymous lifetime #2 defined on the method body at 39:5... | LL | fn dummy3(self: &&Bar) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...does not necessarily outlive the lifetime 'a as defined on the impl at 35:6 +note: ...does not necessarily outlive the lifetime `'a` as defined on the impl at 35:6 --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { @@ -90,7 +90,7 @@ LL | fn dummy3(self: &&Bar) {} | = note: expected type `&'a Bar` found type `&Bar` -note: the lifetime 'a as defined on the impl at 35:6... +note: the lifetime `'a` as defined on the impl at 35:6... --> $DIR/ufcs-explicit-self-bad.rs:35:6 | LL | impl<'a, T> SomeTrait for &'a Bar { diff --git a/src/test/ui/variance/variance-btree-invariant-types.stderr b/src/test/ui/variance/variance-btree-invariant-types.stderr index 49222fc7fa62..0f93927683ea 100644 --- a/src/test/ui/variance/variance-btree-invariant-types.stderr +++ b/src/test/ui/variance/variance-btree-invariant-types.stderr @@ -6,7 +6,7 @@ LL | v | = note: expected type `std::collections::btree_map::IterMut<'_, &'new (), _>` found type `std::collections::btree_map::IterMut<'_, &'static (), _>` -note: the lifetime 'new as defined on the function body at 3:21... +note: the lifetime `'new` as defined on the function body at 3:21... --> $DIR/variance-btree-invariant-types.rs:3:21 | LL | fn iter_cov_key<'a, 'new>(v: IterMut<'a, &'static (), ()>) -> IterMut<'a, &'new (), ()> { @@ -21,7 +21,7 @@ LL | v | = note: expected type `std::collections::btree_map::IterMut<'_, _, &'new ()>` found type `std::collections::btree_map::IterMut<'_, _, &'static ()>` -note: the lifetime 'new as defined on the function body at 6:21... +note: the lifetime `'new` as defined on the function body at 6:21... --> $DIR/variance-btree-invariant-types.rs:6:21 | LL | fn iter_cov_val<'a, 'new>(v: IterMut<'a, (), &'static ()>) -> IterMut<'a, (), &'new ()> { @@ -36,7 +36,7 @@ LL | v | = note: expected type `std::collections::btree_map::IterMut<'_, &'static (), _>` found type `std::collections::btree_map::IterMut<'_, &'new (), _>` -note: the lifetime 'new as defined on the function body at 9:24... +note: the lifetime `'new` as defined on the function body at 9:24... --> $DIR/variance-btree-invariant-types.rs:9:24 | LL | fn iter_contra_key<'a, 'new>(v: IterMut<'a, &'new (), ()>) -> IterMut<'a, &'static (), ()> { @@ -51,7 +51,7 @@ LL | v | = note: expected type `std::collections::btree_map::IterMut<'_, _, &'static ()>` found type `std::collections::btree_map::IterMut<'_, _, &'new ()>` -note: the lifetime 'new as defined on the function body at 12:24... +note: the lifetime `'new` as defined on the function body at 12:24... --> $DIR/variance-btree-invariant-types.rs:12:24 | LL | fn iter_contra_val<'a, 'new>(v: IterMut<'a, (), &'new ()>) -> IterMut<'a, (), &'static ()> { @@ -66,7 +66,7 @@ LL | v | = note: expected type `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` found type `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` -note: the lifetime 'new as defined on the function body at 16:20... +note: the lifetime `'new` as defined on the function body at 16:20... --> $DIR/variance-btree-invariant-types.rs:16:20 | LL | fn occ_cov_key<'a, 'new>(v: OccupiedEntry<'a, &'static (), ()>) @@ -81,7 +81,7 @@ LL | v | = note: expected type `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` found type `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` -note: the lifetime 'new as defined on the function body at 20:20... +note: the lifetime `'new` as defined on the function body at 20:20... --> $DIR/variance-btree-invariant-types.rs:20:20 | LL | fn occ_cov_val<'a, 'new>(v: OccupiedEntry<'a, (), &'static ()>) @@ -96,7 +96,7 @@ LL | v | = note: expected type `std::collections::btree_map::OccupiedEntry<'_, &'static (), _>` found type `std::collections::btree_map::OccupiedEntry<'_, &'new (), _>` -note: the lifetime 'new as defined on the function body at 24:23... +note: the lifetime `'new` as defined on the function body at 24:23... --> $DIR/variance-btree-invariant-types.rs:24:23 | LL | fn occ_contra_key<'a, 'new>(v: OccupiedEntry<'a, &'new (), ()>) @@ -111,7 +111,7 @@ LL | v | = note: expected type `std::collections::btree_map::OccupiedEntry<'_, _, &'static ()>` found type `std::collections::btree_map::OccupiedEntry<'_, _, &'new ()>` -note: the lifetime 'new as defined on the function body at 28:23... +note: the lifetime `'new` as defined on the function body at 28:23... --> $DIR/variance-btree-invariant-types.rs:28:23 | LL | fn occ_contra_val<'a, 'new>(v: OccupiedEntry<'a, (), &'new ()>) @@ -126,7 +126,7 @@ LL | v | = note: expected type `std::collections::btree_map::VacantEntry<'_, &'new (), _>` found type `std::collections::btree_map::VacantEntry<'_, &'static (), _>` -note: the lifetime 'new as defined on the function body at 33:20... +note: the lifetime `'new` as defined on the function body at 33:20... --> $DIR/variance-btree-invariant-types.rs:33:20 | LL | fn vac_cov_key<'a, 'new>(v: VacantEntry<'a, &'static (), ()>) @@ -141,7 +141,7 @@ LL | v | = note: expected type `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` found type `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` -note: the lifetime 'new as defined on the function body at 37:20... +note: the lifetime `'new` as defined on the function body at 37:20... --> $DIR/variance-btree-invariant-types.rs:37:20 | LL | fn vac_cov_val<'a, 'new>(v: VacantEntry<'a, (), &'static ()>) @@ -156,7 +156,7 @@ LL | v | = note: expected type `std::collections::btree_map::VacantEntry<'_, &'static (), _>` found type `std::collections::btree_map::VacantEntry<'_, &'new (), _>` -note: the lifetime 'new as defined on the function body at 41:23... +note: the lifetime `'new` as defined on the function body at 41:23... --> $DIR/variance-btree-invariant-types.rs:41:23 | LL | fn vac_contra_key<'a, 'new>(v: VacantEntry<'a, &'new (), ()>) @@ -171,7 +171,7 @@ LL | v | = note: expected type `std::collections::btree_map::VacantEntry<'_, _, &'static ()>` found type `std::collections::btree_map::VacantEntry<'_, _, &'new ()>` -note: the lifetime 'new as defined on the function body at 45:23... +note: the lifetime `'new` as defined on the function body at 45:23... --> $DIR/variance-btree-invariant-types.rs:45:23 | LL | fn vac_contra_val<'a, 'new>(v: VacantEntry<'a, (), &'new ()>) diff --git a/src/test/ui/variance/variance-contravariant-arg-object.stderr b/src/test/ui/variance/variance-contravariant-arg-object.stderr index 263c849e1998..27017e5dc47d 100644 --- a/src/test/ui/variance/variance-contravariant-arg-object.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-object.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `dyn Get<&'min i32>` found type `dyn Get<&'max i32>` -note: the lifetime 'min as defined on the function body at 10:21... +note: the lifetime `'min` as defined on the function body at 10:21... --> $DIR/variance-contravariant-arg-object.rs:10:21 | LL | fn get_min_from_max<'min, 'max>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 --> $DIR/variance-contravariant-arg-object.rs:10:27 | LL | fn get_min_from_max<'min, 'max>(v: Box>) @@ -25,12 +25,12 @@ LL | v | = note: expected type `dyn Get<&'max i32>` found type `dyn Get<&'min i32>` -note: the lifetime 'min as defined on the function body at 17:21... +note: the lifetime `'min` as defined on the function body at 17:21... --> $DIR/variance-contravariant-arg-object.rs:17:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 17:27 --> $DIR/variance-contravariant-arg-object.rs:17:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) diff --git a/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr b/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr index ffe690dd2207..1752b3b36a48 100644 --- a/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-contravariant-arg-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::() | = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` -note: the lifetime 'min as defined on the function body at 10:21... +note: the lifetime `'min` as defined on the function body at 10:21... --> $DIR/variance-contravariant-arg-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 --> $DIR/variance-contravariant-arg-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::() | = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` -note: the lifetime 'min as defined on the function body at 16:21... +note: the lifetime `'min` as defined on the function body at 16:21... --> $DIR/variance-contravariant-arg-trait-match.rs:16:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 16:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 16:27 --> $DIR/variance-contravariant-arg-trait-match.rs:16:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-contravariant-self-trait-match.stderr b/src/test/ui/variance/variance-contravariant-self-trait-match.stderr index 6f445d79bf5d..e35aec4c0ce2 100644 --- a/src/test/ui/variance/variance-contravariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-contravariant-self-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::<&'min G>(); | = note: expected type `Get` found type `Get` -note: the lifetime 'min as defined on the function body at 10:21... +note: the lifetime `'min` as defined on the function body at 10:21... --> $DIR/variance-contravariant-self-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 --> $DIR/variance-contravariant-self-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::<&'max G>(); | = note: expected type `Get` found type `Get` -note: the lifetime 'min as defined on the function body at 16:21... +note: the lifetime `'min` as defined on the function body at 16:21... --> $DIR/variance-contravariant-self-trait-match.rs:16:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 16:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 16:27 --> $DIR/variance-contravariant-self-trait-match.rs:16:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-covariant-arg-object.stderr b/src/test/ui/variance/variance-covariant-arg-object.stderr index 94f80c2b657f..b986edb809f6 100644 --- a/src/test/ui/variance/variance-covariant-arg-object.stderr +++ b/src/test/ui/variance/variance-covariant-arg-object.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `dyn Get<&'min i32>` found type `dyn Get<&'max i32>` -note: the lifetime 'min as defined on the function body at 10:21... +note: the lifetime `'min` as defined on the function body at 10:21... --> $DIR/variance-covariant-arg-object.rs:10:21 | LL | fn get_min_from_max<'min, 'max>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 --> $DIR/variance-covariant-arg-object.rs:10:27 | LL | fn get_min_from_max<'min, 'max>(v: Box>) @@ -25,12 +25,12 @@ LL | v | = note: expected type `dyn Get<&'max i32>` found type `dyn Get<&'min i32>` -note: the lifetime 'min as defined on the function body at 18:21... +note: the lifetime `'min` as defined on the function body at 18:21... --> $DIR/variance-covariant-arg-object.rs:18:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 18:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 18:27 --> $DIR/variance-covariant-arg-object.rs:18:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) diff --git a/src/test/ui/variance/variance-covariant-arg-trait-match.stderr b/src/test/ui/variance/variance-covariant-arg-trait-match.stderr index c0209edc9155..aa383fcc2628 100644 --- a/src/test/ui/variance/variance-covariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-covariant-arg-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::() | = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` -note: the lifetime 'min as defined on the function body at 10:21... +note: the lifetime `'min` as defined on the function body at 10:21... --> $DIR/variance-covariant-arg-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 --> $DIR/variance-covariant-arg-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::() | = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` -note: the lifetime 'min as defined on the function body at 17:21... +note: the lifetime `'min` as defined on the function body at 17:21... --> $DIR/variance-covariant-arg-trait-match.rs:17:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 17:27 --> $DIR/variance-covariant-arg-trait-match.rs:17:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-covariant-self-trait-match.stderr b/src/test/ui/variance/variance-covariant-self-trait-match.stderr index fe5fe105c6b3..a25d1044d425 100644 --- a/src/test/ui/variance/variance-covariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-covariant-self-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::<&'min G>(); | = note: expected type `Get` found type `Get` -note: the lifetime 'min as defined on the function body at 10:21... +note: the lifetime `'min` as defined on the function body at 10:21... --> $DIR/variance-covariant-self-trait-match.rs:10:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 10:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 10:27 --> $DIR/variance-covariant-self-trait-match.rs:10:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::<&'max G>(); | = note: expected type `Get` found type `Get` -note: the lifetime 'min as defined on the function body at 17:21... +note: the lifetime `'min` as defined on the function body at 17:21... --> $DIR/variance-covariant-self-trait-match.rs:17:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 17:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 17:27 --> $DIR/variance-covariant-self-trait-match.rs:17:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-invariant-arg-object.stderr b/src/test/ui/variance/variance-invariant-arg-object.stderr index 50a8697d4392..8ff1e23e8add 100644 --- a/src/test/ui/variance/variance-invariant-arg-object.stderr +++ b/src/test/ui/variance/variance-invariant-arg-object.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `dyn Get<&'min i32>` found type `dyn Get<&'max i32>` -note: the lifetime 'min as defined on the function body at 7:21... +note: the lifetime `'min` as defined on the function body at 7:21... --> $DIR/variance-invariant-arg-object.rs:7:21 | LL | fn get_min_from_max<'min, 'max>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 7:27 --> $DIR/variance-invariant-arg-object.rs:7:27 | LL | fn get_min_from_max<'min, 'max>(v: Box>) @@ -25,12 +25,12 @@ LL | v | = note: expected type `dyn Get<&'max i32>` found type `dyn Get<&'min i32>` -note: the lifetime 'min as defined on the function body at 14:21... +note: the lifetime `'min` as defined on the function body at 14:21... --> $DIR/variance-invariant-arg-object.rs:14:21 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 14:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 14:27 --> $DIR/variance-invariant-arg-object.rs:14:27 | LL | fn get_max_from_min<'min, 'max, G>(v: Box>) diff --git a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr b/src/test/ui/variance/variance-invariant-arg-trait-match.stderr index c8a1111e6237..b58993737c78 100644 --- a/src/test/ui/variance/variance-invariant-arg-trait-match.stderr +++ b/src/test/ui/variance/variance-invariant-arg-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::() | = note: expected type `Get<&'min i32>` found type `Get<&'max i32>` -note: the lifetime 'min as defined on the function body at 7:21... +note: the lifetime `'min` as defined on the function body at 7:21... --> $DIR/variance-invariant-arg-trait-match.rs:7:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 7:27 --> $DIR/variance-invariant-arg-trait-match.rs:7:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::() | = note: expected type `Get<&'max i32>` found type `Get<&'min i32>` -note: the lifetime 'min as defined on the function body at 13:21... +note: the lifetime `'min` as defined on the function body at 13:21... --> $DIR/variance-invariant-arg-trait-match.rs:13:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 13:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 13:27 --> $DIR/variance-invariant-arg-trait-match.rs:13:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-invariant-self-trait-match.stderr b/src/test/ui/variance/variance-invariant-self-trait-match.stderr index cb03d95f7710..4a1d4d28b480 100644 --- a/src/test/ui/variance/variance-invariant-self-trait-match.stderr +++ b/src/test/ui/variance/variance-invariant-self-trait-match.stderr @@ -6,12 +6,12 @@ LL | impls_get::<&'min G>(); | = note: expected type `Get` found type `Get` -note: the lifetime 'min as defined on the function body at 7:21... +note: the lifetime `'min` as defined on the function body at 7:21... --> $DIR/variance-invariant-self-trait-match.rs:7:21 | LL | fn get_min_from_max<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 7:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 7:27 --> $DIR/variance-invariant-self-trait-match.rs:7:27 | LL | fn get_min_from_max<'min, 'max, G>() @@ -25,12 +25,12 @@ LL | impls_get::<&'max G>(); | = note: expected type `Get` found type `Get` -note: the lifetime 'min as defined on the function body at 13:21... +note: the lifetime `'min` as defined on the function body at 13:21... --> $DIR/variance-invariant-self-trait-match.rs:13:21 | LL | fn get_max_from_min<'min, 'max, G>() | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 13:27 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 13:27 --> $DIR/variance-invariant-self-trait-match.rs:13:27 | LL | fn get_max_from_min<'min, 'max, G>() diff --git a/src/test/ui/variance/variance-use-contravariant-struct-1.stderr b/src/test/ui/variance/variance-use-contravariant-struct-1.stderr index 7c433378df5c..618f56da512d 100644 --- a/src/test/ui/variance/variance-use-contravariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-contravariant-struct-1.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `SomeStruct<&'min ()>` found type `SomeStruct<&'max ()>` -note: the lifetime 'min as defined on the function body at 8:8... +note: the lifetime `'min` as defined on the function body at 8:8... --> $DIR/variance-use-contravariant-struct-1.rs:8:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 8:13 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 8:13 --> $DIR/variance-use-contravariant-struct-1.rs:8:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) diff --git a/src/test/ui/variance/variance-use-covariant-struct-1.stderr b/src/test/ui/variance/variance-use-covariant-struct-1.stderr index 6ae7d12c4633..0b3a8dcfc86f 100644 --- a/src/test/ui/variance/variance-use-covariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-covariant-struct-1.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `SomeStruct<&'max ()>` found type `SomeStruct<&'min ()>` -note: the lifetime 'min as defined on the function body at 6:8... +note: the lifetime `'min` as defined on the function body at 6:8... --> $DIR/variance-use-covariant-struct-1.rs:6:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 6:13 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 6:13 --> $DIR/variance-use-covariant-struct-1.rs:6:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'min ()>) diff --git a/src/test/ui/variance/variance-use-invariant-struct-1.stderr b/src/test/ui/variance/variance-use-invariant-struct-1.stderr index 793954e3a1f0..31deefb535e9 100644 --- a/src/test/ui/variance/variance-use-invariant-struct-1.stderr +++ b/src/test/ui/variance/variance-use-invariant-struct-1.stderr @@ -6,12 +6,12 @@ LL | v | = note: expected type `SomeStruct<&'min ()>` found type `SomeStruct<&'max ()>` -note: the lifetime 'min as defined on the function body at 8:8... +note: the lifetime `'min` as defined on the function body at 8:8... --> $DIR/variance-use-invariant-struct-1.rs:8:8 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 8:13 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 8:13 --> $DIR/variance-use-invariant-struct-1.rs:8:13 | LL | fn foo<'min,'max>(v: SomeStruct<&'max ()>) @@ -25,12 +25,12 @@ LL | v | = note: expected type `SomeStruct<&'max ()>` found type `SomeStruct<&'min ()>` -note: the lifetime 'min as defined on the function body at 15:8... +note: the lifetime `'min` as defined on the function body at 15:8... --> $DIR/variance-use-invariant-struct-1.rs:15:8 | LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) | ^^^^ -note: ...does not necessarily outlive the lifetime 'max as defined on the function body at 15:13 +note: ...does not necessarily outlive the lifetime `'max` as defined on the function body at 15:13 --> $DIR/variance-use-invariant-struct-1.rs:15:13 | LL | fn bar<'min,'max>(v: SomeStruct<&'min ()>) diff --git a/src/test/ui/wf/wf-static-method.stderr b/src/test/ui/wf/wf-static-method.stderr index da4e8ebf9c05..93d16514a507 100644 --- a/src/test/ui/wf/wf-static-method.stderr +++ b/src/test/ui/wf/wf-static-method.stderr @@ -4,12 +4,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | u | ^ | -note: ...the reference is valid for the lifetime 'a as defined on the impl at 14:6... +note: ...the reference is valid for the lifetime `'a` as defined on the impl at 14:6... --> $DIR/wf-static-method.rs:14:6 | LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { | ^^ -note: ...but the borrowed content is only valid for the lifetime 'b as defined on the impl at 14:10 +note: ...but the borrowed content is only valid for the lifetime `'b` as defined on the impl at 14:10 --> $DIR/wf-static-method.rs:14:10 | LL | impl<'a, 'b> Foo<'a, 'b, Evil<'a, 'b>> for () { @@ -21,12 +21,12 @@ error[E0478]: lifetime bound not satisfied LL | let me = Self::make_me(); | ^^^^^^^^^^^^^ | -note: lifetime parameter instantiated with the lifetime 'b as defined on the impl at 23:10 +note: lifetime parameter instantiated with the lifetime `'b` as defined on the impl at 23:10 --> $DIR/wf-static-method.rs:23:10 | LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { | ^^ -note: but lifetime parameter must outlive the lifetime 'a as defined on the impl at 23:6 +note: but lifetime parameter must outlive the lifetime `'a` as defined on the impl at 23:6 --> $DIR/wf-static-method.rs:23:6 | LL | impl<'a, 'b> Foo<'a, 'b, ()> for IndirectEvil<'a, 'b> { @@ -38,12 +38,12 @@ error[E0312]: lifetime of reference outlives lifetime of borrowed content... LL | u | ^ | -note: ...the reference is valid for the lifetime 'a as defined on the impl at 31:6... +note: ...the reference is valid for the lifetime `'a` as defined on the impl at 31:6... --> $DIR/wf-static-method.rs:31:6 | LL | impl<'a, 'b> Evil<'a, 'b> { | ^^ -note: ...but the borrowed content is only valid for the lifetime 'b as defined on the impl at 31:10 +note: ...but the borrowed content is only valid for the lifetime `'b` as defined on the impl at 31:10 --> $DIR/wf-static-method.rs:31:10 | LL | impl<'a, 'b> Evil<'a, 'b> { @@ -55,7 +55,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | <()>::static_evil(b) | ^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'b as defined on the function body at 40:13... +note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 40:13... --> $DIR/wf-static-method.rs:40:13 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -65,7 +65,7 @@ note: ...so that reference does not outlive borrowed content | LL | <()>::static_evil(b) | ^ -note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 40:9... +note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 40:9... --> $DIR/wf-static-method.rs:40:9 | LL | fn evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -82,7 +82,7 @@ error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` d LL | ::static_evil(b) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime 'b as defined on the function body at 44:22... +note: first, the lifetime cannot outlive the lifetime `'b` as defined on the function body at 44:22... --> $DIR/wf-static-method.rs:44:22 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { @@ -92,7 +92,7 @@ note: ...so that reference does not outlive borrowed content | LL | ::static_evil(b) | ^ -note: but, the lifetime must be valid for the lifetime 'a as defined on the function body at 44:18... +note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 44:18... --> $DIR/wf-static-method.rs:44:18 | LL | fn indirect_evil<'a, 'b>(b: &'b u32) -> &'a u32 { From 63d67fa273f6b4409623b1dc9517ee5aade18cd2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 11 Oct 2019 09:57:44 +0200 Subject: [PATCH 264/545] ignore-emcscripten as it does not support threads --- src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs index a6666d66ce57..bc15fcb0e399 100644 --- a/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +++ b/src/test/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs @@ -1,5 +1,6 @@ // run-pass // ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten no threads support // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine // should still run destructors as it unwinds the stack. However, From 90d0baf2b4ec7837b50f1d57ff79e31dbebf10c6 Mon Sep 17 00:00:00 2001 From: qtmlabs Date: Fri, 11 Oct 2019 15:13:22 +0700 Subject: [PATCH 265/545] Upgrade GCC to 8.3.0, glibc to 1.17.0 and crosstool-ng to 1.24.0 for dist-armv7-linux --- src/ci/docker/README.md | 9 +- src/ci/docker/dist-armv7-linux/Dockerfile | 8 +- .../armv7-linux-gnueabihf.config | 809 +++++++++++------- .../docker/dist-armv7-linux/crosstool-ng.sh | 11 + .../001-arm-libgcc_s_resume-used.patch | 48 -- 5 files changed, 514 insertions(+), 371 deletions(-) create mode 100644 src/ci/docker/dist-armv7-linux/crosstool-ng.sh delete mode 100644 src/ci/docker/dist-armv7-linux/patches/glibc/ports-2.16.0/001-arm-libgcc_s_resume-used.patch diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 367e43849923..a2d83eca24b0 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -165,8 +165,7 @@ For targets: `arm-unknown-linux-gnueabihf` For targets: `armv7-unknown-linux-gnueabihf` - Path and misc options > Prefix directory = /x-tools/${CT\_TARGET} -- Path and misc options > Patches origin = Bundled, then local -- Path and misc options > Local patch directory = /tmp/patches +- Path and misc options > Patches origin = Bundled only - Target options > Target Architecture = arm - Target options > Suffix to the arch-part = v7 - Target options > Architecture level = armv7-a -- (+) @@ -174,9 +173,9 @@ For targets: `armv7-unknown-linux-gnueabihf` - Target options > Floating point = hardware (FPU) -- (\*) - Target options > Default instruction set mode = thumb -- (\*) - Operating System > Target OS = linux -- Operating System > Linux kernel version = 3.2.72 -- Precise kernel -- C-library > glibc version = 2.16.0 -- C compiler > gcc version = 5.2.0 +- Operating System > Linux kernel version = 3.2.101 +- C-library > glibc version = 2.17.0 +- C compiler > gcc version = 8.3.0 - C compiler > C++ = ENABLE -- to cross compile LLVM (\*) These options have been selected to match the configuration of the arm diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile index 170b8134d3ed..d3ea563eab12 100644 --- a/src/ci/docker/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-linux/Dockerfile @@ -3,12 +3,7 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -# Ubuntu 16.04 (this container) ships with make 4, but something in the -# toolchains we build below chokes on that, so go back to make 3 -COPY scripts/make3.sh /scripts/ -RUN sh /scripts/make3.sh - -COPY scripts/crosstool-ng.sh /scripts/ +COPY crosstool-ng.sh /scripts/ RUN sh /scripts/crosstool-ng.sh COPY scripts/rustbuild-setup.sh /scripts/ @@ -16,7 +11,6 @@ RUN sh /scripts/rustbuild-setup.sh USER rustbuild WORKDIR /tmp -COPY dist-armv7-linux/patches/ /tmp/patches/ COPY dist-armv7-linux/build-toolchains.sh dist-armv7-linux/armv7-linux-gnueabihf.config /tmp/ RUN ./build-toolchains.sh diff --git a/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config b/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config index 5cccfd8444d3..81b3d7477ec8 100644 --- a/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config +++ b/src/ci/docker/dist-armv7-linux/armv7-linux-gnueabihf.config @@ -1,9 +1,32 @@ # # Automatically generated file; DO NOT EDIT. -# Crosstool-NG Configuration +# crosstool-NG Configuration # -CT_CONFIGURE_has_make381=y -CT_CONFIGURE_has_xz=y +CT_CONFIGURE_has_static_link=y +CT_CONFIGURE_has_cxx11=y +CT_CONFIGURE_has_wget=y +CT_CONFIGURE_has_curl=y +CT_CONFIGURE_has_make_3_81_or_newer=y +CT_CONFIGURE_has_make_4_0_or_newer=y +CT_CONFIGURE_has_libtool_2_4_or_newer=y +CT_CONFIGURE_has_libtoolize_2_4_or_newer=y +CT_CONFIGURE_has_autoconf_2_65_or_newer=y +CT_CONFIGURE_has_autoreconf_2_65_or_newer=y +CT_CONFIGURE_has_automake_1_15_or_newer=y +CT_CONFIGURE_has_gnu_m4_1_4_12_or_newer=y +CT_CONFIGURE_has_python_3_4_or_newer=y +CT_CONFIGURE_has_bison_2_7_or_newer=y +CT_CONFIGURE_has_python=y +CT_CONFIGURE_has_dtc=y +CT_CONFIGURE_has_svn=y +CT_CONFIGURE_has_git=y +CT_CONFIGURE_has_md5sum=y +CT_CONFIGURE_has_sha1sum=y +CT_CONFIGURE_has_sha256sum=y +CT_CONFIGURE_has_sha512sum=y +CT_CONFIGURE_has_install_with_strip_program=y +CT_CONFIG_VERSION_CURRENT="3" +CT_CONFIG_VERSION="3" CT_MODULES=y # @@ -21,40 +44,46 @@ CT_MODULES=y # Paths # CT_LOCAL_TARBALLS_DIR="" +# CT_TARBALLS_BUILDROOT_LAYOUT is not set CT_WORK_DIR="${CT_TOP_DIR}/.build" +CT_BUILD_TOP_DIR="${CT_WORK_DIR:-${CT_TOP_DIR}/.build}/${CT_HOST:+HOST-${CT_HOST}/}${CT_TARGET}" CT_PREFIX_DIR="/x-tools/${CT_TARGET}" -CT_INSTALL_DIR="${CT_PREFIX_DIR}" CT_RM_RF_PREFIX_DIR=y CT_REMOVE_DOCS=y -CT_INSTALL_DIR_RO=y +CT_INSTALL_LICENSES=y +CT_PREFIX_DIR_RO=y CT_STRIP_HOST_TOOLCHAIN_EXECUTABLES=y # CT_STRIP_TARGET_TOOLCHAIN_EXECUTABLES is not set # # Downloading # +CT_DOWNLOAD_AGENT_WGET=y +# CT_DOWNLOAD_AGENT_CURL is not set +# CT_DOWNLOAD_AGENT_NONE is not set # CT_FORBID_DOWNLOAD is not set # CT_FORCE_DOWNLOAD is not set CT_CONNECT_TIMEOUT=10 +CT_DOWNLOAD_WGET_OPTIONS="--passive-ftp --tries=3 -nc --progress=dot:binary" # CT_ONLY_DOWNLOAD is not set # CT_USE_MIRROR is not set +CT_VERIFY_DOWNLOAD_DIGEST=y +CT_VERIFY_DOWNLOAD_DIGEST_SHA512=y +# CT_VERIFY_DOWNLOAD_DIGEST_SHA256 is not set +# CT_VERIFY_DOWNLOAD_DIGEST_SHA1 is not set +# CT_VERIFY_DOWNLOAD_DIGEST_MD5 is not set +CT_VERIFY_DOWNLOAD_DIGEST_ALG="sha512" +# CT_VERIFY_DOWNLOAD_SIGNATURE is not set # # Extracting # # CT_FORCE_EXTRACT is not set -CT_OVERIDE_CONFIG_GUESS_SUB=y +CT_OVERRIDE_CONFIG_GUESS_SUB=y # CT_ONLY_EXTRACT is not set -# CT_PATCH_BUNDLED is not set -# CT_PATCH_LOCAL is not set -CT_PATCH_BUNDLED_LOCAL=y -# CT_PATCH_LOCAL_BUNDLED is not set -# CT_PATCH_BUNDLED_FALLBACK_LOCAL is not set -# CT_PATCH_LOCAL_FALLBACK_BUNDLED is not set -# CT_PATCH_NONE is not set -CT_PATCH_ORDER="bundled,local" -CT_PATCH_USE_LOCAL=y -CT_LOCAL_PATCH_DIR="/tmp/patches" +CT_PATCH_BUNDLED=y +# CT_PATCH_BUNDLED_LOCAL is not set +CT_PATCH_ORDER="bundled" # # Build behavior @@ -90,78 +119,29 @@ CT_LOG_FILE_COMPRESS=y # # Target options # +# CT_ARCH_ALPHA is not set +# CT_ARCH_ARC is not set +CT_ARCH_ARM=y +# CT_ARCH_AVR is not set +# CT_ARCH_M68K is not set +# CT_ARCH_MIPS is not set +# CT_ARCH_NIOS2 is not set +# CT_ARCH_POWERPC is not set +# CT_ARCH_S390 is not set +# CT_ARCH_SH is not set +# CT_ARCH_SPARC is not set +# CT_ARCH_X86 is not set +# CT_ARCH_XTENSA is not set CT_ARCH="arm" -CT_ARCH_SUPPORTS_BOTH_MMU=y -CT_ARCH_SUPPORTS_BOTH_ENDIAN=y -CT_ARCH_SUPPORTS_32=y -CT_ARCH_SUPPORTS_64=y -CT_ARCH_SUPPORTS_WITH_ARCH=y -CT_ARCH_SUPPORTS_WITH_CPU=y -CT_ARCH_SUPPORTS_WITH_TUNE=y -CT_ARCH_SUPPORTS_WITH_FLOAT=y -CT_ARCH_SUPPORTS_WITH_FPU=y -CT_ARCH_SUPPORTS_SOFTFP=y -CT_ARCH_DEFAULT_HAS_MMU=y -CT_ARCH_DEFAULT_LE=y -CT_ARCH_DEFAULT_32=y -CT_ARCH_ARCH="armv7-a" +CT_ARCH_CHOICE_KSYM="ARM" CT_ARCH_CPU="" CT_ARCH_TUNE="" -CT_ARCH_FPU="vfpv3-d16" -# CT_ARCH_BE is not set -CT_ARCH_LE=y -CT_ARCH_32=y -# CT_ARCH_64 is not set -CT_ARCH_BITNESS=32 -CT_ARCH_FLOAT_HW=y -# CT_ARCH_FLOAT_SW is not set -CT_TARGET_CFLAGS="" -CT_TARGET_LDFLAGS="" -# CT_ARCH_alpha is not set -CT_ARCH_arm=y -# CT_ARCH_avr is not set -# CT_ARCH_m68k is not set -# CT_ARCH_mips is not set -# CT_ARCH_nios2 is not set -# CT_ARCH_powerpc is not set -# CT_ARCH_s390 is not set -# CT_ARCH_sh is not set -# CT_ARCH_sparc is not set -# CT_ARCH_x86 is not set -# CT_ARCH_xtensa is not set -CT_ARCH_alpha_AVAILABLE=y -CT_ARCH_arm_AVAILABLE=y -CT_ARCH_avr_AVAILABLE=y -CT_ARCH_m68k_AVAILABLE=y -CT_ARCH_microblaze_AVAILABLE=y -CT_ARCH_mips_AVAILABLE=y -CT_ARCH_nios2_AVAILABLE=y -CT_ARCH_powerpc_AVAILABLE=y -CT_ARCH_s390_AVAILABLE=y -CT_ARCH_sh_AVAILABLE=y -CT_ARCH_sparc_AVAILABLE=y -CT_ARCH_x86_AVAILABLE=y -CT_ARCH_xtensa_AVAILABLE=y -CT_ARCH_SUFFIX="v7" +CT_ARCH_ARM_SHOW=y # -# Generic target options -# -# CT_MULTILIB is not set -CT_ARCH_USE_MMU=y -CT_ARCH_ENDIAN="little" - -# -# Target optimisations -# -CT_ARCH_EXCLUSIVE_WITH_CPU=y -# CT_ARCH_FLOAT_AUTO is not set -# CT_ARCH_FLOAT_SOFTFP is not set -CT_ARCH_FLOAT="hard" - -# -# arm other options +# Options for arm # +CT_ARCH_ARM_PKG_KSYM="" CT_ARCH_ARM_MODE="thumb" # CT_ARCH_ARM_MODE_ARM is not set CT_ARCH_ARM_MODE_THUMB=y @@ -169,6 +149,50 @@ CT_ARCH_ARM_MODE_THUMB=y CT_ARCH_ARM_EABI_FORCE=y CT_ARCH_ARM_EABI=y CT_ARCH_ARM_TUPLE_USE_EABIHF=y +CT_ALL_ARCH_CHOICES="ALPHA ARC ARM AVR M68K MICROBLAZE MIPS MOXIE MSP430 NIOS2 POWERPC RISCV S390 SH SPARC X86 XTENSA" +CT_ARCH_SUFFIX="v7" +# CT_OMIT_TARGET_VENDOR is not set + +# +# Generic target options +# +# CT_MULTILIB is not set +CT_DEMULTILIB=y +CT_ARCH_SUPPORTS_BOTH_MMU=y +CT_ARCH_DEFAULT_HAS_MMU=y +CT_ARCH_USE_MMU=y +CT_ARCH_SUPPORTS_FLAT_FORMAT=y +CT_ARCH_SUPPORTS_EITHER_ENDIAN=y +CT_ARCH_DEFAULT_LE=y +# CT_ARCH_BE is not set +CT_ARCH_LE=y +CT_ARCH_ENDIAN="little" +CT_ARCH_SUPPORTS_32=y +CT_ARCH_SUPPORTS_64=y +CT_ARCH_DEFAULT_32=y +CT_ARCH_BITNESS=32 +CT_ARCH_32=y +# CT_ARCH_64 is not set + +# +# Target optimisations +# +CT_ARCH_SUPPORTS_WITH_ARCH=y +CT_ARCH_SUPPORTS_WITH_CPU=y +CT_ARCH_SUPPORTS_WITH_TUNE=y +CT_ARCH_SUPPORTS_WITH_FLOAT=y +CT_ARCH_SUPPORTS_WITH_FPU=y +CT_ARCH_SUPPORTS_SOFTFP=y +CT_ARCH_EXCLUSIVE_WITH_CPU=y +CT_ARCH_ARCH="armv7-a" +CT_ARCH_FPU="vfpv3-d16" +# CT_ARCH_FLOAT_AUTO is not set +CT_ARCH_FLOAT_HW=y +# CT_ARCH_FLOAT_SOFTFP is not set +# CT_ARCH_FLOAT_SW is not set +CT_TARGET_CFLAGS="" +CT_TARGET_LDFLAGS="" +CT_ARCH_FLOAT="hard" # # Toolchain options @@ -182,7 +206,9 @@ CT_USE_SYSROOT=y CT_SYSROOT_NAME="sysroot" CT_SYSROOT_DIR_PREFIX="" CT_WANTS_STATIC_LINK=y +CT_WANTS_STATIC_LINK_CXX=y # CT_STATIC_TOOLCHAIN is not set +CT_SHOW_CT_VERSION=y CT_TOOLCHAIN_PKGVERSION="" CT_TOOLCHAIN_BUGURL="" @@ -216,126 +242,207 @@ CT_BUILD_SUFFIX="" # Operating System # CT_KERNEL_SUPPORTS_SHARED_LIBS=y +# CT_KERNEL_BARE_METAL is not set +CT_KERNEL_LINUX=y CT_KERNEL="linux" -CT_KERNEL_VERSION="3.2.72" -# CT_KERNEL_bare_metal is not set -CT_KERNEL_linux=y -CT_KERNEL_bare_metal_AVAILABLE=y -CT_KERNEL_linux_AVAILABLE=y -# CT_KERNEL_V_4_3 is not set -# CT_KERNEL_V_4_2 is not set -# CT_KERNEL_V_4_1 is not set -# CT_KERNEL_V_3_18 is not set -# CT_KERNEL_V_3_14 is not set -# CT_KERNEL_V_3_12 is not set -# CT_KERNEL_V_3_10 is not set -# CT_KERNEL_V_3_4 is not set -CT_KERNEL_V_3_2=y -# CT_KERNEL_V_2_6_32 is not set -# CT_KERNEL_LINUX_CUSTOM is not set -CT_KERNEL_windows_AVAILABLE=y +CT_KERNEL_CHOICE_KSYM="LINUX" +CT_KERNEL_LINUX_SHOW=y + +# +# Options for linux +# +CT_KERNEL_LINUX_PKG_KSYM="LINUX" +CT_LINUX_DIR_NAME="linux" +CT_LINUX_PKG_NAME="linux" +CT_LINUX_SRC_RELEASE=y +CT_LINUX_PATCH_ORDER="global" +# CT_LINUX_V_4_20 is not set +# CT_LINUX_V_4_19 is not set +# CT_LINUX_V_4_18 is not set +# CT_LINUX_V_4_17 is not set +# CT_LINUX_V_4_16 is not set +# CT_LINUX_V_4_15 is not set +# CT_LINUX_V_4_14 is not set +# CT_LINUX_V_4_13 is not set +# CT_LINUX_V_4_12 is not set +# CT_LINUX_V_4_11 is not set +# CT_LINUX_V_4_10 is not set +# CT_LINUX_V_4_9 is not set +# CT_LINUX_V_4_4 is not set +# CT_LINUX_V_4_1 is not set +# CT_LINUX_V_3_16 is not set +# CT_LINUX_V_3_13 is not set +# CT_LINUX_V_3_12 is not set +# CT_LINUX_V_3_10 is not set +# CT_LINUX_V_3_4 is not set +CT_LINUX_V_3_2=y +# CT_LINUX_V_2_6_32 is not set +# CT_LINUX_NO_VERSIONS is not set +CT_LINUX_VERSION="3.2.101" +CT_LINUX_MIRRORS="$(CT_Mirrors kernel.org linux ${CT_LINUX_VERSION})" +CT_LINUX_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_LINUX_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_LINUX_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_LINUX_SIGNATURE_FORMAT="unpacked/.sign" +CT_LINUX_4_8_or_older=y +CT_LINUX_older_than_4_8=y +CT_LINUX_3_7_or_older=y +CT_LINUX_older_than_3_7=y +CT_LINUX_later_than_3_2=y +CT_LINUX_3_2_or_later=y +CT_KERNEL_LINUX_VERBOSITY_0=y +# CT_KERNEL_LINUX_VERBOSITY_1 is not set +# CT_KERNEL_LINUX_VERBOSITY_2 is not set +CT_KERNEL_LINUX_VERBOSE_LEVEL=0 +CT_KERNEL_LINUX_INSTALL_CHECK=y +CT_ALL_KERNEL_CHOICES="BARE_METAL LINUX WINDOWS" # # Common kernel options # CT_SHARED_LIBS=y -# -# linux other options -# -CT_KERNEL_LINUX_VERBOSITY_0=y -# CT_KERNEL_LINUX_VERBOSITY_1 is not set -# CT_KERNEL_LINUX_VERBOSITY_2 is not set -CT_KERNEL_LINUX_VERBOSE_LEVEL=0 -CT_KERNEL_LINUX_INSTALL_CHECK=y - # # Binary utilities # CT_ARCH_BINFMT_ELF=y +CT_BINUTILS_BINUTILS=y CT_BINUTILS="binutils" -CT_BINUTILS_binutils=y +CT_BINUTILS_CHOICE_KSYM="BINUTILS" +CT_BINUTILS_BINUTILS_SHOW=y + +# +# Options for binutils +# +CT_BINUTILS_BINUTILS_PKG_KSYM="BINUTILS" +CT_BINUTILS_DIR_NAME="binutils" +CT_BINUTILS_USE_GNU=y +CT_BINUTILS_USE="BINUTILS" +CT_BINUTILS_PKG_NAME="binutils" +CT_BINUTILS_SRC_RELEASE=y +CT_BINUTILS_PATCH_ORDER="global" +CT_BINUTILS_V_2_32=y +# CT_BINUTILS_V_2_31 is not set +# CT_BINUTILS_V_2_30 is not set +# CT_BINUTILS_V_2_29 is not set +# CT_BINUTILS_V_2_28 is not set +# CT_BINUTILS_V_2_27 is not set +# CT_BINUTILS_V_2_26 is not set +# CT_BINUTILS_NO_VERSIONS is not set +CT_BINUTILS_VERSION="2.32" +CT_BINUTILS_MIRRORS="$(CT_Mirrors GNU binutils) $(CT_Mirrors sourceware binutils/releases)" +CT_BINUTILS_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_BINUTILS_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_BINUTILS_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" +CT_BINUTILS_SIGNATURE_FORMAT="packed/.sig" +CT_BINUTILS_later_than_2_30=y +CT_BINUTILS_2_30_or_later=y +CT_BINUTILS_later_than_2_27=y +CT_BINUTILS_2_27_or_later=y +CT_BINUTILS_later_than_2_25=y +CT_BINUTILS_2_25_or_later=y +CT_BINUTILS_later_than_2_23=y +CT_BINUTILS_2_23_or_later=y # # GNU binutils # -# CT_CC_BINUTILS_SHOW_LINARO is not set -CT_BINUTILS_V_2_25_1=y -# CT_BINUTILS_V_2_25 is not set -# CT_BINUTILS_V_2_24 is not set -# CT_BINUTILS_V_2_23_2 is not set -# CT_BINUTILS_V_2_23_1 is not set -# CT_BINUTILS_V_2_22 is not set -# CT_BINUTILS_V_2_21_53 is not set -# CT_BINUTILS_V_2_21_1a is not set -# CT_BINUTILS_V_2_20_1a is not set -# CT_BINUTILS_V_2_19_1a is not set -# CT_BINUTILS_V_2_18a is not set -CT_BINUTILS_VERSION="2.25.1" -CT_BINUTILS_2_25_1_or_later=y -CT_BINUTILS_2_25_or_later=y -CT_BINUTILS_2_24_or_later=y -CT_BINUTILS_2_23_or_later=y -CT_BINUTILS_2_22_or_later=y -CT_BINUTILS_2_21_or_later=y -CT_BINUTILS_2_20_or_later=y -CT_BINUTILS_2_19_or_later=y -CT_BINUTILS_2_18_or_later=y CT_BINUTILS_HAS_HASH_STYLE=y CT_BINUTILS_HAS_GOLD=y -CT_BINUTILS_GOLD_SUPPORTS_ARCH=y -CT_BINUTILS_GOLD_SUPPORT=y CT_BINUTILS_HAS_PLUGINS=y CT_BINUTILS_HAS_PKGVERSION_BUGURL=y -CT_BINUTILS_FORCE_LD_BFD=y +CT_BINUTILS_GOLD_SUPPORTS_ARCH=y +CT_BINUTILS_GOLD_SUPPORT=y +CT_BINUTILS_FORCE_LD_BFD_DEFAULT=y CT_BINUTILS_LINKER_LD=y # CT_BINUTILS_LINKER_LD_GOLD is not set -# CT_BINUTILS_LINKER_GOLD_LD is not set CT_BINUTILS_LINKERS_LIST="ld" CT_BINUTILS_LINKER_DEFAULT="bfd" # CT_BINUTILS_PLUGINS is not set +CT_BINUTILS_RELRO=m CT_BINUTILS_EXTRA_CONFIG_ARRAY="" # CT_BINUTILS_FOR_TARGET is not set - -# -# binutils other options -# +CT_ALL_BINUTILS_CHOICES="BINUTILS" # # C-library # +CT_LIBC_GLIBC=y +# CT_LIBC_UCLIBC is not set CT_LIBC="glibc" -CT_LIBC_VERSION="2.16.0" -CT_LIBC_glibc=y -# CT_LIBC_musl is not set -# CT_LIBC_uClibc is not set -CT_LIBC_avr_libc_AVAILABLE=y -CT_LIBC_glibc_AVAILABLE=y +CT_LIBC_CHOICE_KSYM="GLIBC" CT_THREADS="nptl" -# CT_CC_GLIBC_SHOW_LINARO is not set -# CT_LIBC_GLIBC_V_2_22 is not set -# CT_LIBC_GLIBC_V_2_21 is not set -# CT_LIBC_GLIBC_V_2_20 is not set -# CT_LIBC_GLIBC_V_2_19 is not set -# CT_LIBC_GLIBC_V_2_18 is not set -# CT_LIBC_GLIBC_V_2_17 is not set -CT_LIBC_GLIBC_V_2_16_0=y -# CT_LIBC_GLIBC_V_2_15 is not set -# CT_LIBC_GLIBC_V_2_14_1 is not set -# CT_LIBC_GLIBC_V_2_14 is not set -# CT_LIBC_GLIBC_V_2_13 is not set -# CT_LIBC_GLIBC_V_2_12_2 is not set -# CT_LIBC_GLIBC_V_2_12_1 is not set -# CT_LIBC_GLIBC_V_2_11_1 is not set -# CT_LIBC_GLIBC_V_2_11 is not set -# CT_LIBC_GLIBC_V_2_10_1 is not set -# CT_LIBC_GLIBC_V_2_9 is not set -# CT_LIBC_GLIBC_V_2_8 is not set -CT_LIBC_mingw_AVAILABLE=y -CT_LIBC_musl_AVAILABLE=y -CT_LIBC_newlib_AVAILABLE=y -CT_LIBC_none_AVAILABLE=y -CT_LIBC_uClibc_AVAILABLE=y +CT_LIBC_GLIBC_SHOW=y + +# +# Options for glibc +# +CT_LIBC_GLIBC_PKG_KSYM="GLIBC" +CT_GLIBC_DIR_NAME="glibc" +CT_GLIBC_USE_GNU=y +CT_GLIBC_USE="GLIBC" +CT_GLIBC_PKG_NAME="glibc" +CT_GLIBC_SRC_RELEASE=y +CT_GLIBC_PATCH_ORDER="global" +# CT_GLIBC_V_2_29 is not set +# CT_GLIBC_V_2_28 is not set +# CT_GLIBC_V_2_27 is not set +# CT_GLIBC_V_2_26 is not set +# CT_GLIBC_V_2_25 is not set +# CT_GLIBC_V_2_24 is not set +# CT_GLIBC_V_2_23 is not set +# CT_GLIBC_V_2_19 is not set +CT_GLIBC_V_2_17=y +# CT_GLIBC_V_2_12_1 is not set +# CT_GLIBC_NO_VERSIONS is not set +CT_GLIBC_VERSION="2.17" +CT_GLIBC_MIRRORS="$(CT_Mirrors GNU glibc)" +CT_GLIBC_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GLIBC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GLIBC_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" +CT_GLIBC_SIGNATURE_FORMAT="packed/.sig" +CT_GLIBC_2_29_or_older=y +CT_GLIBC_older_than_2_29=y +CT_GLIBC_2_27_or_older=y +CT_GLIBC_older_than_2_27=y +CT_GLIBC_2_26_or_older=y +CT_GLIBC_older_than_2_26=y +CT_GLIBC_2_25_or_older=y +CT_GLIBC_older_than_2_25=y +CT_GLIBC_2_24_or_older=y +CT_GLIBC_older_than_2_24=y +CT_GLIBC_2_23_or_older=y +CT_GLIBC_older_than_2_23=y +CT_GLIBC_2_20_or_older=y +CT_GLIBC_older_than_2_20=y +CT_GLIBC_2_17_or_later=y +CT_GLIBC_2_17_or_older=y +CT_GLIBC_later_than_2_14=y +CT_GLIBC_2_14_or_later=y +CT_GLIBC_DEP_KERNEL_HEADERS_VERSION=y +CT_GLIBC_DEP_BINUTILS=y +CT_GLIBC_DEP_GCC=y +CT_GLIBC_DEP_PYTHON=y +CT_GLIBC_HAS_NPTL_ADDON=y +CT_GLIBC_HAS_PORTS_ADDON=y +CT_GLIBC_HAS_LIBIDN_ADDON=y +CT_GLIBC_USE_PORTS_ADDON=y +CT_GLIBC_USE_NPTL_ADDON=y +# CT_GLIBC_USE_LIBIDN_ADDON is not set +CT_GLIBC_HAS_OBSOLETE_RPC=y +CT_GLIBC_EXTRA_CONFIG_ARRAY="" +CT_GLIBC_CONFIGPARMS="" +CT_GLIBC_EXTRA_CFLAGS="" +CT_GLIBC_ENABLE_OBSOLETE_RPC=y +# CT_GLIBC_DISABLE_VERSIONING is not set +CT_GLIBC_OLDEST_ABI="" +CT_GLIBC_FORCE_UNWIND=y +# CT_GLIBC_LOCALES is not set +# CT_GLIBC_KERNEL_VERSION_NONE is not set +CT_GLIBC_KERNEL_VERSION_AS_HEADERS=y +# CT_GLIBC_KERNEL_VERSION_CHOSEN is not set +CT_GLIBC_MIN_KERNEL="3.2.101" +CT_ALL_LIBC_CHOICES="AVR_LIBC BIONIC GLIBC MINGW_W64 MOXIEBOX MUSL NEWLIB NONE UCLIBC" CT_LIBC_SUPPORT_THREADS_ANY=y CT_LIBC_SUPPORT_THREADS_NATIVE=y @@ -343,100 +450,71 @@ CT_LIBC_SUPPORT_THREADS_NATIVE=y # Common C library options # CT_THREADS_NATIVE=y +# CT_CREATE_LDSO_CONF is not set CT_LIBC_XLDD=y -# -# glibc other options -# -CT_LIBC_GLIBC_PORTS_EXTERNAL=y -CT_LIBC_GLIBC_MAY_FORCE_PORTS=y -CT_LIBC_glibc_familly=y -CT_LIBC_GLIBC_EXTRA_CONFIG_ARRAY="" -CT_LIBC_GLIBC_CONFIGPARMS="" -CT_LIBC_GLIBC_EXTRA_CFLAGS="" -CT_LIBC_EXTRA_CC_ARGS="" -# CT_LIBC_DISABLE_VERSIONING is not set -CT_LIBC_OLDEST_ABI="" -CT_LIBC_GLIBC_FORCE_UNWIND=y -CT_LIBC_GLIBC_USE_PORTS=y -CT_LIBC_ADDONS_LIST="" - -# -# WARNING !!! -# - -# -# For glibc >= 2.8, it can happen that the tarballs -# - -# -# for the addons are not available for download. -# - -# -# If that happens, bad luck... Try a previous version -# - -# -# or try again later... :-( -# -# CT_LIBC_LOCALES is not set -# CT_LIBC_GLIBC_KERNEL_VERSION_NONE is not set -CT_LIBC_GLIBC_KERNEL_VERSION_AS_HEADERS=y -# CT_LIBC_GLIBC_KERNEL_VERSION_CHOSEN is not set -CT_LIBC_GLIBC_MIN_KERNEL="3.2.72" - # # C compiler # -CT_CC="gcc" CT_CC_CORE_PASSES_NEEDED=y CT_CC_CORE_PASS_1_NEEDED=y CT_CC_CORE_PASS_2_NEEDED=y -CT_CC_gcc=y -# CT_CC_GCC_SHOW_LINARO is not set -CT_CC_GCC_V_5_2_0=y -# CT_CC_GCC_V_4_9_3 is not set -# CT_CC_GCC_V_4_8_5 is not set -# CT_CC_GCC_V_4_7_4 is not set -# CT_CC_GCC_V_4_6_4 is not set -# CT_CC_GCC_V_4_5_4 is not set -# CT_CC_GCC_V_4_4_7 is not set -# CT_CC_GCC_V_4_3_6 is not set -# CT_CC_GCC_V_4_2_4 is not set -CT_CC_GCC_4_2_or_later=y -CT_CC_GCC_4_3_or_later=y -CT_CC_GCC_4_4_or_later=y -CT_CC_GCC_4_5_or_later=y -CT_CC_GCC_4_6_or_later=y -CT_CC_GCC_4_7_or_later=y -CT_CC_GCC_4_8_or_later=y -CT_CC_GCC_4_9_or_later=y -CT_CC_GCC_5=y -CT_CC_GCC_5_or_later=y -CT_CC_GCC_HAS_GRAPHITE=y -CT_CC_GCC_USE_GRAPHITE=y -CT_CC_GCC_HAS_LTO=y -CT_CC_GCC_USE_LTO=y -CT_CC_GCC_HAS_PKGVERSION_BUGURL=y -CT_CC_GCC_HAS_BUILD_ID=y -CT_CC_GCC_HAS_LNK_HASH_STYLE=y -CT_CC_GCC_USE_GMP_MPFR=y -CT_CC_GCC_USE_MPC=y -CT_CC_GCC_HAS_LIBQUADMATH=y -CT_CC_GCC_HAS_LIBSANITIZER=y -CT_CC_GCC_VERSION="5.2.0" -# CT_CC_LANG_FORTRAN is not set +CT_CC_SUPPORT_CXX=y +CT_CC_SUPPORT_FORTRAN=y +CT_CC_SUPPORT_ADA=y +CT_CC_SUPPORT_OBJC=y +CT_CC_SUPPORT_OBJCXX=y +CT_CC_SUPPORT_GOLANG=y +CT_CC_GCC=y +CT_CC="gcc" +CT_CC_CHOICE_KSYM="GCC" +CT_CC_GCC_SHOW=y + +# +# Options for gcc +# +CT_CC_GCC_PKG_KSYM="GCC" +CT_GCC_DIR_NAME="gcc" +CT_GCC_USE_GNU=y +CT_GCC_USE="GCC" +CT_GCC_PKG_NAME="gcc" +CT_GCC_SRC_RELEASE=y +CT_GCC_PATCH_ORDER="global" +CT_GCC_V_8=y +# CT_GCC_V_7 is not set +# CT_GCC_V_6 is not set +# CT_GCC_V_5 is not set +# CT_GCC_V_4_9 is not set +# CT_GCC_NO_VERSIONS is not set +CT_GCC_VERSION="8.3.0" +CT_GCC_MIRRORS="$(CT_Mirrors GNU gcc/gcc-${CT_GCC_VERSION}) $(CT_Mirrors sourceware gcc/releases/gcc-${CT_GCC_VERSION})" +CT_GCC_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GCC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GCC_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_GCC_SIGNATURE_FORMAT="" +CT_GCC_later_than_7=y +CT_GCC_7_or_later=y +CT_GCC_later_than_6=y +CT_GCC_6_or_later=y +CT_GCC_later_than_5=y +CT_GCC_5_or_later=y +CT_GCC_later_than_4_9=y +CT_GCC_4_9_or_later=y +CT_GCC_later_than_4_8=y +CT_GCC_4_8_or_later=y +CT_CC_GCC_HAS_LIBMPX=y CT_CC_GCC_ENABLE_CXX_FLAGS="" CT_CC_GCC_CORE_EXTRA_CONFIG_ARRAY="" CT_CC_GCC_EXTRA_CONFIG_ARRAY="" -CT_CC_GCC_EXTRA_ENV_ARRAY="" CT_CC_GCC_STATIC_LIBSTDCXX=y # CT_CC_GCC_SYSTEM_ZLIB is not set +CT_CC_GCC_CONFIG_TLS=m # # Optimisation features # +CT_CC_GCC_USE_GRAPHITE=y +CT_CC_GCC_USE_LTO=y # # Settings for libraries running on target @@ -465,97 +543,206 @@ CT_CC_GCC_DEC_FLOAT_AUTO=y # CT_CC_GCC_DEC_FLOAT_BID is not set # CT_CC_GCC_DEC_FLOAT_DPD is not set # CT_CC_GCC_DEC_FLOATS_NO is not set -CT_CC_SUPPORT_CXX=y -CT_CC_SUPPORT_FORTRAN=y -CT_CC_SUPPORT_JAVA=y -CT_CC_SUPPORT_ADA=y -CT_CC_SUPPORT_OBJC=y -CT_CC_SUPPORT_OBJCXX=y -CT_CC_SUPPORT_GOLANG=y +CT_ALL_CC_CHOICES="GCC" # # Additional supported languages: # CT_CC_LANG_CXX=y -# CT_CC_LANG_JAVA is not set +# CT_CC_LANG_FORTRAN is not set # # Debug facilities # -# CT_DEBUG_dmalloc is not set -# CT_DEBUG_duma is not set -# CT_DEBUG_gdb is not set -# CT_DEBUG_ltrace is not set -# CT_DEBUG_strace is not set +# CT_DEBUG_DUMA is not set +# CT_DEBUG_GDB is not set +# CT_DEBUG_LTRACE is not set +# CT_DEBUG_STRACE is not set +CT_ALL_DEBUG_CHOICES="DUMA GDB LTRACE STRACE" # # Companion libraries # -CT_COMPLIBS_NEEDED=y +# CT_COMPLIBS_CHECK is not set +# CT_COMP_LIBS_CLOOG is not set +# CT_COMP_LIBS_EXPAT is not set +CT_COMP_LIBS_GETTEXT=y +CT_COMP_LIBS_GETTEXT_PKG_KSYM="GETTEXT" +CT_GETTEXT_DIR_NAME="gettext" +CT_GETTEXT_PKG_NAME="gettext" +CT_GETTEXT_SRC_RELEASE=y +CT_GETTEXT_PATCH_ORDER="global" +CT_GETTEXT_V_0_19_8_1=y +# CT_GETTEXT_NO_VERSIONS is not set +CT_GETTEXT_VERSION="0.19.8.1" +CT_GETTEXT_MIRRORS="$(CT_Mirrors GNU gettext)" +CT_GETTEXT_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GETTEXT_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GETTEXT_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.gz" +CT_GETTEXT_SIGNATURE_FORMAT="packed/.sig" +CT_COMP_LIBS_GMP=y +CT_COMP_LIBS_GMP_PKG_KSYM="GMP" +CT_GMP_DIR_NAME="gmp" +CT_GMP_PKG_NAME="gmp" +CT_GMP_SRC_RELEASE=y +CT_GMP_PATCH_ORDER="global" +CT_GMP_V_6_1=y +# CT_GMP_NO_VERSIONS is not set +CT_GMP_VERSION="6.1.2" +CT_GMP_MIRRORS="https://gmplib.org/download/gmp https://gmplib.org/download/gmp/archive $(CT_Mirrors GNU gmp)" +CT_GMP_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_GMP_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_GMP_ARCHIVE_FORMATS=".tar.xz .tar.lz .tar.bz2" +CT_GMP_SIGNATURE_FORMAT="packed/.sig" +CT_GMP_later_than_5_1_0=y +CT_GMP_5_1_0_or_later=y +CT_GMP_later_than_5_0_0=y +CT_GMP_5_0_0_or_later=y +CT_COMP_LIBS_ISL=y +CT_COMP_LIBS_ISL_PKG_KSYM="ISL" +CT_ISL_DIR_NAME="isl" +CT_ISL_PKG_NAME="isl" +CT_ISL_SRC_RELEASE=y +CT_ISL_PATCH_ORDER="global" +CT_ISL_V_0_20=y +# CT_ISL_V_0_19 is not set +# CT_ISL_V_0_18 is not set +# CT_ISL_V_0_17 is not set +# CT_ISL_V_0_16 is not set +# CT_ISL_V_0_15 is not set +# CT_ISL_NO_VERSIONS is not set +CT_ISL_VERSION="0.20" +CT_ISL_MIRRORS="http://isl.gforge.inria.fr" +CT_ISL_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_ISL_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_ISL_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz" +CT_ISL_SIGNATURE_FORMAT="" +CT_ISL_later_than_0_18=y +CT_ISL_0_18_or_later=y +CT_ISL_later_than_0_15=y +CT_ISL_0_15_or_later=y +CT_ISL_REQUIRE_0_15_or_later=y +CT_ISL_later_than_0_14=y +CT_ISL_0_14_or_later=y +CT_ISL_REQUIRE_0_14_or_later=y +CT_ISL_later_than_0_13=y +CT_ISL_0_13_or_later=y +CT_ISL_later_than_0_12=y +CT_ISL_0_12_or_later=y +CT_ISL_REQUIRE_0_12_or_later=y +# CT_COMP_LIBS_LIBELF is not set +CT_COMP_LIBS_LIBICONV=y +CT_COMP_LIBS_LIBICONV_PKG_KSYM="LIBICONV" +CT_LIBICONV_DIR_NAME="libiconv" +CT_LIBICONV_PKG_NAME="libiconv" +CT_LIBICONV_SRC_RELEASE=y +CT_LIBICONV_PATCH_ORDER="global" +CT_LIBICONV_V_1_15=y +# CT_LIBICONV_NO_VERSIONS is not set +CT_LIBICONV_VERSION="1.15" +CT_LIBICONV_MIRRORS="$(CT_Mirrors GNU libiconv)" +CT_LIBICONV_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_LIBICONV_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_LIBICONV_ARCHIVE_FORMATS=".tar.gz" +CT_LIBICONV_SIGNATURE_FORMAT="packed/.sig" +CT_COMP_LIBS_MPC=y +CT_COMP_LIBS_MPC_PKG_KSYM="MPC" +CT_MPC_DIR_NAME="mpc" +CT_MPC_PKG_NAME="mpc" +CT_MPC_SRC_RELEASE=y +CT_MPC_PATCH_ORDER="global" +# CT_MPC_V_1_1 is not set +CT_MPC_V_1_0=y +# CT_MPC_NO_VERSIONS is not set +CT_MPC_VERSION="1.0.3" +CT_MPC_MIRRORS="http://www.multiprecision.org/downloads $(CT_Mirrors GNU mpc)" +CT_MPC_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_MPC_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_MPC_ARCHIVE_FORMATS=".tar.gz" +CT_MPC_SIGNATURE_FORMAT="packed/.sig" +CT_MPC_1_1_0_or_older=y +CT_MPC_older_than_1_1_0=y +CT_COMP_LIBS_MPFR=y +CT_COMP_LIBS_MPFR_PKG_KSYM="MPFR" +CT_MPFR_DIR_NAME="mpfr" +CT_MPFR_PKG_NAME="mpfr" +CT_MPFR_SRC_RELEASE=y +CT_MPFR_PATCH_ORDER="global" +CT_MPFR_V_3_1=y +# CT_MPFR_NO_VERSIONS is not set +CT_MPFR_VERSION="3.1.6" +CT_MPFR_MIRRORS="http://www.mpfr.org/mpfr-${CT_MPFR_VERSION} $(CT_Mirrors GNU mpfr)" +CT_MPFR_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_MPFR_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_MPFR_ARCHIVE_FORMATS=".tar.xz .tar.bz2 .tar.gz .zip" +CT_MPFR_SIGNATURE_FORMAT="packed/.asc" +CT_MPFR_4_0_0_or_older=y +CT_MPFR_older_than_4_0_0=y +CT_MPFR_REQUIRE_older_than_4_0_0=y +CT_MPFR_later_than_3_0_0=y +CT_MPFR_3_0_0_or_later=y +CT_COMP_LIBS_NCURSES=y +CT_COMP_LIBS_NCURSES_PKG_KSYM="NCURSES" +CT_NCURSES_DIR_NAME="ncurses" +CT_NCURSES_PKG_NAME="ncurses" +CT_NCURSES_SRC_RELEASE=y +CT_NCURSES_PATCH_ORDER="global" +CT_NCURSES_V_6_1=y +# CT_NCURSES_V_6_0 is not set +# CT_NCURSES_NO_VERSIONS is not set +CT_NCURSES_VERSION="6.1" +CT_NCURSES_MIRRORS="ftp://invisible-island.net/ncurses $(CT_Mirrors GNU ncurses)" +CT_NCURSES_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_NCURSES_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_NCURSES_ARCHIVE_FORMATS=".tar.gz" +CT_NCURSES_SIGNATURE_FORMAT="packed/.sig" +CT_NCURSES_HOST_CONFIG_ARGS="" +CT_NCURSES_HOST_DISABLE_DB=y +CT_NCURSES_HOST_FALLBACKS="linux,xterm,xterm-color,xterm-256color,vt100" +CT_NCURSES_TARGET_CONFIG_ARGS="" +# CT_NCURSES_TARGET_DISABLE_DB is not set +CT_NCURSES_TARGET_FALLBACKS="" +CT_COMP_LIBS_ZLIB=y +CT_COMP_LIBS_ZLIB_PKG_KSYM="ZLIB" +CT_ZLIB_DIR_NAME="zlib" +CT_ZLIB_PKG_NAME="zlib" +CT_ZLIB_SRC_RELEASE=y +CT_ZLIB_PATCH_ORDER="global" +CT_ZLIB_V_1_2_11=y +# CT_ZLIB_NO_VERSIONS is not set +CT_ZLIB_VERSION="1.2.11" +CT_ZLIB_MIRRORS="http://downloads.sourceforge.net/project/libpng/zlib/${CT_ZLIB_VERSION}" +CT_ZLIB_ARCHIVE_FILENAME="@{pkg_name}-@{version}" +CT_ZLIB_ARCHIVE_DIRNAME="@{pkg_name}-@{version}" +CT_ZLIB_ARCHIVE_FORMATS=".tar.xz .tar.gz" +CT_ZLIB_SIGNATURE_FORMAT="packed/.asc" +CT_ALL_COMP_LIBS_CHOICES="CLOOG EXPAT GETTEXT GMP ISL LIBELF LIBICONV MPC MPFR NCURSES ZLIB" CT_LIBICONV_NEEDED=y CT_GETTEXT_NEEDED=y CT_GMP_NEEDED=y CT_MPFR_NEEDED=y CT_ISL_NEEDED=y CT_MPC_NEEDED=y -CT_COMPLIBS=y +CT_NCURSES_NEEDED=y +CT_ZLIB_NEEDED=y CT_LIBICONV=y CT_GETTEXT=y CT_GMP=y CT_MPFR=y CT_ISL=y CT_MPC=y -CT_LIBICONV_V_1_14=y -CT_LIBICONV_VERSION="1.14" -CT_GETTEXT_V_0_19_6=y -CT_GETTEXT_VERSION="0.19.6" -CT_GMP_V_6_0_0=y -# CT_GMP_V_5_1_3 is not set -# CT_GMP_V_5_1_1 is not set -# CT_GMP_V_5_0_2 is not set -# CT_GMP_V_5_0_1 is not set -# CT_GMP_V_4_3_2 is not set -# CT_GMP_V_4_3_1 is not set -# CT_GMP_V_4_3_0 is not set -CT_GMP_5_0_2_or_later=y -CT_GMP_VERSION="6.0.0a" -CT_MPFR_V_3_1_3=y -# CT_MPFR_V_3_1_2 is not set -# CT_MPFR_V_3_1_0 is not set -# CT_MPFR_V_3_0_1 is not set -# CT_MPFR_V_3_0_0 is not set -# CT_MPFR_V_2_4_2 is not set -# CT_MPFR_V_2_4_1 is not set -# CT_MPFR_V_2_4_0 is not set -CT_MPFR_VERSION="3.1.3" -CT_ISL_V_0_14=y -# CT_ISL_V_0_12_2 is not set -CT_ISL_V_0_14_or_later=y -CT_ISL_V_0_12_or_later=y -CT_ISL_VERSION="0.14" -# CT_CLOOG_V_0_18_4 is not set -# CT_CLOOG_V_0_18_1 is not set -# CT_CLOOG_V_0_18_0 is not set -CT_MPC_V_1_0_3=y -# CT_MPC_V_1_0_2 is not set -# CT_MPC_V_1_0_1 is not set -# CT_MPC_V_1_0 is not set -# CT_MPC_V_0_9 is not set -# CT_MPC_V_0_8_2 is not set -# CT_MPC_V_0_8_1 is not set -# CT_MPC_V_0_7 is not set -CT_MPC_VERSION="1.0.3" - -# -# Companion libraries common options -# -# CT_COMPLIBS_CHECK is not set +CT_NCURSES=y +CT_ZLIB=y # # Companion tools # - -# -# READ HELP before you say 'Y' below !!! -# -# CT_COMP_TOOLS is not set +# CT_COMP_TOOLS_FOR_HOST is not set +# CT_COMP_TOOLS_AUTOCONF is not set +# CT_COMP_TOOLS_AUTOMAKE is not set +# CT_COMP_TOOLS_BISON is not set +# CT_COMP_TOOLS_DTC is not set +# CT_COMP_TOOLS_LIBTOOL is not set +# CT_COMP_TOOLS_M4 is not set +# CT_COMP_TOOLS_MAKE is not set +CT_ALL_COMP_TOOLS_CHOICES="AUTOCONF AUTOMAKE BISON DTC LIBTOOL M4 MAKE" diff --git a/src/ci/docker/dist-armv7-linux/crosstool-ng.sh b/src/ci/docker/dist-armv7-linux/crosstool-ng.sh new file mode 100644 index 000000000000..47ce88868ae1 --- /dev/null +++ b/src/ci/docker/dist-armv7-linux/crosstool-ng.sh @@ -0,0 +1,11 @@ +set -ex + +url="https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz" +curl -Lf $url | tar xzf - +cd crosstool-ng-crosstool-ng-1.24.0 +./bootstrap +./configure --prefix=/usr/local +make -j$(nproc) +make install +cd .. +rm -rf crosstool-ng-crosstool-ng-1.24.0 diff --git a/src/ci/docker/dist-armv7-linux/patches/glibc/ports-2.16.0/001-arm-libgcc_s_resume-used.patch b/src/ci/docker/dist-armv7-linux/patches/glibc/ports-2.16.0/001-arm-libgcc_s_resume-used.patch deleted file mode 100644 index 871d5225c0f7..000000000000 --- a/src/ci/docker/dist-armv7-linux/patches/glibc/ports-2.16.0/001-arm-libgcc_s_resume-used.patch +++ /dev/null @@ -1,48 +0,0 @@ -commit bdb24c2851fd5f0ad9b82d7ea1db911d334b02d2 -Author: Joseph Myers -Date: Tue May 20 21:27:13 2014 +0000 - - Fix ARM build with GCC trunk. - - sysdeps/unix/sysv/linux/arm/unwind-resume.c and - sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c have static - variables that are written in C code but only read from toplevel asms. - Current GCC trunk now optimizes away such apparently write-only static - variables, so causing a build failure. This patch marks those - variables with __attribute_used__ to avoid that optimization. - - Tested that this fixes the build for ARM. - - * sysdeps/unix/sysv/linux/arm/unwind-forcedunwind.c - (libgcc_s_resume): Use __attribute_used__. - * sysdeps/unix/sysv/linux/arm/unwind-resume.c (libgcc_s_resume): - Likewise. - -diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c -index 29e2c2b00b04..e848bfeffdcb 100644 ---- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c -+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-forcedunwind.c -@@ -22,7 +22,8 @@ - #include - - static void *libgcc_s_handle; --static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); -+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc) -+ __attribute_used__; - static _Unwind_Reason_Code (*libgcc_s_personality) - (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); - static _Unwind_Reason_Code (*libgcc_s_forcedunwind) -diff --git a/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c b/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c -index 285b99b5ed0d..48d00fc83641 100644 ---- a/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c -+++ b/ports/sysdeps/unix/sysv/linux/arm/nptl/unwind-resume.c -@@ -20,7 +20,8 @@ - #include - #include - --static void (*libgcc_s_resume) (struct _Unwind_Exception *exc); -+static void (*libgcc_s_resume) (struct _Unwind_Exception *exc) -+ __attribute_used__; - static _Unwind_Reason_Code (*libgcc_s_personality) - (_Unwind_State, struct _Unwind_Exception *, struct _Unwind_Context *); - From 4f97e5d41160e256c9d76d26432831ece83ef480 Mon Sep 17 00:00:00 2001 From: qtmlabs Date: Fri, 11 Oct 2019 15:32:01 +0700 Subject: [PATCH 266/545] Remove reference to Ubuntu 15.10 ARM toolchain --- src/ci/docker/README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index a2d83eca24b0..8fbf512af3cd 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -169,17 +169,15 @@ For targets: `armv7-unknown-linux-gnueabihf` - Target options > Target Architecture = arm - Target options > Suffix to the arch-part = v7 - Target options > Architecture level = armv7-a -- (+) -- Target options > Use specific FPU = vfpv3-d16 -- (\*) -- Target options > Floating point = hardware (FPU) -- (\*) -- Target options > Default instruction set mode = thumb -- (\*) +- Target options > Use specific FPU = vfpv3-d16 +- Target options > Floating point = hardware (FPU) +- Target options > Default instruction set mode = thumb - Operating System > Target OS = linux - Operating System > Linux kernel version = 3.2.101 - C-library > glibc version = 2.17.0 - C compiler > gcc version = 8.3.0 - C compiler > C++ = ENABLE -- to cross compile LLVM -(\*) These options have been selected to match the configuration of the arm - toolchains shipped with Ubuntu 15.10 (+) These options have been selected to match the gcc flags we use to compile C libraries like jemalloc. See the mk/cfg/arm(v7)-uknown-linux-gnueabi{,hf}.mk file in Rust's source code. From e2ce082fd83a13a7cd989906950d618fa3e2b296 Mon Sep 17 00:00:00 2001 From: qtmlabs Date: Fri, 11 Oct 2019 16:05:17 +0700 Subject: [PATCH 267/545] Revert "Remove reference to Ubuntu 15.10 ARM toolchain" This reverts commit 4f97e5d41160e256c9d76d26432831ece83ef480. --- src/ci/docker/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 8fbf512af3cd..a2d83eca24b0 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -169,15 +169,17 @@ For targets: `armv7-unknown-linux-gnueabihf` - Target options > Target Architecture = arm - Target options > Suffix to the arch-part = v7 - Target options > Architecture level = armv7-a -- (+) -- Target options > Use specific FPU = vfpv3-d16 -- Target options > Floating point = hardware (FPU) -- Target options > Default instruction set mode = thumb +- Target options > Use specific FPU = vfpv3-d16 -- (\*) +- Target options > Floating point = hardware (FPU) -- (\*) +- Target options > Default instruction set mode = thumb -- (\*) - Operating System > Target OS = linux - Operating System > Linux kernel version = 3.2.101 - C-library > glibc version = 2.17.0 - C compiler > gcc version = 8.3.0 - C compiler > C++ = ENABLE -- to cross compile LLVM +(\*) These options have been selected to match the configuration of the arm + toolchains shipped with Ubuntu 15.10 (+) These options have been selected to match the gcc flags we use to compile C libraries like jemalloc. See the mk/cfg/arm(v7)-uknown-linux-gnueabi{,hf}.mk file in Rust's source code. From 028f53e38e5830897693ea3644c672a096cfa0ec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 11 Oct 2019 14:58:05 +0200 Subject: [PATCH 268/545] emcscripten: ignore another thread-using test --- .../issue-64655-allow-unwind-when-calling-panic-directly.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs index c941d36479e5..ff10d412a110 100644 --- a/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +++ b/src/test/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs @@ -1,5 +1,6 @@ // run-pass // ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten no threads support // rust-lang/rust#64655: with panic=unwind, a panic from a subroutine // should still run destructors as it unwinds the stack. However, From a32aec021eee20ad27c232bdacb5c4ac6af7808a Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Fri, 11 Oct 2019 15:14:23 +0300 Subject: [PATCH 269/545] deriving: avoid dummy Span on an artificial `type_ident` path The dummy Span pointed to the beginning of the source file instead to where the `#[derive]` is located. Later, it tripped the `in_derive_expansion(span)` check at `src/librustc/middle/stability.rs`, causing a span-less deprecation warning to be emitted. Fixes #56195, #55417. --- src/libsyntax_ext/deriving/generic/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 9f75f72e820f..abdcb6c8e3d3 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -192,7 +192,7 @@ use syntax::util::map_in_place::MapInPlace; use syntax::ptr::P; use syntax::symbol::{Symbol, kw, sym}; use syntax::parse::ParseSess; -use syntax_pos::{DUMMY_SP, Span}; +use syntax_pos::{Span}; use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty}; @@ -1022,7 +1022,7 @@ impl<'a> MethodDef<'a> { // [fields of next Self arg], [etc]> let mut patterns = Vec::new(); for i in 0..self_args.len() { - let struct_path = cx.path(DUMMY_SP, vec![type_ident]); + let struct_path = cx.path(trait_.span, vec![type_ident]); let (pat, ident_expr) = trait_.create_struct_pattern(cx, struct_path, struct_def, From e285175b63626bf930b90b27ba78b35842d0da2f Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Fri, 11 Oct 2019 16:20:04 +0300 Subject: [PATCH 270/545] test: extend derive_on_deprecated to include more derivations --- src/test/ui/deprecation/derive_on_deprecated.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/test/ui/deprecation/derive_on_deprecated.rs b/src/test/ui/deprecation/derive_on_deprecated.rs index ed4055ecdd38..ac771ac81d11 100644 --- a/src/test/ui/deprecation/derive_on_deprecated.rs +++ b/src/test/ui/deprecation/derive_on_deprecated.rs @@ -6,4 +6,10 @@ #[derive(Default)] struct X; +#[deprecated(note="Do not use this")] +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] +pub struct Step { + _skip: Option, +} + fn main() {} From d92cef74736aa4503e37ee67806ce5ab3a4eb97a Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Fri, 11 Oct 2019 07:44:01 -0700 Subject: [PATCH 271/545] resolve_for_fn_ptr checks that the instance is an Item before returning shim. --- src/librustc/ty/instance.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 0a86b0b41480..5139c8085a58 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -311,16 +311,18 @@ impl<'tcx> Instance<'tcx> { ) -> Option> { debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); Instance::resolve(tcx, param_env, def_id, substs).map(|resolved| { - let resolved_def = resolved.def_id(); - let codegen_attrs = tcx.codegen_fn_attrs(resolved_def); - if codegen_attrs.flags.contains(CodegenFnAttrFlags::TRACK_CALLER) { - debug!(" => fn pointer created for function with #[track_caller]"); - Instance { - def: InstanceDef::ReifyShim(resolved_def), - substs, - } - } else { - resolved + let has_track_caller = |def| tcx.codegen_fn_attrs(def).flags + .contains(CodegenFnAttrFlags::TRACK_CALLER); + + match resolved.def { + InstanceDef::Item(def_id) if has_track_caller(def_id) => { + debug!(" => fn pointer created for function with #[track_caller]"); + Instance { + def: InstanceDef::ReifyShim(def_id), + substs, + } + }, + _ => resolved, } }) } From 2d5ef8f9ff091aa6e2758958745cc3edfa84f937 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Fri, 11 Oct 2019 07:45:59 -0700 Subject: [PATCH 272/545] Clarify comment about purpose of ReifyShim. --- src/librustc_mir/shim.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index c4d66ee7dbd7..f532a18072fb 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -69,8 +69,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx // We are generating a call back to our def-id, which the // codegen backend knows to turn to an actual virtual call. ty::InstanceDef::Virtual(def_id, _) | - // ...or we are generating a direct call to our #[track_caller] function which - // requires an implicit caller location that the virtual call won't pass + // ...or we are generating a direct call to a function for which indirect calls must be + // codegen'd differently than direct ones (example: #[track_caller]) ty::InstanceDef::ReifyShim(def_id) => { build_call_shim( tcx, From 7140c024c27c511ca382a361edac99a1116130b7 Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Fri, 11 Oct 2019 17:38:20 +0300 Subject: [PATCH 273/545] resolve: fix error title regarding private constructors The constructor is private, not the type. Idea credit to @petrochenkov, discussed at #65153 --- src/librustc_resolve/lib.rs | 32 ++++-- src/test/ui/privacy/privacy5.rs | 96 ++++++++-------- src/test/ui/privacy/privacy5.stderr | 104 +++++++++--------- src/test/ui/resolve/privacy-struct-ctor.rs | 12 +- .../ui/resolve/privacy-struct-ctor.stderr | 12 +- src/test/ui/rfc-2008-non-exhaustive/struct.rs | 2 +- .../ui/rfc-2008-non-exhaustive/struct.stderr | 2 +- 7 files changed, 136 insertions(+), 124 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ce4126b511df..b7c24a2f36ae 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2379,26 +2379,38 @@ impl<'a> Resolver<'a> { let mut reported_spans = FxHashSet::default(); for &PrivacyError(dedup_span, ident, binding) in &self.privacy_errors { if reported_spans.insert(dedup_span) { - let mut err = struct_span_err!( - self.session, - ident.span, - E0603, - "{} `{}` is private", - binding.res().descr(), - ident.name, - ); - if let NameBindingKind::Res( + let session = &self.session; + let mk_struct_span_error = |is_constructor| { + struct_span_err!( + session, + ident.span, + E0603, + "{}{} `{}` is private", + binding.res().descr(), + if is_constructor { " constructor"} else { "" }, + ident.name, + ) + }; + + let mut err = if let NameBindingKind::Res( Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id), _ ) = binding.kind { let def_id = (&*self).parent(ctor_def_id).expect("no parent for a constructor"); if let Some(fields) = self.field_names.get(&def_id) { + let mut err = mk_struct_span_error(true); let first_field = fields.first().expect("empty field list in the map"); err.span_label( fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)), "a tuple struct constructor is private if any of its fields is private", ); + err + } else { + mk_struct_span_error(false) } - } + } else { + mk_struct_span_error(false) + }; + err.emit(); } } diff --git a/src/test/ui/privacy/privacy5.rs b/src/test/ui/privacy/privacy5.rs index 741ba0be2c2b..3dc26b1955cd 100644 --- a/src/test/ui/privacy/privacy5.rs +++ b/src/test/ui/privacy/privacy5.rs @@ -48,31 +48,31 @@ mod a { } fn this_crate() { - let a = a::A(()); //~ ERROR tuple struct `A` is private - let b = a::B(2); //~ ERROR tuple struct `B` is private - let c = a::C(2, 3); //~ ERROR tuple struct `C` is private + let a = a::A(()); //~ ERROR tuple struct constructor `A` is private + let b = a::B(2); //~ ERROR tuple struct constructor `B` is private + let c = a::C(2, 3); //~ ERROR tuple struct constructor `C` is private let d = a::D(4); - let a::A(()) = a; //~ ERROR tuple struct `A` is private - let a::A(_) = a; //~ ERROR tuple struct `A` is private - match a { a::A(()) => {} } //~ ERROR tuple struct `A` is private - match a { a::A(_) => {} } //~ ERROR tuple struct `A` is private + let a::A(()) = a; //~ ERROR tuple struct constructor `A` is private + let a::A(_) = a; //~ ERROR tuple struct constructor `A` is private + match a { a::A(()) => {} } //~ ERROR tuple struct constructor `A` is private + match a { a::A(_) => {} } //~ ERROR tuple struct constructor `A` is private - let a::B(_) = b; //~ ERROR tuple struct `B` is private - let a::B(_b) = b; //~ ERROR tuple struct `B` is private - match b { a::B(_) => {} } //~ ERROR tuple struct `B` is private - match b { a::B(_b) => {} } //~ ERROR tuple struct `B` is private - match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct `B` is private - //~^ ERROR tuple struct `B` is private + let a::B(_) = b; //~ ERROR tuple struct constructor `B` is private + let a::B(_b) = b; //~ ERROR tuple struct constructor `B` is private + match b { a::B(_) => {} } //~ ERROR tuple struct constructor `B` is private + match b { a::B(_b) => {} } //~ ERROR tuple struct constructor `B` is private + match b { a::B(1) => {} a::B(_) => {} } //~ ERROR tuple struct constructor `B` is private + //~^ ERROR tuple struct constructor `B` is private - let a::C(_, _) = c; //~ ERROR tuple struct `C` is private - let a::C(_a, _) = c; //~ ERROR tuple struct `C` is private - let a::C(_, _b) = c; //~ ERROR tuple struct `C` is private - let a::C(_a, _b) = c; //~ ERROR tuple struct `C` is private - match c { a::C(_, _) => {} } //~ ERROR tuple struct `C` is private - match c { a::C(_a, _) => {} } //~ ERROR tuple struct `C` is private - match c { a::C(_, _b) => {} } //~ ERROR tuple struct `C` is private - match c { a::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private + let a::C(_, _) = c; //~ ERROR tuple struct constructor `C` is private + let a::C(_a, _) = c; //~ ERROR tuple struct constructor `C` is private + let a::C(_, _b) = c; //~ ERROR tuple struct constructor `C` is private + let a::C(_a, _b) = c; //~ ERROR tuple struct constructor `C` is private + match c { a::C(_, _) => {} } //~ ERROR tuple struct constructor `C` is private + match c { a::C(_a, _) => {} } //~ ERROR tuple struct constructor `C` is private + match c { a::C(_, _b) => {} } //~ ERROR tuple struct constructor `C` is private + match c { a::C(_a, _b) => {} } //~ ERROR tuple struct constructor `C` is private let a::D(_) = d; let a::D(_d) = d; @@ -80,38 +80,38 @@ fn this_crate() { match d { a::D(_d) => {} } match d { a::D(1) => {} a::D(_) => {} } - let a2 = a::A; //~ ERROR tuple struct `A` is private - let b2 = a::B; //~ ERROR tuple struct `B` is private - let c2 = a::C; //~ ERROR tuple struct `C` is private + let a2 = a::A; //~ ERROR tuple struct constructor `A` is private + let b2 = a::B; //~ ERROR tuple struct constructor `B` is private + let c2 = a::C; //~ ERROR tuple struct constructor `C` is private let d2 = a::D; } fn xcrate() { - let a = other::A(()); //~ ERROR tuple struct `A` is private - let b = other::B(2); //~ ERROR tuple struct `B` is private - let c = other::C(2, 3); //~ ERROR tuple struct `C` is private + let a = other::A(()); //~ ERROR tuple struct constructor `A` is private + let b = other::B(2); //~ ERROR tuple struct constructor `B` is private + let c = other::C(2, 3); //~ ERROR tuple struct constructor `C` is private let d = other::D(4); - let other::A(()) = a; //~ ERROR tuple struct `A` is private - let other::A(_) = a; //~ ERROR tuple struct `A` is private - match a { other::A(()) => {} } //~ ERROR tuple struct `A` is private - match a { other::A(_) => {} } //~ ERROR tuple struct `A` is private + let other::A(()) = a; //~ ERROR tuple struct constructor `A` is private + let other::A(_) = a; //~ ERROR tuple struct constructor `A` is private + match a { other::A(()) => {} } //~ ERROR tuple struct constructor `A` is private + match a { other::A(_) => {} } //~ ERROR tuple struct constructor `A` is private - let other::B(_) = b; //~ ERROR tuple struct `B` is private - let other::B(_b) = b; //~ ERROR tuple struct `B` is private - match b { other::B(_) => {} } //~ ERROR tuple struct `B` is private - match b { other::B(_b) => {} } //~ ERROR tuple struct `B` is private - match b { other::B(1) => {} other::B(_) => {} } //~ ERROR tuple struct `B` is private - //~^ ERROR tuple struct `B` is private + let other::B(_) = b; //~ ERROR tuple struct constructor `B` is private + let other::B(_b) = b; //~ ERROR tuple struct constructor `B` is private + match b { other::B(_) => {} } //~ ERROR tuple struct constructor `B` is private + match b { other::B(_b) => {} } //~ ERROR tuple struct constructor `B` is private + match b { other::B(1) => {}//~ ERROR tuple struct constructor `B` is private + other::B(_) => {} } //~ ERROR tuple struct constructor `B` is private - let other::C(_, _) = c; //~ ERROR tuple struct `C` is private - let other::C(_a, _) = c; //~ ERROR tuple struct `C` is private - let other::C(_, _b) = c; //~ ERROR tuple struct `C` is private - let other::C(_a, _b) = c; //~ ERROR tuple struct `C` is private - match c { other::C(_, _) => {} } //~ ERROR tuple struct `C` is private - match c { other::C(_a, _) => {} } //~ ERROR tuple struct `C` is private - match c { other::C(_, _b) => {} } //~ ERROR tuple struct `C` is private - match c { other::C(_a, _b) => {} } //~ ERROR tuple struct `C` is private + let other::C(_, _) = c; //~ ERROR tuple struct constructor `C` is private + let other::C(_a, _) = c; //~ ERROR tuple struct constructor `C` is private + let other::C(_, _b) = c; //~ ERROR tuple struct constructor `C` is private + let other::C(_a, _b) = c; //~ ERROR tuple struct constructor `C` is private + match c { other::C(_, _) => {} } //~ ERROR tuple struct constructor `C` is private + match c { other::C(_a, _) => {} } //~ ERROR tuple struct constructor `C` is private + match c { other::C(_, _b) => {} } //~ ERROR tuple struct constructor `C` is private + match c { other::C(_a, _b) => {} } //~ ERROR tuple struct constructor `C` is private let other::D(_) = d; let other::D(_d) = d; @@ -119,9 +119,9 @@ fn xcrate() { match d { other::D(_d) => {} } match d { other::D(1) => {} other::D(_) => {} } - let a2 = other::A; //~ ERROR tuple struct `A` is private - let b2 = other::B; //~ ERROR tuple struct `B` is private - let c2 = other::C; //~ ERROR tuple struct `C` is private + let a2 = other::A; //~ ERROR tuple struct constructor `A` is private + let b2 = other::B; //~ ERROR tuple struct constructor `B` is private + let c2 = other::C; //~ ERROR tuple struct constructor `C` is private let d2 = other::D; } diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr index c1b90d7c6bf2..23e7536444b5 100644 --- a/src/test/ui/privacy/privacy5.stderr +++ b/src/test/ui/privacy/privacy5.stderr @@ -1,4 +1,4 @@ -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:51:16 | LL | pub struct A(()); @@ -7,7 +7,7 @@ LL | pub struct A(()); LL | let a = a::A(()); | ^ -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:52:16 | LL | pub struct B(isize); @@ -16,7 +16,7 @@ LL | pub struct B(isize); LL | let b = a::B(2); | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:53:16 | LL | pub struct C(pub isize, isize); @@ -25,7 +25,7 @@ LL | pub struct C(pub isize, isize); LL | let c = a::C(2, 3); | ^ -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:56:12 | LL | pub struct A(()); @@ -34,7 +34,7 @@ LL | pub struct A(()); LL | let a::A(()) = a; | ^ -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:57:12 | LL | pub struct A(()); @@ -43,7 +43,7 @@ LL | pub struct A(()); LL | let a::A(_) = a; | ^ -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:58:18 | LL | pub struct A(()); @@ -52,7 +52,7 @@ LL | pub struct A(()); LL | match a { a::A(()) => {} } | ^ -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:59:18 | LL | pub struct A(()); @@ -61,7 +61,7 @@ LL | pub struct A(()); LL | match a { a::A(_) => {} } | ^ -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:61:12 | LL | pub struct B(isize); @@ -70,7 +70,7 @@ LL | pub struct B(isize); LL | let a::B(_) = b; | ^ -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:62:12 | LL | pub struct B(isize); @@ -79,7 +79,7 @@ LL | pub struct B(isize); LL | let a::B(_b) = b; | ^ -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:63:18 | LL | pub struct B(isize); @@ -88,7 +88,7 @@ LL | pub struct B(isize); LL | match b { a::B(_) => {} } | ^ -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:64:18 | LL | pub struct B(isize); @@ -97,7 +97,7 @@ LL | pub struct B(isize); LL | match b { a::B(_b) => {} } | ^ -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:65:18 | LL | pub struct B(isize); @@ -106,7 +106,7 @@ LL | pub struct B(isize); LL | match b { a::B(1) => {} a::B(_) => {} } | ^ -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:65:32 | LL | pub struct B(isize); @@ -115,7 +115,7 @@ LL | pub struct B(isize); LL | match b { a::B(1) => {} a::B(_) => {} } | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:68:12 | LL | pub struct C(pub isize, isize); @@ -124,7 +124,7 @@ LL | pub struct C(pub isize, isize); LL | let a::C(_, _) = c; | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:69:12 | LL | pub struct C(pub isize, isize); @@ -133,7 +133,7 @@ LL | pub struct C(pub isize, isize); LL | let a::C(_a, _) = c; | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:70:12 | LL | pub struct C(pub isize, isize); @@ -142,7 +142,7 @@ LL | pub struct C(pub isize, isize); LL | let a::C(_, _b) = c; | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:71:12 | LL | pub struct C(pub isize, isize); @@ -151,7 +151,7 @@ LL | pub struct C(pub isize, isize); LL | let a::C(_a, _b) = c; | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:72:18 | LL | pub struct C(pub isize, isize); @@ -160,7 +160,7 @@ LL | pub struct C(pub isize, isize); LL | match c { a::C(_, _) => {} } | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:73:18 | LL | pub struct C(pub isize, isize); @@ -169,7 +169,7 @@ LL | pub struct C(pub isize, isize); LL | match c { a::C(_a, _) => {} } | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:74:18 | LL | pub struct C(pub isize, isize); @@ -178,7 +178,7 @@ LL | pub struct C(pub isize, isize); LL | match c { a::C(_, _b) => {} } | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:75:18 | LL | pub struct C(pub isize, isize); @@ -187,7 +187,7 @@ LL | pub struct C(pub isize, isize); LL | match c { a::C(_a, _b) => {} } | ^ -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:83:17 | LL | pub struct A(()); @@ -196,7 +196,7 @@ LL | pub struct A(()); LL | let a2 = a::A; | ^ -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:84:17 | LL | pub struct B(isize); @@ -205,7 +205,7 @@ LL | pub struct B(isize); LL | let b2 = a::B; | ^ -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:85:17 | LL | pub struct C(pub isize, isize); @@ -214,7 +214,7 @@ LL | pub struct C(pub isize, isize); LL | let c2 = a::C; | ^ -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:90:20 | LL | let a = other::A(()); @@ -225,7 +225,7 @@ LL | let a = other::A(()); LL | pub struct A(()); | -- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:91:20 | LL | let b = other::B(2); @@ -236,7 +236,7 @@ LL | let b = other::B(2); LL | pub struct B(isize); | ----- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:92:20 | LL | let c = other::C(2, 3); @@ -247,7 +247,7 @@ LL | let c = other::C(2, 3); LL | pub struct C(pub isize, isize); | ---------------- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:95:16 | LL | let other::A(()) = a; @@ -258,7 +258,7 @@ LL | let other::A(()) = a; LL | pub struct A(()); | -- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:96:16 | LL | let other::A(_) = a; @@ -269,7 +269,7 @@ LL | let other::A(_) = a; LL | pub struct A(()); | -- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:97:22 | LL | match a { other::A(()) => {} } @@ -280,7 +280,7 @@ LL | match a { other::A(()) => {} } LL | pub struct A(()); | -- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:98:22 | LL | match a { other::A(_) => {} } @@ -291,7 +291,7 @@ LL | match a { other::A(_) => {} } LL | pub struct A(()); | -- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:100:16 | LL | let other::B(_) = b; @@ -302,7 +302,7 @@ LL | let other::B(_) = b; LL | pub struct B(isize); | ----- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:101:16 | LL | let other::B(_b) = b; @@ -313,7 +313,7 @@ LL | let other::B(_b) = b; LL | pub struct B(isize); | ----- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:102:22 | LL | match b { other::B(_) => {} } @@ -324,7 +324,7 @@ LL | match b { other::B(_) => {} } LL | pub struct B(isize); | ----- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:103:22 | LL | match b { other::B(_b) => {} } @@ -335,10 +335,10 @@ LL | match b { other::B(_b) => {} } LL | pub struct B(isize); | ----- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:104:22 | -LL | match b { other::B(1) => {} other::B(_) => {} } +LL | match b { other::B(1) => {} | ^ | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 @@ -346,18 +346,18 @@ LL | match b { other::B(1) => {} other::B(_) => {} } LL | pub struct B(isize); | ----- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `B` is private - --> $DIR/privacy5.rs:104:40 +error[E0603]: tuple struct constructor `B` is private + --> $DIR/privacy5.rs:105:16 | -LL | match b { other::B(1) => {} other::B(_) => {} } - | ^ +LL | other::B(_) => {} } + | ^ | ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | LL | pub struct B(isize); | ----- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:107:16 | LL | let other::C(_, _) = c; @@ -368,7 +368,7 @@ LL | let other::C(_, _) = c; LL | pub struct C(pub isize, isize); | ---------------- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:108:16 | LL | let other::C(_a, _) = c; @@ -379,7 +379,7 @@ LL | let other::C(_a, _) = c; LL | pub struct C(pub isize, isize); | ---------------- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:109:16 | LL | let other::C(_, _b) = c; @@ -390,7 +390,7 @@ LL | let other::C(_, _b) = c; LL | pub struct C(pub isize, isize); | ---------------- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:110:16 | LL | let other::C(_a, _b) = c; @@ -401,7 +401,7 @@ LL | let other::C(_a, _b) = c; LL | pub struct C(pub isize, isize); | ---------------- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:111:22 | LL | match c { other::C(_, _) => {} } @@ -412,7 +412,7 @@ LL | match c { other::C(_, _) => {} } LL | pub struct C(pub isize, isize); | ---------------- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:112:22 | LL | match c { other::C(_a, _) => {} } @@ -423,7 +423,7 @@ LL | match c { other::C(_a, _) => {} } LL | pub struct C(pub isize, isize); | ---------------- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:113:22 | LL | match c { other::C(_, _b) => {} } @@ -434,7 +434,7 @@ LL | match c { other::C(_, _b) => {} } LL | pub struct C(pub isize, isize); | ---------------- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:114:22 | LL | match c { other::C(_a, _b) => {} } @@ -445,7 +445,7 @@ LL | match c { other::C(_a, _b) => {} } LL | pub struct C(pub isize, isize); | ---------------- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `A` is private +error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:122:21 | LL | let a2 = other::A; @@ -456,7 +456,7 @@ LL | let a2 = other::A; LL | pub struct A(()); | -- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `B` is private +error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:123:21 | LL | let b2 = other::B; @@ -467,7 +467,7 @@ LL | let b2 = other::B; LL | pub struct B(isize); | ----- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `C` is private +error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:124:21 | LL | let c2 = other::C; diff --git a/src/test/ui/resolve/privacy-struct-ctor.rs b/src/test/ui/resolve/privacy-struct-ctor.rs index 0b389acf75d8..0eecc7f8cc5d 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.rs +++ b/src/test/ui/resolve/privacy-struct-ctor.rs @@ -16,7 +16,7 @@ mod m { fn f() { n::Z; - //~^ ERROR tuple struct `Z` is private + //~^ ERROR tuple struct constructor `Z` is private Z; //~^ ERROR expected value, found struct `Z` } @@ -27,21 +27,21 @@ use m::S2; // OK, only the type is imported fn main() { m::S; - //~^ ERROR tuple struct `S` is private + //~^ ERROR tuple struct constructor `S` is private let _: S = m::S(2); - //~^ ERROR tuple struct `S` is private + //~^ ERROR tuple struct constructor `S` is private S; //~^ ERROR expected value, found struct `S` m::n::Z; - //~^ ERROR tuple struct `Z` is private + //~^ ERROR tuple struct constructor `Z` is private S2; //~^ ERROR expected value, found struct `S2` xcrate::m::S; - //~^ ERROR tuple struct `S` is private + //~^ ERROR tuple struct constructor `S` is private xcrate::S; //~^ ERROR expected value, found struct `xcrate::S` xcrate::m::n::Z; - //~^ ERROR tuple struct `Z` is private + //~^ ERROR tuple struct constructor `Z` is private } diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index d5311fde2e79..aa988088f70d 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -34,7 +34,7 @@ help: possible better candidate is found in another module, you can import it in LL | use m::S; | -error[E0603]: tuple struct `Z` is private +error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:18:12 | LL | pub(in m) struct Z(pub(in m::n) u8); @@ -43,7 +43,7 @@ LL | pub(in m) struct Z(pub(in m::n) u8); LL | n::Z; | ^ -error[E0603]: tuple struct `S` is private +error[E0603]: tuple struct constructor `S` is private --> $DIR/privacy-struct-ctor.rs:29:8 | LL | pub struct S(u8); @@ -52,7 +52,7 @@ LL | pub struct S(u8); LL | m::S; | ^ -error[E0603]: tuple struct `S` is private +error[E0603]: tuple struct constructor `S` is private --> $DIR/privacy-struct-ctor.rs:31:19 | LL | pub struct S(u8); @@ -61,7 +61,7 @@ LL | pub struct S(u8); LL | let _: S = m::S(2); | ^ -error[E0603]: tuple struct `Z` is private +error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:35:11 | LL | pub(in m) struct Z(pub(in m::n) u8); @@ -70,7 +70,7 @@ LL | pub(in m) struct Z(pub(in m::n) u8); LL | m::n::Z; | ^ -error[E0603]: tuple struct `S` is private +error[E0603]: tuple struct constructor `S` is private --> $DIR/privacy-struct-ctor.rs:41:16 | LL | xcrate::m::S; @@ -81,7 +81,7 @@ LL | xcrate::m::S; LL | pub struct S(u8); | -- a tuple struct constructor is private if any of its fields is private -error[E0603]: tuple struct `Z` is private +error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:45:19 | LL | xcrate::m::n::Z; diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.rs b/src/test/ui/rfc-2008-non-exhaustive/struct.rs index 94ac588d2408..cf383a260e04 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.rs +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.rs @@ -21,7 +21,7 @@ fn main() { //~^ ERROR expected function, found struct `TupleStruct` [E0423] let ts_explicit = structs::TupleStruct(640, 480); - //~^ ERROR tuple struct `TupleStruct` is private [E0603] + //~^ ERROR tuple struct constructor `TupleStruct` is private [E0603] let TupleStruct { 0: first_field, 1: second_field } = ts; //~^ ERROR `..` required with struct marked as non-exhaustive diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index 15f97f7e1d6f..fde9ac27fbfb 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -10,7 +10,7 @@ error[E0423]: expected value, found struct `UnitStruct` LL | let us = UnitStruct; | ^^^^^^^^^^ constructor is not visible here due to private fields -error[E0603]: tuple struct `TupleStruct` is private +error[E0603]: tuple struct constructor `TupleStruct` is private --> $DIR/struct.rs:23:32 | LL | let ts_explicit = structs::TupleStruct(640, 480); From 57aae75ce39de12f1af8d33d2836db59f7269ed2 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Fri, 11 Oct 2019 17:13:19 +0200 Subject: [PATCH 274/545] improve performance of signed saturating_mul Reciprocal throughput is improved from 2.3 to 1.7. https://godbolt.org/z/ROMiX6 --- src/libcore/num/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ebde82de8345..998c8f816520 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1058,7 +1058,7 @@ $EndFeature, " #[inline] pub fn saturating_mul(self, rhs: Self) -> Self { self.checked_mul(rhs).unwrap_or_else(|| { - if (self < 0 && rhs < 0) || (self > 0 && rhs > 0) { + if (self < 0) == (rhs < 0) { Self::max_value() } else { Self::min_value() From 93ae6924af65f38b4998199c0da5ad75acde4466 Mon Sep 17 00:00:00 2001 From: Jack O'Connor Date: Fri, 11 Oct 2019 14:23:25 -0400 Subject: [PATCH 275/545] make File::try_clone produce non-inheritable handles on Windows File handles shouldn't be inheritable in general. `std::process::Command` takes care of making them inheritable when child processes are spawned, and the `CREATE_PROCESS_LOCK` protects against races in that section on Windows. But `File::try_clone` has been creating inheritable file descriptors outside of that lock, which could be leaking into other child processes unintentionally. See also https://github.com/rust-lang/rust/pull/31069#discussion_r334117665. --- src/libstd/sys/windows/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/windows/fs.rs b/src/libstd/sys/windows/fs.rs index 204f6af5fc1a..4160123c9a2a 100644 --- a/src/libstd/sys/windows/fs.rs +++ b/src/libstd/sys/windows/fs.rs @@ -412,7 +412,7 @@ impl File { pub fn duplicate(&self) -> io::Result { Ok(File { - handle: self.handle.duplicate(0, true, c::DUPLICATE_SAME_ACCESS)?, + handle: self.handle.duplicate(0, false, c::DUPLICATE_SAME_ACCESS)?, }) } From 9d11bda8ddffc5f575d04f8ba8037ef581b10ecd Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Fri, 11 Oct 2019 22:00:15 +0300 Subject: [PATCH 276/545] resolve: shorten wording on private constructor error --- src/librustc_resolve/lib.rs | 2 +- src/test/ui/privacy/privacy5.stderr | 96 +++++++++---------- .../ui/resolve/privacy-struct-ctor.stderr | 12 +-- .../ui/rfc-2008-non-exhaustive/struct.stderr | 2 +- 4 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index b7c24a2f36ae..a2346a3f81d5 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2401,7 +2401,7 @@ impl<'a> Resolver<'a> { let first_field = fields.first().expect("empty field list in the map"); err.span_label( fields.iter().fold(first_field.span, |acc, field| acc.to(field.span)), - "a tuple struct constructor is private if any of its fields is private", + "a constructor is private if any of the fields is private", ); err } else { diff --git a/src/test/ui/privacy/privacy5.stderr b/src/test/ui/privacy/privacy5.stderr index 23e7536444b5..2ee83149b695 100644 --- a/src/test/ui/privacy/privacy5.stderr +++ b/src/test/ui/privacy/privacy5.stderr @@ -2,7 +2,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:51:16 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private ... LL | let a = a::A(()); | ^ @@ -11,7 +11,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:52:16 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private ... LL | let b = a::B(2); | ^ @@ -20,7 +20,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:53:16 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | let c = a::C(2, 3); | ^ @@ -29,7 +29,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:56:12 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private ... LL | let a::A(()) = a; | ^ @@ -38,7 +38,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:57:12 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private ... LL | let a::A(_) = a; | ^ @@ -47,7 +47,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:58:18 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private ... LL | match a { a::A(()) => {} } | ^ @@ -56,7 +56,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:59:18 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private ... LL | match a { a::A(_) => {} } | ^ @@ -65,7 +65,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:61:12 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private ... LL | let a::B(_) = b; | ^ @@ -74,7 +74,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:62:12 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private ... LL | let a::B(_b) = b; | ^ @@ -83,7 +83,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:63:18 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private ... LL | match b { a::B(_) => {} } | ^ @@ -92,7 +92,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:64:18 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private ... LL | match b { a::B(_b) => {} } | ^ @@ -101,7 +101,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:65:18 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private ... LL | match b { a::B(1) => {} a::B(_) => {} } | ^ @@ -110,7 +110,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:65:32 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private ... LL | match b { a::B(1) => {} a::B(_) => {} } | ^ @@ -119,7 +119,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:68:12 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | let a::C(_, _) = c; | ^ @@ -128,7 +128,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:69:12 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | let a::C(_a, _) = c; | ^ @@ -137,7 +137,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:70:12 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | let a::C(_, _b) = c; | ^ @@ -146,7 +146,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:71:12 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | let a::C(_a, _b) = c; | ^ @@ -155,7 +155,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:72:18 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | match c { a::C(_, _) => {} } | ^ @@ -164,7 +164,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:73:18 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | match c { a::C(_a, _) => {} } | ^ @@ -173,7 +173,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:74:18 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | match c { a::C(_, _b) => {} } | ^ @@ -182,7 +182,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:75:18 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | match c { a::C(_a, _b) => {} } | ^ @@ -191,7 +191,7 @@ error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:83:17 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private ... LL | let a2 = a::A; | ^ @@ -200,7 +200,7 @@ error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:84:17 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private ... LL | let b2 = a::B; | ^ @@ -209,7 +209,7 @@ error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:85:17 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private ... LL | let c2 = a::C; | ^ @@ -223,7 +223,7 @@ LL | let a = other::A(()); ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:91:20 @@ -234,7 +234,7 @@ LL | let b = other::B(2); ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:92:20 @@ -245,7 +245,7 @@ LL | let c = other::C(2, 3); ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:95:16 @@ -256,7 +256,7 @@ LL | let other::A(()) = a; ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:96:16 @@ -267,7 +267,7 @@ LL | let other::A(_) = a; ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:97:22 @@ -278,7 +278,7 @@ LL | match a { other::A(()) => {} } ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:98:22 @@ -289,7 +289,7 @@ LL | match a { other::A(_) => {} } ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:100:16 @@ -300,7 +300,7 @@ LL | let other::B(_) = b; ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:101:16 @@ -311,7 +311,7 @@ LL | let other::B(_b) = b; ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:102:22 @@ -322,7 +322,7 @@ LL | match b { other::B(_) => {} } ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:103:22 @@ -333,7 +333,7 @@ LL | match b { other::B(_b) => {} } ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:104:22 @@ -344,7 +344,7 @@ LL | match b { other::B(1) => {} ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:105:16 @@ -355,7 +355,7 @@ LL | other::B(_) => {} } ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:107:16 @@ -366,7 +366,7 @@ LL | let other::C(_, _) = c; ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:108:16 @@ -377,7 +377,7 @@ LL | let other::C(_a, _) = c; ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:109:16 @@ -388,7 +388,7 @@ LL | let other::C(_, _b) = c; ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:110:16 @@ -399,7 +399,7 @@ LL | let other::C(_a, _b) = c; ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:111:22 @@ -410,7 +410,7 @@ LL | match c { other::C(_, _) => {} } ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:112:22 @@ -421,7 +421,7 @@ LL | match c { other::C(_a, _) => {} } ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:113:22 @@ -432,7 +432,7 @@ LL | match c { other::C(_, _b) => {} } ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:114:22 @@ -443,7 +443,7 @@ LL | match c { other::C(_a, _b) => {} } ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `A` is private --> $DIR/privacy5.rs:122:21 @@ -454,7 +454,7 @@ LL | let a2 = other::A; ::: $DIR/auxiliary/privacy_tuple_struct.rs:1:14 | LL | pub struct A(()); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `B` is private --> $DIR/privacy5.rs:123:21 @@ -465,7 +465,7 @@ LL | let b2 = other::B; ::: $DIR/auxiliary/privacy_tuple_struct.rs:2:14 | LL | pub struct B(isize); - | ----- a tuple struct constructor is private if any of its fields is private + | ----- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `C` is private --> $DIR/privacy5.rs:124:21 @@ -476,7 +476,7 @@ LL | let c2 = other::C; ::: $DIR/auxiliary/privacy_tuple_struct.rs:3:14 | LL | pub struct C(pub isize, isize); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error: aborting due to 48 previous errors diff --git a/src/test/ui/resolve/privacy-struct-ctor.stderr b/src/test/ui/resolve/privacy-struct-ctor.stderr index aa988088f70d..7d884d3a6691 100644 --- a/src/test/ui/resolve/privacy-struct-ctor.stderr +++ b/src/test/ui/resolve/privacy-struct-ctor.stderr @@ -38,7 +38,7 @@ error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:18:12 | LL | pub(in m) struct Z(pub(in m::n) u8); - | --------------- a tuple struct constructor is private if any of its fields is private + | --------------- a constructor is private if any of the fields is private ... LL | n::Z; | ^ @@ -47,7 +47,7 @@ error[E0603]: tuple struct constructor `S` is private --> $DIR/privacy-struct-ctor.rs:29:8 | LL | pub struct S(u8); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private ... LL | m::S; | ^ @@ -56,7 +56,7 @@ error[E0603]: tuple struct constructor `S` is private --> $DIR/privacy-struct-ctor.rs:31:19 | LL | pub struct S(u8); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private ... LL | let _: S = m::S(2); | ^ @@ -65,7 +65,7 @@ error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:35:11 | LL | pub(in m) struct Z(pub(in m::n) u8); - | --------------- a tuple struct constructor is private if any of its fields is private + | --------------- a constructor is private if any of the fields is private ... LL | m::n::Z; | ^ @@ -79,7 +79,7 @@ LL | xcrate::m::S; ::: $DIR/auxiliary/privacy-struct-ctor.rs:2:18 | LL | pub struct S(u8); - | -- a tuple struct constructor is private if any of its fields is private + | -- a constructor is private if any of the fields is private error[E0603]: tuple struct constructor `Z` is private --> $DIR/privacy-struct-ctor.rs:45:19 @@ -90,7 +90,7 @@ LL | xcrate::m::n::Z; ::: $DIR/auxiliary/privacy-struct-ctor.rs:5:28 | LL | pub(in m) struct Z(pub(in m::n) u8); - | --------------- a tuple struct constructor is private if any of its fields is private + | --------------- a constructor is private if any of the fields is private error: aborting due to 10 previous errors diff --git a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr index fde9ac27fbfb..d3686a1b8696 100644 --- a/src/test/ui/rfc-2008-non-exhaustive/struct.stderr +++ b/src/test/ui/rfc-2008-non-exhaustive/struct.stderr @@ -19,7 +19,7 @@ LL | let ts_explicit = structs::TupleStruct(640, 480); ::: $DIR/auxiliary/structs.rs:13:24 | LL | pub struct TupleStruct(pub u16, pub u16); - | ---------------- a tuple struct constructor is private if any of its fields is private + | ---------------- a constructor is private if any of the fields is private error[E0603]: unit struct `UnitStruct` is private --> $DIR/struct.rs:32:32 From 715ffab116b4dddad98c088eeb1b5ad0dc9c0b16 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 11 Oct 2019 22:33:55 +0200 Subject: [PATCH 277/545] InterpCx: make memory field public --- src/librustc_mir/interpret/eval_context.rs | 12 +----------- src/librustc_mir/interpret/intern.rs | 7 +++---- src/librustc_mir/interpret/terminator.rs | 4 ++-- 3 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index e1c45132103b..06fdd407951c 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -35,7 +35,7 @@ pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> { pub(crate) param_env: ty::ParamEnv<'tcx>, /// The virtual memory system. - pub(crate) memory: Memory<'mir, 'tcx, M>, + pub memory: Memory<'mir, 'tcx, M>, /// The virtual call stack. pub(crate) stack: Vec>, @@ -211,16 +211,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - #[inline(always)] - pub fn memory(&self) -> &Memory<'mir, 'tcx, M> { - &self.memory - } - - #[inline(always)] - pub fn memory_mut(&mut self) -> &mut Memory<'mir, 'tcx, M> { - &mut self.memory - } - #[inline(always)] pub fn force_ptr( &self, diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index ec06b6298e11..646d1783c8ec 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -73,8 +73,7 @@ fn intern_shallow<'rt, 'mir, 'tcx>( ); // remove allocation let tcx = ecx.tcx; - let memory = ecx.memory_mut(); - let (kind, mut alloc) = match memory.alloc_map.remove(&alloc_id) { + let (kind, mut alloc) = match ecx.memory.alloc_map.remove(&alloc_id) { Some(entry) => entry, None => { // Pointer not found in local memory map. It is either a pointer to the global @@ -332,7 +331,7 @@ pub fn intern_const_alloc_recursive( let mut todo: Vec<_> = leftover_allocations.iter().cloned().collect(); while let Some(alloc_id) = todo.pop() { - if let Some((_, mut alloc)) = ecx.memory_mut().alloc_map.remove(&alloc_id) { + if let Some((_, mut alloc)) = ecx.memory.alloc_map.remove(&alloc_id) { // We can't call the `intern_shallow` method here, as its logic is tailored to safe // references and a `leftover_allocations` set (where we only have a todo-list here). // So we hand-roll the interning logic here again. @@ -350,7 +349,7 @@ pub fn intern_const_alloc_recursive( todo.push(reloc); } } - } else if ecx.memory().dead_alloc_map.contains_key(&alloc_id) { + } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { // dangling pointer throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into())) } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index ef6b7d626e7a..31a6126b9594 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -140,12 +140,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { .read_immediate(self.eval_operand(len, None)?) .expect("can't eval len") .to_scalar()? - .to_bits(self.memory().pointer_size())? as u64; + .to_bits(self.memory.pointer_size())? as u64; let index = self .read_immediate(self.eval_operand(index, None)?) .expect("can't eval index") .to_scalar()? - .to_bits(self.memory().pointer_size())? as u64; + .to_bits(self.memory.pointer_size())? as u64; err_panic!(BoundsCheck { len, index }) } Overflow(op) => err_panic!(Overflow(*op)), From 05db5a269868c11a0d3916665a478962d4648a6b Mon Sep 17 00:00:00 2001 From: memoryruins Date: Fri, 11 Oct 2019 16:36:50 -0400 Subject: [PATCH 278/545] Report lint in external macros --- src/librustc/lint/builtin.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 5ca474a8b1d9..983e3a9922ec 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -21,7 +21,8 @@ declare_lint! { declare_lint! { pub CONST_ERR, Deny, - "constant evaluation detected erroneous expression" + "constant evaluation detected erroneous expression", + report_in_external_macro: true } declare_lint! { From 48fff6f9ada2de37ad05db1084641323e7085d7d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 9 Oct 2019 08:50:39 -0400 Subject: [PATCH 279/545] don't assume we can *always* find a return type hint in async fn In particular, we sometimes cannot if there is an earlier error. --- src/librustc_typeck/check/closure.rs | 15 ++++++++++++--- src/test/ui/async-await/issues/issue-65159.rs | 10 ++++++++++ src/test/ui/async-await/issues/issue-65159.stderr | 9 +++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/async-await/issues/issue-65159.rs create mode 100644 src/test/ui/async-await/issues/issue-65159.stderr diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 8b97bf643e9b..4f4133954cf1 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -611,6 +611,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some(hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn)) => { debug!("supplied_sig_of_closure: closure is async fn body"); self.deduce_future_output_from_obligations(expr_def_id) + .unwrap_or_else(|| { + // AFAIK, deducing the future output + // always succeeds *except* in error cases + // like #65159. I'd like to return Error + // here, but I can't because I can't + // easily (and locally) prove that we + // *have* reported an + // error. --nikomatsakis + astconv.ty_infer(None, decl.output.span()) + }) } _ => astconv.ty_infer(None, decl.output.span()), @@ -645,7 +655,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn deduce_future_output_from_obligations( &self, expr_def_id: DefId, - ) -> Ty<'tcx> { + ) -> Option> { debug!("deduce_future_output_from_obligations(expr_def_id={:?})", expr_def_id); let ret_coercion = @@ -688,8 +698,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { None } - }) - .unwrap(); + }); debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty); output_ty diff --git a/src/test/ui/async-await/issues/issue-65159.rs b/src/test/ui/async-await/issues/issue-65159.rs new file mode 100644 index 000000000000..b5fee061f277 --- /dev/null +++ b/src/test/ui/async-await/issues/issue-65159.rs @@ -0,0 +1,10 @@ +// Regression test for #65159. We used to ICE. +// +// edition:2018 + +async fn copy() -> Result<()> //~ ERROR wrong number of type arguments +{ + Ok(()) +} + +fn main() { } diff --git a/src/test/ui/async-await/issues/issue-65159.stderr b/src/test/ui/async-await/issues/issue-65159.stderr new file mode 100644 index 000000000000..56d2c38b302e --- /dev/null +++ b/src/test/ui/async-await/issues/issue-65159.stderr @@ -0,0 +1,9 @@ +error[E0107]: wrong number of type arguments: expected 2, found 1 + --> $DIR/issue-65159.rs:5:20 + | +LL | async fn copy() -> Result<()> + | ^^^^^^^^^^ expected 2 type arguments + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0107`. From 95a65cd1e3d0242339d71326cfdd638e869a37d6 Mon Sep 17 00:00:00 2001 From: memoryruins Date: Fri, 11 Oct 2019 17:13:38 -0400 Subject: [PATCH 280/545] Add regression test for CONST_ERR lints in extern macros --- src/test/ui/consts/auxiliary/external_macro.rs | 14 ++++++++++++++ .../ui/consts/const-external-macro-const-err.rs | 13 +++++++++++++ .../consts/const-external-macro-const-err.stderr | 11 +++++++++++ 3 files changed, 38 insertions(+) create mode 100644 src/test/ui/consts/auxiliary/external_macro.rs create mode 100644 src/test/ui/consts/const-external-macro-const-err.rs create mode 100644 src/test/ui/consts/const-external-macro-const-err.stderr diff --git a/src/test/ui/consts/auxiliary/external_macro.rs b/src/test/ui/consts/auxiliary/external_macro.rs new file mode 100644 index 000000000000..d260634c9963 --- /dev/null +++ b/src/test/ui/consts/auxiliary/external_macro.rs @@ -0,0 +1,14 @@ +#![feature(allow_internal_unstable)] + +// Macro to help ensure CONST_ERR lint errors +// are not silenced in external macros. +// https://github.com/rust-lang/rust/issues/65300 + +#[macro_export] +#[allow_internal_unstable(type_ascription)] +macro_rules! static_assert { + ($test:expr) => { + #[allow(dead_code)] + const _: () = [()][!($test: bool) as usize]; + } +} diff --git a/src/test/ui/consts/const-external-macro-const-err.rs b/src/test/ui/consts/const-external-macro-const-err.rs new file mode 100644 index 000000000000..616d24f4a7bc --- /dev/null +++ b/src/test/ui/consts/const-external-macro-const-err.rs @@ -0,0 +1,13 @@ +// edition:2018 +// aux-build:external_macro.rs + +// Ensure that CONST_ERR lint errors +// are not silenced in external macros. +// https://github.com/rust-lang/rust/issues/65300 + +extern crate external_macro; +use external_macro::static_assert; + +fn main() { + static_assert!(2 + 2 == 5); //~ ERROR +} diff --git a/src/test/ui/consts/const-external-macro-const-err.stderr b/src/test/ui/consts/const-external-macro-const-err.stderr new file mode 100644 index 000000000000..237c4d792c9e --- /dev/null +++ b/src/test/ui/consts/const-external-macro-const-err.stderr @@ -0,0 +1,11 @@ +error: any use of this value will cause an error + --> $DIR/const-external-macro-const-err.rs:12:5 + | +LL | static_assert!(2 + 2 == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 + | + = note: `#[deny(const_err)]` on by default + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + From 000fe63b6fc57b09828930cacbab20c2ee6e6d15 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 11 Oct 2019 17:41:55 -0400 Subject: [PATCH 281/545] Remove painful test that is not pulling its weight Research suggests that we are not properly testing this case anyway, and even if we were, it is unlikely that we will regress here -- or, perhaps more accurately, if we do, I am uncertain that we care too much. It definitely seems like an edge case, and one that is particularly unlikely to occur as time goes on. --- .../linker-output-non-utf8/Makefile | 23 ------------------- .../linker-output-non-utf8/exec.rs | 6 ----- .../linker-output-non-utf8/library.rs | 10 -------- 3 files changed, 39 deletions(-) delete mode 100644 src/test/run-make-fulldeps/linker-output-non-utf8/Makefile delete mode 100644 src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs delete mode 100644 src/test/run-make-fulldeps/linker-output-non-utf8/library.rs diff --git a/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile b/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile deleted file mode 100644 index b47ce17ec8ba..000000000000 --- a/src/test/run-make-fulldeps/linker-output-non-utf8/Makefile +++ /dev/null @@ -1,23 +0,0 @@ --include ../tools.mk - -# Make sure we don't ICE if the linker prints a non-UTF-8 error message. - -# ignore-windows -# -# This does not work in its current form on windows, possibly due to -# gcc bugs or something about valid Windows paths. See issue #29151 -# for more information. - -# ignore-macos -# -# This also does not work on Apple APFS due to the filesystem requiring -# valid UTF-8 paths. - -# The zzz it to allow humans to tab complete or glob this thing. -bad_dir := $(TMPDIR)/zzz$$'\xff' - -all: - $(RUSTC) library.rs - mkdir $(bad_dir) - mv $(TMPDIR)/liblibrary.a $(bad_dir) - $(RUSTC) -L $(bad_dir) exec.rs 2>&1 | $(CGREP) this_symbol_not_defined diff --git a/src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs b/src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs deleted file mode 100644 index 6864018d64e9..000000000000 --- a/src/test/run-make-fulldeps/linker-output-non-utf8/exec.rs +++ /dev/null @@ -1,6 +0,0 @@ -#[link(name="library")] -extern "C" { - fn foo(); -} - -fn main() { unsafe { foo(); } } diff --git a/src/test/run-make-fulldeps/linker-output-non-utf8/library.rs b/src/test/run-make-fulldeps/linker-output-non-utf8/library.rs deleted file mode 100644 index 6689a82fa2c4..000000000000 --- a/src/test/run-make-fulldeps/linker-output-non-utf8/library.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![crate_type = "staticlib"] - -extern "C" { - fn this_symbol_not_defined(); -} - -#[no_mangle] -pub extern "C" fn foo() { - unsafe { this_symbol_not_defined(); } -} From 88ea4ff26a361ca5b0cea0c4b1a4fa15f7a2a141 Mon Sep 17 00:00:00 2001 From: qtmlabs Date: Sat, 12 Oct 2019 12:05:22 +0700 Subject: [PATCH 282/545] Add crosstool-ng 1.24.0 unzip dependency --- src/ci/docker/scripts/cross-apt-packages.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ci/docker/scripts/cross-apt-packages.sh b/src/ci/docker/scripts/cross-apt-packages.sh index 51945fd72adc..bb72e33def21 100644 --- a/src/ci/docker/scripts/cross-apt-packages.sh +++ b/src/ci/docker/scripts/cross-apt-packages.sh @@ -22,5 +22,6 @@ apt-get update && apt-get install -y --no-install-recommends \ python2.7 \ sudo \ texinfo \ + unzip \ wget \ xz-utils From e0395341f7e38e804646bce23809b407564e84db Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sat, 12 Oct 2019 12:45:28 +0800 Subject: [PATCH 283/545] replace the hand-written binary search with the library one --- src/libsyntax/source_map.rs | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 7d0d2392945e..07c301f524ea 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -882,21 +882,13 @@ impl SourceMap { let files = &files.source_files; let count = files.len(); - // Binary search for the `SourceFile`. - let mut a = 0; - let mut b = count; - while b - a > 1 { - let m = (a + b) / 2; - if files[m].start_pos > pos { - b = m; - } else { - a = m; - } - } + // (p - 1) below will not underflow, this follows previous implementation's assumption. + assert!(count >= 1); + let ret = files.binary_search_by_key(&pos, |key| key.start_pos).unwrap_or_else(|p| p - 1); - assert!(a < count, "position {} does not resolve to a source location", pos.to_usize()); + assert!(ret < count, "position {} does not resolve to a source location", pos.to_usize()); - return a; + return ret; } pub fn count_lines(&self) -> usize { From ae79ea3422805d13fa2ec11429596aadfc0db5c9 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Fri, 11 Oct 2019 16:28:02 +0200 Subject: [PATCH 284/545] Update RLS and Rustfmt This also bumps rustc-ap-* crates and fixes the relevant toolstate. --- Cargo.lock | 65 ++++++++++++++++++++++++++++------------------- src/tools/rls | 2 +- src/tools/rustfmt | 2 +- 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 217ce65c1963..40bc9192be19 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2657,9 +2657,9 @@ dependencies = [ [[package]] name = "racer" -version = "2.1.27" +version = "2.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde22b84ab75220015cbd91240222402bf885cbe3a5dc856475771abb82533ae" +checksum = "acc70369054bad4ad0c16a3f45cd73e0695361a3af35c7b465e619ac2674f064" dependencies = [ "bitflags", "clap", @@ -3117,9 +3117,9 @@ dependencies = [ [[package]] name = "rustc-ap-arena" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f59b76d334bd533f3fdc5c651c27678c5e80fac67c6f7da22ba21a58878c55f5" +checksum = "a623fd4805842e9bd0bb6e6dace63efede0ee22de4522a0b03b7c3d15a22f009" dependencies = [ "rustc-ap-rustc_data_structures", "smallvec", @@ -3127,15 +3127,15 @@ dependencies = [ [[package]] name = "rustc-ap-graphviz" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e632ef08ca17458acfd46d2ead3d541a1c249586cd5329f5fe333dacfab6142" +checksum = "ee549ade784b444ef10c0240c3487ed785aa65d711071f7984246b15329a17b6" [[package]] name = "rustc-ap-rustc_data_structures" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89e2c7be68185418f3cd56af3df8b29007a59a1cebefa63612d055f9bcb1a36" +checksum = "ca545744a5a9b42e3d0410d6290d40de96dd567253fe77f310c1de4afd213dd4" dependencies = [ "cfg-if", "crossbeam-utils 0.6.5", @@ -3144,8 +3144,9 @@ dependencies = [ "jobserver", "lazy_static 1.3.0", "log", - "parking_lot 0.7.1", + "parking_lot 0.9.0", "rustc-ap-graphviz", + "rustc-ap-rustc_index", "rustc-ap-serialize", "rustc-hash", "rustc-rayon 0.2.0", @@ -3156,9 +3157,9 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_errors" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e47cb380abeb72b01e42b2342d592f7eeea7d536c2f1f0d0e550dc509e46333" +checksum = "a6967a41ed38ef4bce0f559fe9a4801d8ba12ac032f40a12a55e72f79d52c9bb" dependencies = [ "annotate-snippets", "atty", @@ -3172,19 +3173,29 @@ dependencies = [ ] [[package]] -name = "rustc-ap-rustc_lexer" -version = "583.0.0" +name = "rustc-ap-rustc_index" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494cfaf67f49217d67d0774eeecbba61ac89acf478db97ef11f113ed8a959305" +checksum = "457a5c204ae2fdaa5bdb5b196e58ca59896870d80445fe423063c9453496e3ea" +dependencies = [ + "rustc-ap-serialize", + "smallvec", +] + +[[package]] +name = "rustc-ap-rustc_lexer" +version = "606.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed0c064676f8a08e42a36b0d4e4a102465fb0f4b75e11436cb7f66d2c3fa7139" dependencies = [ "unicode-xid 0.2.0", ] [[package]] name = "rustc-ap-rustc_macros" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e5d36becc59b4497f9cbd3ae0610081de0207a1d0e95c066369167b14f486f" +checksum = "b2d77e46159c5288c585decbcdc9d742889c65e307c31e104c7a36d63fe1f5d0" dependencies = [ "itertools 0.8.0", "proc-macro2 0.4.30", @@ -3195,22 +3206,23 @@ dependencies = [ [[package]] name = "rustc-ap-rustc_target" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7bfc5f96dfc3b9f8d5b57884f7f37467ecff6776cd4b8b491a7daece6fdd7c2" +checksum = "86ca895350b0de14d064b499168c93fa183958d5462eb042c927d93623e41ec1" dependencies = [ "bitflags", "log", "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_index", "rustc-ap-serialize", "rustc-ap-syntax_pos", ] [[package]] name = "rustc-ap-serialize" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb9ee231cf79eded39c56647499f83d6136ff5c8c0baaa9e21b6febee00f4f6" +checksum = "92679240e86f4583cc05f8dcf6439bdab87bac9e6555718469176de9bd52ba20" dependencies = [ "indexmap", "smallvec", @@ -3218,17 +3230,17 @@ dependencies = [ [[package]] name = "rustc-ap-syntax" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3827fc208814efbde82d613e31d11b4250ce9e8cf8afe4a4d47bbbd099632c9" +checksum = "0a0c30f8e38c847dbfd9e2f1e472ab06d0bd0a23ab53ae4c5a44912842ce834e" dependencies = [ "bitflags", "lazy_static 1.3.0", "log", "rustc-ap-rustc_data_structures", "rustc-ap-rustc_errors", + "rustc-ap-rustc_index", "rustc-ap-rustc_lexer", - "rustc-ap-rustc_macros", "rustc-ap-rustc_target", "rustc-ap-serialize", "rustc-ap-syntax_pos", @@ -3238,13 +3250,14 @@ dependencies = [ [[package]] name = "rustc-ap-syntax_pos" -version = "583.0.0" +version = "606.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "930ed81c34f325e512cc315c04d676fa84a373879d5c43bb54054a0522b05213" +checksum = "2bdaa0fb40143b4b878256ac4e2b498885daafc269502504d91929eab4744bf4" dependencies = [ "cfg-if", "rustc-ap-arena", "rustc-ap-rustc_data_structures", + "rustc-ap-rustc_index", "rustc-ap-rustc_macros", "rustc-ap-serialize", "scoped-tls", @@ -3846,7 +3859,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.4.8" +version = "1.4.9" dependencies = [ "annotate-snippets", "bytecount", diff --git a/src/tools/rls b/src/tools/rls index 8dc9ba96d57c..a18df1618194 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 8dc9ba96d57c5705b99a18a380d41579e9d2d675 +Subproject commit a18df16181947edd5eb593ea0f2321e0035448ee diff --git a/src/tools/rustfmt b/src/tools/rustfmt index afb1ee1c1459..33e3667085e4 160000 --- a/src/tools/rustfmt +++ b/src/tools/rustfmt @@ -1 +1 @@ -Subproject commit afb1ee1c14594aed5bb4a762b357b01f13c9de10 +Subproject commit 33e3667085e4c73d4391c6168552458eb47664de From 81d813dd67fd94fdd680ba68f20e3df7b8953904 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Sat, 12 Oct 2019 08:29:27 +0000 Subject: [PATCH 285/545] Bump home crate --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40bc9192be19..844320fff3f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1330,9 +1330,9 @@ checksum = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" [[package]] name = "home" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07c315e106bd6f83f026a20ddaeef2706782e490db1dcdd37caad38a0e895b3" +checksum = "a3753954f7bd71f0e671afb8b5a992d1724cf43b7f95a563cd4a0bde94659ca8" dependencies = [ "scopeguard 1.0.0", "winapi 0.3.6", From a14601e06cba5bf4418f298929c2fad009bdbc51 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 13:26:31 +0200 Subject: [PATCH 286/545] std::fmt: move format string grammar to the bottom --- src/liballoc/fmt.rs | 49 +++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 68cbc366d7bc..5b6aec79e912 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -300,30 +300,6 @@ //! it would internally pass around this structure until it has been determined //! where output should go to. //! -//! # Syntax -//! -//! The syntax for the formatting language used is drawn from other languages, -//! so it should not be too alien. Arguments are formatted with Python-like -//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like -//! `%`. The actual grammar for the formatting syntax is: -//! -//! ```text -//! format_string := [ maybe-format ] * -//! maybe-format := '{' '{' | '}' '}' | -//! format := '{' [ argument ] [ ':' format_spec ] '}' -//! argument := integer | identifier -//! -//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type] -//! fill := character -//! align := '<' | '^' | '>' -//! sign := '+' | '-' -//! width := count -//! precision := count | '*' -//! type := identifier | '?' | '' -//! count := parameter | integer -//! parameter := argument '$' -//! ``` -//! //! # Formatting Parameters //! //! Each argument being formatted can be transformed by a number of formatting @@ -479,6 +455,31 @@ //! them with the same character. For example, the `{` character is escaped with //! `{{` and the `}` character is escaped with `}}`. //! +//! # Syntax +//! +//! Below, you can find the full grammar of format strings. +//! The syntax for the formatting language used is drawn from other languages, +//! so it should not be too alien. Arguments are formatted with Python-like +//! syntax, meaning that arguments are surrounded by `{}` instead of the C-like +//! `%`. The actual grammar for the formatting syntax is: +//! +//! ```text +//! format_string := [ maybe-format ] * +//! maybe-format := '{' '{' | '}' '}' | +//! format := '{' [ argument ] [ ':' format_spec ] '}' +//! argument := integer | identifier +//! +//! format_spec := [[fill]align][sign]['#']['0'][width]['.' precision][type] +//! fill := character +//! align := '<' | '^' | '>' +//! sign := '+' | '-' +//! width := count +//! precision := count | '*' +//! type := identifier | '?' | '' +//! count := parameter | integer +//! parameter := argument '$' +//! ``` +//! //! [`usize`]: ../../std/primitive.usize.html //! [`isize`]: ../../std/primitive.isize.html //! [`i8`]: ../../std/primitive.i8.html From f727f8ae5e1663557904c23438ea9525d50e9abc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 13:31:58 +0200 Subject: [PATCH 287/545] move Formatting Traits down --- src/liballoc/fmt.rs | 408 ++++++++++++++++++++++---------------------- 1 file changed, 204 insertions(+), 204 deletions(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 5b6aec79e912..bdd1583080bf 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -97,209 +97,6 @@ //! actual object being formatted, and the number of characters must have the //! type [`usize`]. //! -//! ## Formatting traits -//! -//! When requesting that an argument be formatted with a particular type, you -//! are actually requesting that an argument ascribes to a particular trait. -//! This allows multiple actual types to be formatted via `{:x}` (like [`i8`] as -//! well as [`isize`]). The current mapping of types to traits is: -//! -//! * *nothing* ⇒ [`Display`] -//! * `?` ⇒ [`Debug`] -//! * `x?` ⇒ [`Debug`] with lower-case hexadecimal integers -//! * `X?` ⇒ [`Debug`] with upper-case hexadecimal integers -//! * `o` ⇒ [`Octal`](trait.Octal.html) -//! * `x` ⇒ [`LowerHex`](trait.LowerHex.html) -//! * `X` ⇒ [`UpperHex`](trait.UpperHex.html) -//! * `p` ⇒ [`Pointer`](trait.Pointer.html) -//! * `b` ⇒ [`Binary`] -//! * `e` ⇒ [`LowerExp`](trait.LowerExp.html) -//! * `E` ⇒ [`UpperExp`](trait.UpperExp.html) -//! -//! What this means is that any type of argument which implements the -//! [`fmt::Binary`][`Binary`] trait can then be formatted with `{:b}`. Implementations -//! are provided for these traits for a number of primitive types by the -//! standard library as well. If no format is specified (as in `{}` or `{:6}`), -//! then the format trait used is the [`Display`] trait. -//! -//! When implementing a format trait for your own type, you will have to -//! implement a method of the signature: -//! -//! ``` -//! # #![allow(dead_code)] -//! # use std::fmt; -//! # struct Foo; // our custom type -//! # impl fmt::Display for Foo { -//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -//! # write!(f, "testing, testing") -//! # } } -//! ``` -//! -//! Your type will be passed as `self` by-reference, and then the function -//! should emit output into the `f.buf` stream. It is up to each format trait -//! implementation to correctly adhere to the requested formatting parameters. -//! The values of these parameters will be listed in the fields of the -//! [`Formatter`] struct. In order to help with this, the [`Formatter`] struct also -//! provides some helper methods. -//! -//! Additionally, the return value of this function is [`fmt::Result`] which is a -//! type alias of [`Result`]`<(), `[`std::fmt::Error`]`>`. Formatting implementations -//! should ensure that they propagate errors from the [`Formatter`][`Formatter`] (e.g., when -//! calling [`write!`]). However, they should never return errors spuriously. That -//! is, a formatting implementation must and may only return an error if the -//! passed-in [`Formatter`] returns an error. This is because, contrary to what -//! the function signature might suggest, string formatting is an infallible -//! operation. This function only returns a result because writing to the -//! underlying stream might fail and it must provide a way to propagate the fact -//! that an error has occurred back up the stack. -//! -//! An example of implementing the formatting traits would look -//! like: -//! -//! ``` -//! use std::fmt; -//! -//! #[derive(Debug)] -//! struct Vector2D { -//! x: isize, -//! y: isize, -//! } -//! -//! impl fmt::Display for Vector2D { -//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -//! // The `f` value implements the `Write` trait, which is what the -//! // write! macro is expecting. Note that this formatting ignores the -//! // various flags provided to format strings. -//! write!(f, "({}, {})", self.x, self.y) -//! } -//! } -//! -//! // Different traits allow different forms of output of a type. The meaning -//! // of this format is to print the magnitude of a vector. -//! impl fmt::Binary for Vector2D { -//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { -//! let magnitude = (self.x * self.x + self.y * self.y) as f64; -//! let magnitude = magnitude.sqrt(); -//! -//! // Respect the formatting flags by using the helper method -//! // `pad_integral` on the Formatter object. See the method -//! // documentation for details, and the function `pad` can be used -//! // to pad strings. -//! let decimals = f.precision().unwrap_or(3); -//! let string = format!("{:.*}", decimals, magnitude); -//! f.pad_integral(true, "", &string) -//! } -//! } -//! -//! fn main() { -//! let myvector = Vector2D { x: 3, y: 4 }; -//! -//! println!("{}", myvector); // => "(3, 4)" -//! println!("{:?}", myvector); // => "Vector2D {x: 3, y:4}" -//! println!("{:10.3b}", myvector); // => " 5.000" -//! } -//! ``` -//! -//! ### `fmt::Display` vs `fmt::Debug` -//! -//! These two formatting traits have distinct purposes: -//! -//! - [`fmt::Display`][`Display`] implementations assert that the type can be faithfully -//! represented as a UTF-8 string at all times. It is **not** expected that -//! all types implement the [`Display`] trait. -//! - [`fmt::Debug`][`Debug`] implementations should be implemented for **all** public types. -//! Output will typically represent the internal state as faithfully as possible. -//! The purpose of the [`Debug`] trait is to facilitate debugging Rust code. In -//! most cases, using `#[derive(Debug)]` is sufficient and recommended. -//! -//! Some examples of the output from both traits: -//! -//! ``` -//! assert_eq!(format!("{} {:?}", 3, 4), "3 4"); -//! assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'"); -//! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); -//! ``` -//! -//! ## Related macros -//! -//! There are a number of related macros in the [`format!`] family. The ones that -//! are currently implemented are: -//! -//! ```ignore (only-for-syntax-highlight) -//! format! // described above -//! write! // first argument is a &mut io::Write, the destination -//! writeln! // same as write but appends a newline -//! print! // the format string is printed to the standard output -//! println! // same as print but appends a newline -//! eprint! // the format string is printed to the standard error -//! eprintln! // same as eprint but appends a newline -//! format_args! // described below. -//! ``` -//! -//! ### `write!` -//! -//! This and [`writeln!`] are two macros which are used to emit the format string -//! to a specified stream. This is used to prevent intermediate allocations of -//! format strings and instead directly write the output. Under the hood, this -//! function is actually invoking the [`write_fmt`] function defined on the -//! [`std::io::Write`] trait. Example usage is: -//! -//! ``` -//! # #![allow(unused_must_use)] -//! use std::io::Write; -//! let mut w = Vec::new(); -//! write!(&mut w, "Hello {}!", "world"); -//! ``` -//! -//! ### `print!` -//! -//! This and [`println!`] emit their output to stdout. Similarly to the [`write!`] -//! macro, the goal of these macros is to avoid intermediate allocations when -//! printing output. Example usage is: -//! -//! ``` -//! print!("Hello {}!", "world"); -//! println!("I have a newline {}", "character at the end"); -//! ``` -//! ### `eprint!` -//! -//! The [`eprint!`] and [`eprintln!`] macros are identical to -//! [`print!`] and [`println!`], respectively, except they emit their -//! output to stderr. -//! -//! ### `format_args!` -//! -//! This is a curious macro which is used to safely pass around -//! an opaque object describing the format string. This object -//! does not require any heap allocations to create, and it only -//! references information on the stack. Under the hood, all of -//! the related macros are implemented in terms of this. First -//! off, some example usage is: -//! -//! ``` -//! # #![allow(unused_must_use)] -//! use std::fmt; -//! use std::io::{self, Write}; -//! -//! let mut some_writer = io::stdout(); -//! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro")); -//! -//! fn my_fmt_fn(args: fmt::Arguments) { -//! write!(&mut io::stdout(), "{}", args); -//! } -//! my_fmt_fn(format_args!(", or a {} too", "function")); -//! ``` -//! -//! The result of the [`format_args!`] macro is a value of type [`fmt::Arguments`]. -//! This structure can then be passed to the [`write`] and [`format`] functions -//! inside this module in order to process the format string. -//! The goal of this macro is to even further prevent intermediate allocations -//! when dealing formatting strings. -//! -//! For example, a logging library could use the standard formatting syntax, but -//! it would internally pass around this structure until it has been determined -//! where output should go to. -//! //! # Formatting Parameters //! //! Each argument being formatted can be transformed by a number of formatting @@ -457,7 +254,7 @@ //! //! # Syntax //! -//! Below, you can find the full grammar of format strings. +//! To summarize, you can find the full grammar of format strings. //! The syntax for the formatting language used is drawn from other languages, //! so it should not be too alien. Arguments are formatted with Python-like //! syntax, meaning that arguments are surrounded by `{}` instead of the C-like @@ -480,6 +277,209 @@ //! parameter := argument '$' //! ``` //! +//! # Formatting traits +//! +//! When requesting that an argument be formatted with a particular type, you +//! are actually requesting that an argument ascribes to a particular trait. +//! This allows multiple actual types to be formatted via `{:x}` (like [`i8`] as +//! well as [`isize`]). The current mapping of types to traits is: +//! +//! * *nothing* ⇒ [`Display`] +//! * `?` ⇒ [`Debug`] +//! * `x?` ⇒ [`Debug`] with lower-case hexadecimal integers +//! * `X?` ⇒ [`Debug`] with upper-case hexadecimal integers +//! * `o` ⇒ [`Octal`](trait.Octal.html) +//! * `x` ⇒ [`LowerHex`](trait.LowerHex.html) +//! * `X` ⇒ [`UpperHex`](trait.UpperHex.html) +//! * `p` ⇒ [`Pointer`](trait.Pointer.html) +//! * `b` ⇒ [`Binary`] +//! * `e` ⇒ [`LowerExp`](trait.LowerExp.html) +//! * `E` ⇒ [`UpperExp`](trait.UpperExp.html) +//! +//! What this means is that any type of argument which implements the +//! [`fmt::Binary`][`Binary`] trait can then be formatted with `{:b}`. Implementations +//! are provided for these traits for a number of primitive types by the +//! standard library as well. If no format is specified (as in `{}` or `{:6}`), +//! then the format trait used is the [`Display`] trait. +//! +//! When implementing a format trait for your own type, you will have to +//! implement a method of the signature: +//! +//! ``` +//! # #![allow(dead_code)] +//! # use std::fmt; +//! # struct Foo; // our custom type +//! # impl fmt::Display for Foo { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! # write!(f, "testing, testing") +//! # } } +//! ``` +//! +//! Your type will be passed as `self` by-reference, and then the function +//! should emit output into the `f.buf` stream. It is up to each format trait +//! implementation to correctly adhere to the requested formatting parameters. +//! The values of these parameters will be listed in the fields of the +//! [`Formatter`] struct. In order to help with this, the [`Formatter`] struct also +//! provides some helper methods. +//! +//! Additionally, the return value of this function is [`fmt::Result`] which is a +//! type alias of [`Result`]`<(), `[`std::fmt::Error`]`>`. Formatting implementations +//! should ensure that they propagate errors from the [`Formatter`][`Formatter`] (e.g., when +//! calling [`write!`]). However, they should never return errors spuriously. That +//! is, a formatting implementation must and may only return an error if the +//! passed-in [`Formatter`] returns an error. This is because, contrary to what +//! the function signature might suggest, string formatting is an infallible +//! operation. This function only returns a result because writing to the +//! underlying stream might fail and it must provide a way to propagate the fact +//! that an error has occurred back up the stack. +//! +//! An example of implementing the formatting traits would look +//! like: +//! +//! ``` +//! use std::fmt; +//! +//! #[derive(Debug)] +//! struct Vector2D { +//! x: isize, +//! y: isize, +//! } +//! +//! impl fmt::Display for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! // The `f` value implements the `Write` trait, which is what the +//! // write! macro is expecting. Note that this formatting ignores the +//! // various flags provided to format strings. +//! write!(f, "({}, {})", self.x, self.y) +//! } +//! } +//! +//! // Different traits allow different forms of output of a type. The meaning +//! // of this format is to print the magnitude of a vector. +//! impl fmt::Binary for Vector2D { +//! fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +//! let magnitude = (self.x * self.x + self.y * self.y) as f64; +//! let magnitude = magnitude.sqrt(); +//! +//! // Respect the formatting flags by using the helper method +//! // `pad_integral` on the Formatter object. See the method +//! // documentation for details, and the function `pad` can be used +//! // to pad strings. +//! let decimals = f.precision().unwrap_or(3); +//! let string = format!("{:.*}", decimals, magnitude); +//! f.pad_integral(true, "", &string) +//! } +//! } +//! +//! fn main() { +//! let myvector = Vector2D { x: 3, y: 4 }; +//! +//! println!("{}", myvector); // => "(3, 4)" +//! println!("{:?}", myvector); // => "Vector2D {x: 3, y:4}" +//! println!("{:10.3b}", myvector); // => " 5.000" +//! } +//! ``` +//! +//! ### `fmt::Display` vs `fmt::Debug` +//! +//! These two formatting traits have distinct purposes: +//! +//! - [`fmt::Display`][`Display`] implementations assert that the type can be faithfully +//! represented as a UTF-8 string at all times. It is **not** expected that +//! all types implement the [`Display`] trait. +//! - [`fmt::Debug`][`Debug`] implementations should be implemented for **all** public types. +//! Output will typically represent the internal state as faithfully as possible. +//! The purpose of the [`Debug`] trait is to facilitate debugging Rust code. In +//! most cases, using `#[derive(Debug)]` is sufficient and recommended. +//! +//! Some examples of the output from both traits: +//! +//! ``` +//! assert_eq!(format!("{} {:?}", 3, 4), "3 4"); +//! assert_eq!(format!("{} {:?}", 'a', 'b'), "a 'b'"); +//! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\""); +//! ``` +//! +//! # Related macros +//! +//! There are a number of related macros in the [`format!`] family. The ones that +//! are currently implemented are: +//! +//! ```ignore (only-for-syntax-highlight) +//! format! // described above +//! write! // first argument is a &mut io::Write, the destination +//! writeln! // same as write but appends a newline +//! print! // the format string is printed to the standard output +//! println! // same as print but appends a newline +//! eprint! // the format string is printed to the standard error +//! eprintln! // same as eprint but appends a newline +//! format_args! // described below. +//! ``` +//! +//! ### `write!` +//! +//! This and [`writeln!`] are two macros which are used to emit the format string +//! to a specified stream. This is used to prevent intermediate allocations of +//! format strings and instead directly write the output. Under the hood, this +//! function is actually invoking the [`write_fmt`] function defined on the +//! [`std::io::Write`] trait. Example usage is: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! use std::io::Write; +//! let mut w = Vec::new(); +//! write!(&mut w, "Hello {}!", "world"); +//! ``` +//! +//! ### `print!` +//! +//! This and [`println!`] emit their output to stdout. Similarly to the [`write!`] +//! macro, the goal of these macros is to avoid intermediate allocations when +//! printing output. Example usage is: +//! +//! ``` +//! print!("Hello {}!", "world"); +//! println!("I have a newline {}", "character at the end"); +//! ``` +//! ### `eprint!` +//! +//! The [`eprint!`] and [`eprintln!`] macros are identical to +//! [`print!`] and [`println!`], respectively, except they emit their +//! output to stderr. +//! +//! ### `format_args!` +//! +//! This is a curious macro which is used to safely pass around +//! an opaque object describing the format string. This object +//! does not require any heap allocations to create, and it only +//! references information on the stack. Under the hood, all of +//! the related macros are implemented in terms of this. First +//! off, some example usage is: +//! +//! ``` +//! # #![allow(unused_must_use)] +//! use std::fmt; +//! use std::io::{self, Write}; +//! +//! let mut some_writer = io::stdout(); +//! write!(&mut some_writer, "{}", format_args!("print with a {}", "macro")); +//! +//! fn my_fmt_fn(args: fmt::Arguments) { +//! write!(&mut io::stdout(), "{}", args); +//! } +//! my_fmt_fn(format_args!(", or a {} too", "function")); +//! ``` +//! +//! The result of the [`format_args!`] macro is a value of type [`fmt::Arguments`]. +//! This structure can then be passed to the [`write`] and [`format`] functions +//! inside this module in order to process the format string. +//! The goal of this macro is to even further prevent intermediate allocations +//! when dealing formatting strings. +//! +//! For example, a logging library could use the standard formatting syntax, but +//! it would internally pass around this structure until it has been determined +//! where output should go to. +//! //! [`usize`]: ../../std/primitive.usize.html //! [`isize`]: ../../std/primitive.isize.html //! [`i8`]: ../../std/primitive.i8.html From 62fba55670f3f54356cd757ac6d221be42745fad Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 18 Sep 2019 19:33:31 -0400 Subject: [PATCH 288/545] Make trivial dropck outlives a query This allows caching some recursive types and getting to an error much more quickly. --- src/librustc/query/mod.rs | 6 ++++++ src/librustc/traits/query/dropck_outlives.rs | 16 ++++++++++++---- src/librustc/traits/query/type_op/outlives.rs | 3 +-- src/librustc/ty/mod.rs | 1 + src/librustc_traits/dropck_outlives.rs | 4 ++++ 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c95652f274e3..2a012c527419 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -231,6 +231,12 @@ rustc_queries! { cycle_delay_bug } + query trivial_dropck_outlives(ty: Ty<'tcx>) -> bool { + anon + no_force + desc { "checking if `{:?}` has trivial dropck", ty } + } + query adt_dtorck_constraint( _: DefId ) -> Result, NoSolution> {} diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc/traits/query/dropck_outlives.rs index eaf5971e4592..e84c91daf293 100644 --- a/src/librustc/traits/query/dropck_outlives.rs +++ b/src/librustc/traits/query/dropck_outlives.rs @@ -5,6 +5,7 @@ use std::iter::FromIterator; use syntax::source_map::Span; use crate::ty::subst::GenericArg; use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::query::Providers; impl<'cx, 'tcx> At<'cx, 'tcx> { /// Given a type `ty` of some value being dropped, computes a set @@ -33,7 +34,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { // Quick check: there are a number of cases that we know do not require // any destructor. let tcx = self.infcx.tcx; - if trivial_dropck_outlives(tcx, ty) { + if tcx.trivial_dropck_outlives(ty) { return InferOk { value: vec![], obligations: vec![], @@ -207,15 +208,15 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Error => true, // [T; N] and [T] have same properties as T. - ty::Array(ty, _) | ty::Slice(ty) => trivial_dropck_outlives(tcx, ty), + ty::Array(ty, _) | ty::Slice(ty) => tcx.trivial_dropck_outlives(ty), // (T1..Tn) and closures have same properties as T1..Tn -- // check if *any* of those are trivial. - ty::Tuple(ref tys) => tys.iter().all(|t| trivial_dropck_outlives(tcx, t.expect_ty())), + ty::Tuple(ref tys) => tys.iter().all(|t| tcx.trivial_dropck_outlives(t.expect_ty())), ty::Closure(def_id, ref substs) => substs .as_closure() .upvar_tys(def_id, tcx) - .all(|t| trivial_dropck_outlives(tcx, t)), + .all(|t| tcx.trivial_dropck_outlives(t)), ty::Adt(def, _) => { if Some(def.did) == tcx.lang_items().manually_drop() { @@ -243,3 +244,10 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } + +crate fn provide(p: &mut Providers<'_>) { + *p = Providers { + trivial_dropck_outlives, + ..*p + }; +} diff --git a/src/librustc/traits/query/type_op/outlives.rs b/src/librustc/traits/query/type_op/outlives.rs index 9b956f3e5540..86a32d68fc09 100644 --- a/src/librustc/traits/query/type_op/outlives.rs +++ b/src/librustc/traits/query/type_op/outlives.rs @@ -1,5 +1,4 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; -use crate::traits::query::dropck_outlives::trivial_dropck_outlives; use crate::traits::query::dropck_outlives::DropckOutlivesResult; use crate::traits::query::Fallible; use crate::ty::{ParamEnvAnd, Ty, TyCtxt}; @@ -22,7 +21,7 @@ impl super::QueryTypeOp<'tcx> for DropckOutlives<'tcx> { tcx: TyCtxt<'tcx>, key: &ParamEnvAnd<'tcx, Self>, ) -> Option { - if trivial_dropck_outlives(tcx, key.value.dropped_ty) { + if tcx.trivial_dropck_outlives(key.value.dropped_ty) { Some(DropckOutlivesResult::default()) } else { None diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index cfd859c33c2e..01b7cda6fe91 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3394,6 +3394,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { layout::provide(providers); util::provide(providers); constness::provide(providers); + crate::traits::query::dropck_outlives::provide(providers); *providers = ty::query::Providers { asyncness, associated_item, diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 88e62db9a10d..e751c94f23d1 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -166,6 +166,10 @@ fn dtorck_constraint_for_ty<'tcx>( }); } + if tcx.trivial_dropck_outlives(ty) { + return Ok(DtorckConstraint::empty()); + } + let result = match ty.kind { ty::Bool | ty::Char From 8de7fd884a9478e8fc41a810b9f4b647634efd0c Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 18 Sep 2019 21:48:46 -0400 Subject: [PATCH 289/545] Keep allocated vectors during dropck Previously we'd frequently throw away vectors which is bad for performance --- src/librustc_traits/dropck_outlives.rs | 111 +++++++++++-------------- 1 file changed, 50 insertions(+), 61 deletions(-) diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index e751c94f23d1..c1316f415a55 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -80,22 +80,30 @@ fn dropck_outlives<'tcx>( let mut fulfill_cx = TraitEngine::new(infcx.tcx); let cause = ObligationCause::dummy(); + let mut constraints = DtorckConstraint::empty(); while let Some((ty, depth)) = ty_stack.pop() { - let DtorckConstraint { - dtorck_types, - outlives, - overflows, - } = dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty)?; + info!("{} kinds, {} overflows, {} ty_stack", + result.kinds.len(), result.overflows.len(), ty_stack.len()); + dtorck_constraint_for_ty(tcx, DUMMY_SP, for_ty, depth, ty, &mut constraints)?; // "outlives" represent types/regions that may be touched // by a destructor. - result.kinds.extend(outlives); - result.overflows.extend(overflows); + result.kinds.extend(constraints.outlives.drain(..)); + result.overflows.extend(constraints.overflows.drain(..)); + + // If we have even one overflow, we should stop trying to evaluate further -- + // chances are, the subsequent overflows for this evaluation won't provide useful + // 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 { + break; + } // dtorck types are "types that will get dropped but which // do not themselves define a destructor", more or less. We have // to push them onto the stack to be expanded. - for ty in dtorck_types { + for ty in constraints.dtorck_types.drain(..) { match infcx.at(&cause, param_env).normalize(&ty) { Ok(Normalized { value: ty, @@ -152,25 +160,23 @@ fn dtorck_constraint_for_ty<'tcx>( for_ty: Ty<'tcx>, depth: usize, ty: Ty<'tcx>, -) -> Result, NoSolution> { + constraints: &mut DtorckConstraint<'tcx>, +) -> Result<(), NoSolution> { debug!( "dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty ); if depth >= *tcx.sess.recursion_limit.get() { - return Ok(DtorckConstraint { - outlives: vec![], - dtorck_types: vec![], - overflows: vec![ty], - }); + constraints.overflows.push(ty); + return Ok(()); } if tcx.trivial_dropck_outlives(ty) { - return Ok(DtorckConstraint::empty()); + return Ok(()); } - let result = match ty.kind { + match ty.kind { ty::Bool | ty::Char | ty::Int(_) @@ -185,22 +191,20 @@ fn dtorck_constraint_for_ty<'tcx>( | ty::FnPtr(_) | ty::GeneratorWitness(..) => { // these types never have a destructor - Ok(DtorckConstraint::empty()) } ty::Array(ety, _) | ty::Slice(ety) => { // single-element containers, behave like their element - dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety) + dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ety, constraints)?; } - ty::Tuple(tys) => tys.iter() - .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty.expect_ty())) - .collect(), + ty::Tuple(tys) => for ty in tys.iter() { + dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty.expect_ty(), constraints)?; + }, - ty::Closure(def_id, substs) => substs.as_closure() - .upvar_tys(def_id, tcx) - .map(|ty| dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty)) - .collect(), + ty::Closure(def_id, substs) => for ty in substs.as_closure().upvar_tys(def_id, tcx) { + dtorck_constraint_for_ty(tcx, span, for_ty, depth + 1, ty, constraints)?; + } ty::Generator(def_id, substs, _movability) => { // rust-lang/rust#49918: types can be constructed, stored @@ -226,17 +230,8 @@ fn dtorck_constraint_for_ty<'tcx>( // derived from lifetimes attached to the upvars, and we // *do* incorporate the upvars here. - let constraint = DtorckConstraint { - outlives: substs.as_generator().upvar_tys(def_id, tcx).map(|t| t.into()).collect(), - dtorck_types: vec![], - overflows: vec![], - }; - debug!( - "dtorck_constraint: generator {:?} => {:?}", - def_id, constraint - ); - - Ok(constraint) + constraints.outlives.extend(substs.as_generator().upvar_tys(def_id, tcx) + .map(|t| -> ty::subst::GenericArg<'tcx> { t.into() })); } ty::Adt(def, substs) => { @@ -245,41 +240,34 @@ fn dtorck_constraint_for_ty<'tcx>( outlives, overflows, } = tcx.at(span).adt_dtorck_constraint(def.did)?; - Ok(DtorckConstraint { - // FIXME: we can try to recursively `dtorck_constraint_on_ty` - // there, but that needs some way to handle cycles. - dtorck_types: dtorck_types.subst(tcx, substs), - outlives: outlives.subst(tcx, substs), - overflows: overflows.subst(tcx, substs), - }) + // FIXME: we can try to recursively `dtorck_constraint_on_ty` + // there, but that needs some way to handle cycles. + constraints.dtorck_types.extend(dtorck_types.subst(tcx, substs)); + constraints.outlives.extend(outlives.subst(tcx, substs)); + constraints.overflows.extend(overflows.subst(tcx, substs)); } // Objects must be alive in order for their destructor // to be called. - ty::Dynamic(..) => Ok(DtorckConstraint { - outlives: vec![ty.into()], - dtorck_types: vec![], - overflows: vec![], - }), + ty::Dynamic(..) => { + constraints.outlives.push(ty.into()); + }, // Types that can't be resolved. Pass them forward. - ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => Ok(DtorckConstraint { - outlives: vec![], - dtorck_types: vec![ty], - overflows: vec![], - }), + ty::Projection(..) | ty::Opaque(..) | ty::Param(..) => { + constraints.dtorck_types.push(ty); + }, ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => { // By the time this code runs, all type variables ought to // be fully resolved. - Err(NoSolution) + return Err(NoSolution) } - }; + } - debug!("dtorck_constraint_for_ty({:?}) = {:?}", ty, result); - result + Ok(()) } /// Calculates the dtorck constraint for a type. @@ -305,10 +293,11 @@ crate fn adt_dtorck_constraint( return Ok(result); } - let mut result = def.all_fields() - .map(|field| tcx.type_of(field.did)) - .map(|fty| dtorck_constraint_for_ty(tcx, span, fty, 0, fty)) - .collect::, NoSolution>>()?; + let mut result = DtorckConstraint::empty(); + for field in def.all_fields() { + let fty = tcx.type_of(field.did); + dtorck_constraint_for_ty(tcx, span, fty, 0, fty, &mut result)?; + } result.outlives.extend(tcx.destructor_constraints(def)); dedup_dtorck_constraint(&mut result); From d8c2956906eae34516f3d215cda16dc16656766a Mon Sep 17 00:00:00 2001 From: BO41 Date: Sun, 6 Oct 2019 15:59:49 +0200 Subject: [PATCH 290/545] Improve docs on some char boolean methods --- src/libcore/char/methods.rs | 172 +++++++++++++++++++++++------------- 1 file changed, 109 insertions(+), 63 deletions(-) diff --git a/src/libcore/char/methods.rs b/src/libcore/char/methods.rs index a69eb0f6d4b2..971d89e00444 100644 --- a/src/libcore/char/methods.rs +++ b/src/libcore/char/methods.rs @@ -116,9 +116,9 @@ impl char { // the code is split up here to improve execution speed for cases where // the `radix` is constant and 10 or smaller - let val = if radix <= 10 { + let val = if radix <= 10 { match self { - '0' ..= '9' => self as u32 - '0' as u32, + '0'..='9' => self as u32 - '0' as u32, _ => return None, } } else { @@ -130,8 +130,11 @@ impl char { } }; - if val < radix { Some(val) } - else { None } + if val < radix { + Some(val) + } else { + None + } } /// Returns an iterator that yields the hexadecimal Unicode escape of a @@ -303,8 +306,8 @@ impl char { '\r' => EscapeDefaultState::Backslash('r'), '\n' => EscapeDefaultState::Backslash('n'), '\\' | '\'' | '"' => EscapeDefaultState::Backslash(self), - '\x20' ..= '\x7e' => EscapeDefaultState::Char(self), - _ => EscapeDefaultState::Unicode(self.escape_unicode()) + '\x20'..='\x7e' => EscapeDefaultState::Char(self), + _ => EscapeDefaultState::Unicode(self.escape_unicode()), }; EscapeDefault { state: init_state } } @@ -436,30 +439,31 @@ impl char { pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str { let code = self as u32; unsafe { - let len = - if code < MAX_ONE_B && !dst.is_empty() { + let len = if code < MAX_ONE_B && !dst.is_empty() { *dst.get_unchecked_mut(0) = code as u8; 1 } else if code < MAX_TWO_B && dst.len() >= 2 { *dst.get_unchecked_mut(0) = (code >> 6 & 0x1F) as u8 | TAG_TWO_B; *dst.get_unchecked_mut(1) = (code & 0x3F) as u8 | TAG_CONT; 2 - } else if code < MAX_THREE_B && dst.len() >= 3 { + } else if code < MAX_THREE_B && dst.len() >= 3 { *dst.get_unchecked_mut(0) = (code >> 12 & 0x0F) as u8 | TAG_THREE_B; - *dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *dst.get_unchecked_mut(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT; *dst.get_unchecked_mut(2) = (code & 0x3F) as u8 | TAG_CONT; 3 } else if dst.len() >= 4 { *dst.get_unchecked_mut(0) = (code >> 18 & 0x07) as u8 | TAG_FOUR_B; *dst.get_unchecked_mut(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT; - *dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; + *dst.get_unchecked_mut(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT; *dst.get_unchecked_mut(3) = (code & 0x3F) as u8 | TAG_CONT; 4 } else { - panic!("encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", + panic!( + "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}", from_u32_unchecked(code).len_utf8(), code, - dst.len()) + dst.len(), + ) }; from_utf8_unchecked_mut(dst.get_unchecked_mut(..len)) } @@ -515,15 +519,24 @@ impl char { *dst.get_unchecked_mut(1) = 0xDC00 | ((code as u16) & 0x3FF); slice::from_raw_parts_mut(dst.as_mut_ptr(), 2) } else { - panic!("encode_utf16: need {} units to encode U+{:X}, but the buffer has {}", + panic!( + "encode_utf16: need {} units to encode U+{:X}, but the buffer has {}", from_u32_unchecked(code).len_utf16(), code, - dst.len()) + dst.len(), + ) } } } - /// Returns `true` if this `char` is an alphabetic code point, and false if not. + /// Returns `true` if this `char` has the `Alphabetic` property. + /// + /// `Alphabetic` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and + /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt /// /// # Examples /// @@ -547,10 +560,14 @@ impl char { } } - /// Returns `true` if this `char` is lowercase. + /// Returns `true` if this `char` has the `Lowercase` property. /// - /// 'Lowercase' is defined according to the terms of the Unicode Derived Core - /// Property `Lowercase`. + /// `Lowercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and + /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt /// /// # Examples /// @@ -575,10 +592,14 @@ impl char { } } - /// Returns `true` if this `char` is uppercase. + /// Returns `true` if this `char` has the `Uppercase` property. /// - /// 'Uppercase' is defined according to the terms of the Unicode Derived Core - /// Property `Uppercase`. + /// `Uppercase` is described in Chapter 4 (Character Properties) of the [Unicode Standard] and + /// specified in the [Unicode Character Database][ucd] [`DerivedCoreProperties.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt /// /// # Examples /// @@ -603,10 +624,12 @@ impl char { } } - /// Returns `true` if this `char` is whitespace. + /// Returns `true` if this `char` has the `White_Space` property. /// - /// 'Whitespace' is defined according to the terms of the Unicode Derived Core - /// Property `White_Space`. + /// `White_Space` is specified in the [Unicode Character Database][ucd] [`PropList.txt`]. + /// + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`PropList.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/PropList.txt /// /// # Examples /// @@ -630,10 +653,10 @@ impl char { } } - /// Returns `true` if this `char` is alphanumeric. + /// Returns `true` if this `char` satisfies either [`is_alphabetic()`] or [`is_numeric()`]. /// - /// 'Alphanumeric'-ness is defined in terms of the Unicode General Categories - /// `Nd`, `Nl`, `No` and the Derived Core Property `Alphabetic`. + /// [`is_alphabetic()`]: #method.is_alphabetic + /// [`is_numeric()`]: #method.is_numeric /// /// # Examples /// @@ -655,10 +678,15 @@ impl char { self.is_alphabetic() || self.is_numeric() } - /// Returns `true` if this `char` is a control code point. + /// Returns `true` if this `char` has the general category for control codes. /// - /// 'Control code point' is defined in terms of the Unicode General - /// Category `Cc`. + /// Control codes (code points with the general category of `Cc`) are described in Chapter 4 + /// (Character Properties) of the [Unicode Standard] and specified in the [Unicode Character + /// Database][ucd] [`UnicodeData.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt /// /// # Examples /// @@ -675,19 +703,29 @@ impl char { general_category::Cc(self) } - /// Returns `true` if this `char` is an extended grapheme character. + /// Returns `true` if this `char` has the `Grapheme_Extend` property. /// - /// 'Extended grapheme character' is defined in terms of the Unicode Shaping and Rendering - /// Category `Grapheme_Extend`. + /// `Grapheme_Extend` is described in [Unicode Standard Annex #29 (Unicode Text + /// Segmentation)][uax29] and specified in the [Unicode Character Database][ucd] + /// [`DerivedCoreProperties.txt`]. + /// + /// [uax29]: https://www.unicode.org/reports/tr29/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`DerivedCoreProperties.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/DerivedCoreProperties.txt #[inline] pub(crate) fn is_grapheme_extended(self) -> bool { derived_property::Grapheme_Extend(self) } - /// Returns `true` if this `char` is numeric. + /// Returns `true` if this `char` has one of the general categories for numbers. /// - /// 'Numeric'-ness is defined in terms of the Unicode General Categories - /// `Nd`, `Nl`, `No`. + /// The general categories for numbers (`Nd` for decimal digits, `Nl` for letter-like numeric + /// characters, and `No` for other numeric characters) are specified in the [Unicode Character + /// Database][ucd] [`UnicodeData.txt`]. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt /// /// # Examples /// @@ -713,25 +751,29 @@ impl char { } } - /// Returns an iterator that yields the lowercase equivalent of a `char` - /// as one or more `char`s. + /// Returns an iterator that yields the lowercase mapping of this `char` as one or more + /// `char`s. /// - /// If a character does not have a lowercase equivalent, the same character - /// will be returned back by the iterator. + /// If this `char` does not have a lowercase mapping, the iterator yields the same `char`. /// - /// This performs complex unconditional mappings with no tailoring: it maps - /// one Unicode character to its lowercase equivalent according to the - /// [Unicode database] and the additional complex mappings - /// [`SpecialCasing.txt`]. Conditional mappings (based on context or - /// language) are not considered here. + /// If this `char` has a one-to-one lowercase mapping given by the [Unicode Character + /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`. /// - /// For a full reference, see [here][reference]. + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt /// - /// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt + /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields + /// the `char`(s) given by [`SpecialCasing.txt`]. /// - /// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt + /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt /// - /// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 + /// This operation performs an unconditional mapping without tailoring. That is, the conversion + /// is independent of context and language. + /// + /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in + /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ /// /// # Examples /// @@ -774,25 +816,29 @@ impl char { ToLowercase(CaseMappingIter::new(conversions::to_lower(self))) } - /// Returns an iterator that yields the uppercase equivalent of a `char` - /// as one or more `char`s. + /// Returns an iterator that yields the uppercase mapping of this `char` as one or more + /// `char`s. /// - /// If a character does not have an uppercase equivalent, the same character - /// will be returned back by the iterator. + /// If this `char` does not have a uppercase mapping, the iterator yields the same `char`. /// - /// This performs complex unconditional mappings with no tailoring: it maps - /// one Unicode character to its uppercase equivalent according to the - /// [Unicode database] and the additional complex mappings - /// [`SpecialCasing.txt`]. Conditional mappings (based on context or - /// language) are not considered here. + /// If this `char` has a one-to-one uppercase mapping given by the [Unicode Character + /// Database][ucd] [`UnicodeData.txt`], the iterator yields that `char`. /// - /// For a full reference, see [here][reference]. + /// [ucd]: https://www.unicode.org/reports/tr44/ + /// [`UnicodeData.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/UnicodeData.txt /// - /// [Unicode database]: ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt + /// If this `char` requires special considerations (e.g. multiple `char`s) the iterator yields + /// the `char`(s) given by [`SpecialCasing.txt`]. /// - /// [`SpecialCasing.txt`]: ftp://ftp.unicode.org/Public/UNIDATA/SpecialCasing.txt + /// [`SpecialCasing.txt`]: https://www.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt /// - /// [reference]: http://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992 + /// This operation performs an unconditional mapping without tailoring. That is, the conversion + /// is independent of context and language. + /// + /// In the [Unicode Standard], Chapter 4 (Character Properties) discusses case mapping in + /// general and Chapter 3 (Conformance) discusses the default algorithm for case conversion. + /// + /// [Unicode Standard]: https://www.unicode.org/versions/latest/ /// /// # Examples /// From e5daab8c803484946d57d6cfb53c6b01c5eb60b7 Mon Sep 17 00:00:00 2001 From: BO41 Date: Sat, 12 Oct 2019 15:18:17 +0200 Subject: [PATCH 291/545] Fix typo --- src/libcore/task/wake.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/task/wake.rs b/src/libcore/task/wake.rs index 65e293642874..6f841bd2adf4 100644 --- a/src/libcore/task/wake.rs +++ b/src/libcore/task/wake.rs @@ -217,7 +217,7 @@ impl fmt::Debug for Context<'_> { /// This handle encapsulates a [`RawWaker`] instance, which defines the /// executor-specific wakeup behavior. /// -/// Implements [`Clone`], [`trait@Send`], and [`trait@Sync`]. +/// Implements [`Clone`], [`Send`], and [`Sync`]. /// /// [`RawWaker`]: struct.RawWaker.html #[repr(transparent)] From 504cc208448e5dd60186c6ff48d1f82438bc1e59 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 15:35:15 +0200 Subject: [PATCH 292/545] remove confusing and redundant subsection --- src/liballoc/fmt.rs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index bdd1583080bf..1e39b7f822e9 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -80,23 +80,6 @@ //! arguments which have names. Like with positional parameters, it is not //! valid to provide named parameters that are unused by the format string. //! -//! ## Argument types -//! -//! Each argument's type is dictated by the format string. -//! There are various parameters which require a particular type, however. -//! An example is the `{:.*}` syntax, which sets the number of decimal places -//! in floating-point types: -//! -//! ``` -//! let formatted_number = format!("{:.*}", 2, 1.234567); -//! -//! assert_eq!("1.23", formatted_number) -//! ``` -//! -//! If this syntax is used, then the number of characters to print precedes the -//! actual object being formatted, and the number of characters must have the -//! type [`usize`]. -//! //! # Formatting Parameters //! //! Each argument being formatted can be transformed by a number of formatting From a2b2362ce7000bc4e82006979bb34dfc86a9f396 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 16:22:41 +0200 Subject: [PATCH 293/545] do not reference LLVM for our concurrency memory model --- src/libcore/sync/atomic.rs | 52 ++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index c9ccef972c2b..dc0bea02b7b2 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -18,11 +18,11 @@ //! //! Each method takes an [`Ordering`] which represents the strength of //! the memory barrier for that operation. These orderings are the -//! same as [LLVM atomic orderings][1]. For more information see the [nomicon][2]. +//! same as the [C++ atomic orderings][1]. For more information see the [nomicon][2]. //! //! [`Ordering`]: enum.Ordering.html //! -//! [1]: https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations +//! [1]: https://en.cppreference.com/w/cpp/atomic/memory_order //! [2]: ../../../nomicon/atomics.html //! //! Atomic variables are safe to share between threads (they implement [`Sync`]) @@ -217,8 +217,8 @@ unsafe impl Sync for AtomicPtr {} /// operations synchronize other memory while additionally preserving a total order of such /// operations across all threads. /// -/// Rust's memory orderings are [the same as -/// LLVM's](https://llvm.org/docs/LangRef.html#memory-model-for-concurrent-operations). +/// Rust's memory orderings are [the same as those of +/// C++](https://en.cppreference.com/w/cpp/atomic/memory_order). /// /// For more information see the [nomicon]. /// @@ -231,9 +231,9 @@ unsafe impl Sync for AtomicPtr {} pub enum Ordering { /// No ordering constraints, only atomic operations. /// - /// Corresponds to LLVM's [`Monotonic`] ordering. + /// Corresponds to [`memory_order_relaxed`] in C++. /// - /// [`Monotonic`]: https://llvm.org/docs/Atomics.html#monotonic + /// [`memory_order_relaxed`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering #[stable(feature = "rust1", since = "1.0.0")] Relaxed, /// When coupled with a store, all previous operations become ordered @@ -246,11 +246,12 @@ pub enum Ordering { /// /// This ordering is only applicable for operations that can perform a store. /// - /// Corresponds to LLVM's [`Release`] ordering. + /// Corresponds to [`memory_order_release`] in C++. /// - /// [`Release`]: https://llvm.org/docs/Atomics.html#release - /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire - /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic + /// [`Release`]: #Release + /// [`Acquire`]: #Acquire + /// [`Relaxed`]: #Relaxed + /// [`memory_order_release`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering #[stable(feature = "rust1", since = "1.0.0")] Release, /// When coupled with a load, if the loaded value was written by a store operation with @@ -263,11 +264,12 @@ pub enum Ordering { /// /// This ordering is only applicable for operations that can perform a load. /// - /// Corresponds to LLVM's [`Acquire`] ordering. + /// Corresponds to [`memory_order_acquire`] in C++. /// - /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire - /// [`Release`]: https://llvm.org/docs/Atomics.html#release - /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic + /// [`Acquire`]: #Acquire + /// [`Release`]: #Release + /// [`Relaxed`]: #Relaxed + /// [`memory_order_acquire`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering #[stable(feature = "rust1", since = "1.0.0")] Acquire, /// Has the effects of both [`Acquire`] and [`Release`] together: @@ -275,28 +277,28 @@ pub enum Ordering { /// /// Notice that in the case of `compare_and_swap`, it is possible that the operation ends up /// not performing any store and hence it has just [`Acquire`] ordering. However, - /// [`AcqRel`][`AcquireRelease`] will never perform [`Relaxed`] accesses. + /// `AcqRel` will never perform [`Relaxed`] accesses. /// /// This ordering is only applicable for operations that combine both loads and stores. /// - /// Corresponds to LLVM's [`AcquireRelease`] ordering. + /// Corresponds to [`memory_order_acq_rel`] in C++. /// - /// [`AcquireRelease`]: https://llvm.org/docs/Atomics.html#acquirerelease - /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire - /// [`Release`]: https://llvm.org/docs/Atomics.html#release - /// [`Relaxed`]: https://llvm.org/docs/Atomics.html#monotonic + /// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering + /// [`Acquire`]: #Acquire + /// [`Release`]: #Release + /// [`Relaxed`]: #Relaxed #[stable(feature = "rust1", since = "1.0.0")] AcqRel, /// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store /// operations, respectively) with the additional guarantee that all threads see all /// sequentially consistent operations in the same order. /// - /// Corresponds to LLVM's [`SequentiallyConsistent`] ordering. + /// Corresponds to [`memory_order_seq_cst`] in C++. /// - /// [`SequentiallyConsistent`]: https://llvm.org/docs/Atomics.html#sequentiallyconsistent - /// [`Acquire`]: https://llvm.org/docs/Atomics.html#acquire - /// [`Release`]: https://llvm.org/docs/Atomics.html#release - /// [`AcqRel`]: https://llvm.org/docs/Atomics.html#acquirerelease + /// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering + /// [`Acquire`]: #Acquire + /// [`Release`]: #Release + /// [`AcqRel`]: #AcqRel #[stable(feature = "rust1", since = "1.0.0")] SeqCst, } From 63cb2fa1973e1fcff335f858f77496ba2c8d252c Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Sat, 12 Oct 2019 22:47:17 +0800 Subject: [PATCH 294/545] compress the function, remove the assert check. --- src/libsyntax/source_map.rs | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 07c301f524ea..5e569f9dae37 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -878,17 +878,8 @@ impl SourceMap { // Returns the index of the `SourceFile` (in `self.files`) that contains `pos`. pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize { - let files = self.files.borrow(); - let files = &files.source_files; - let count = files.len(); - - // (p - 1) below will not underflow, this follows previous implementation's assumption. - assert!(count >= 1); - let ret = files.binary_search_by_key(&pos, |key| key.start_pos).unwrap_or_else(|p| p - 1); - - assert!(ret < count, "position {} does not resolve to a source location", pos.to_usize()); - - return ret; + self.files.borrow().source_files.binary_search_by_key(&pos, |key| key.start_pos) + .unwrap_or_else(|p| p - 1) } pub fn count_lines(&self) -> usize { From f36355070e1bb4323a5db7bcb1297d3ed7951992 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 17:57:31 +0200 Subject: [PATCH 295/545] it's C++20 --- src/libcore/sync/atomic.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index dc0bea02b7b2..80bfb7ef614d 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -18,7 +18,7 @@ //! //! Each method takes an [`Ordering`] which represents the strength of //! the memory barrier for that operation. These orderings are the -//! same as the [C++ atomic orderings][1]. For more information see the [nomicon][2]. +//! same as the [C++20 atomic orderings][1]. For more information see the [nomicon][2]. //! //! [`Ordering`]: enum.Ordering.html //! @@ -218,7 +218,7 @@ unsafe impl Sync for AtomicPtr {} /// operations across all threads. /// /// Rust's memory orderings are [the same as those of -/// C++](https://en.cppreference.com/w/cpp/atomic/memory_order). +/// C++20](https://en.cppreference.com/w/cpp/atomic/memory_order). /// /// For more information see the [nomicon]. /// @@ -231,7 +231,7 @@ unsafe impl Sync for AtomicPtr {} pub enum Ordering { /// No ordering constraints, only atomic operations. /// - /// Corresponds to [`memory_order_relaxed`] in C++. + /// Corresponds to [`memory_order_relaxed`] in C++20. /// /// [`memory_order_relaxed`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering #[stable(feature = "rust1", since = "1.0.0")] @@ -246,7 +246,7 @@ pub enum Ordering { /// /// This ordering is only applicable for operations that can perform a store. /// - /// Corresponds to [`memory_order_release`] in C++. + /// Corresponds to [`memory_order_release`] in C++20. /// /// [`Release`]: #Release /// [`Acquire`]: #Acquire @@ -264,7 +264,7 @@ pub enum Ordering { /// /// This ordering is only applicable for operations that can perform a load. /// - /// Corresponds to [`memory_order_acquire`] in C++. + /// Corresponds to [`memory_order_acquire`] in C++20. /// /// [`Acquire`]: #Acquire /// [`Release`]: #Release @@ -281,7 +281,7 @@ pub enum Ordering { /// /// This ordering is only applicable for operations that combine both loads and stores. /// - /// Corresponds to [`memory_order_acq_rel`] in C++. + /// Corresponds to [`memory_order_acq_rel`] in C++20. /// /// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering /// [`Acquire`]: #Acquire @@ -293,7 +293,7 @@ pub enum Ordering { /// operations, respectively) with the additional guarantee that all threads see all /// sequentially consistent operations in the same order. /// - /// Corresponds to [`memory_order_seq_cst`] in C++. + /// Corresponds to [`memory_order_seq_cst`] in C++20. /// /// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering /// [`Acquire`]: #Acquire From fabba8f76491698ea93ee5b71791709075d155ba Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 12 Oct 2019 12:00:34 -0400 Subject: [PATCH 296/545] Revert "Auto merge of #64823 - cuviper:min-std, r=Mark-Simulacrum" This reverts commit 000d90b11f7be70ffb7812680f7abc6deb52ec88, reversing changes made to 898f36c83cc28d7921a1d7b3605323dc5cfcf533. --- src/bootstrap/builder.rs | 1 - src/bootstrap/dist.rs | 129 +++++++-------------------- src/tools/build-manifest/src/main.rs | 30 ------- 3 files changed, 33 insertions(+), 127 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 7e3ae7f2cc90..0caf2d9b6db5 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -443,7 +443,6 @@ impl<'a> Builder<'a> { dist::Rustc, dist::DebuggerScripts, dist::Std, - dist::RustcDev, dist::Analysis, dist::Src, dist::PlainSourceTarball, diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index e5a43dcb29f6..d9dff77a30e6 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -637,28 +637,6 @@ impl Step for DebuggerScripts { } } -fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { - // The only true set of target libraries came from the build triple, so - // let's reduce redundant work by only producing archives from that host. - if compiler.host != builder.config.build { - builder.info("\tskipping, not a build host"); - true - } else { - false - } -} - -/// Copy stamped files into an image's `target/lib` directory. -fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) { - let dst = image.join("lib/rustlib").join(target).join("lib"); - t!(fs::create_dir_all(&dst)); - for (path, host) in builder.read_stamp_file(stamp) { - if !host || builder.config.build == target { - builder.copy(&path, &dst.join(path.file_name().unwrap())); - } - } -} - #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub compiler: Compiler, @@ -689,19 +667,44 @@ impl Step for Std { let target = self.target; let name = pkgname(builder, "rust-std"); - let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); - if skip_host_target_lib(builder, compiler) { - return archive; + + // The only true set of target libraries came from the build triple, so + // let's reduce redundant work by only producing archives from that host. + if compiler.host != builder.config.build { + builder.info("\tskipping, not a build host"); + return distdir(builder).join(format!("{}-{}.tar.gz", name, target)); } - builder.ensure(compile::Std { compiler, target }); + // We want to package up as many target libraries as possible + // for the `rust-std` package, so if this is a host target we + // depend on librustc and otherwise we just depend on libtest. + if builder.hosts.iter().any(|t| t == target) { + builder.ensure(compile::Rustc { compiler, target }); + } else { + builder.ensure(compile::Std { compiler, target }); + } let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); let _ = fs::remove_dir_all(&image); - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - let stamp = compile::libstd_stamp(builder, compiler_to_use, target); - copy_target_libs(builder, &target, &image, &stamp); + let dst = image.join("lib/rustlib").join(target); + t!(fs::create_dir_all(&dst)); + let mut src = builder.sysroot_libdir(compiler, target).to_path_buf(); + src.pop(); // Remove the trailing /lib folder from the sysroot_libdir + builder.cp_filtered(&src, &dst, &|path| { + if let Some(name) = path.file_name().and_then(|s| s.to_str()) { + if name == builder.config.rust_codegen_backends_dir.as_str() { + return false + } + if name == "bin" { + return false + } + if name.contains("LLVM") { + return false + } + } + true + }); let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -720,73 +723,7 @@ impl Step for Std { let _time = timeit(builder); builder.run(&mut cmd); builder.remove_dir(&image); - archive - } -} - -#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] -pub struct RustcDev { - pub compiler: Compiler, - pub target: Interned, -} - -impl Step for RustcDev { - type Output = PathBuf; - const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("rustc-dev") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustcDev { - compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.build, - run.target, - ), - target: run.target, - }); - } - - fn run(self, builder: &Builder<'_>) -> PathBuf { - let compiler = self.compiler; - let target = self.target; - - let name = pkgname(builder, "rustc-dev"); - let archive = distdir(builder).join(format!("{}-{}.tar.gz", name, target)); - if skip_host_target_lib(builder, compiler) { - return archive; - } - - builder.ensure(compile::Rustc { compiler, target }); - - let image = tmpdir(builder).join(format!("{}-{}-image", name, target)); - let _ = fs::remove_dir_all(&image); - - let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); - let stamp = compile::librustc_stamp(builder, compiler_to_use, target); - copy_target_libs(builder, &target, &image, &stamp); - - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=Rust-is-ready-to-develop.") - .arg("--image-dir").arg(&image) - .arg("--work-dir").arg(&tmpdir(builder)) - .arg("--output-dir").arg(&distdir(builder)) - .arg(format!("--package-name={}-{}", name, target)) - .arg(format!("--component-name=rustc-dev-{}", target)) - .arg("--legacy-manifest-dirs=rustlib,cargo"); - - builder.info(&format!("Dist rustc-dev stage{} ({} -> {})", - compiler.stage, &compiler.host, target)); - let _time = timeit(builder); - builder.run(&mut cmd); - builder.remove_dir(&image); - archive + distdir(builder).join(format!("{}-{}.tar.gz", name, target)) } } diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index c0d2deab2f8b..f41e7dd17ede 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -399,7 +399,6 @@ impl Builder { fn add_packages_to(&mut self, manifest: &mut Manifest) { let mut package = |name, targets| self.package(name, &mut manifest.pkg, targets); package("rustc", HOSTS); - package("rustc-dev", HOSTS); package("cargo", HOSTS); package("rust-mingw", MINGW); package("rust-std", TARGETS); @@ -427,13 +426,6 @@ impl Builder { "rls-preview", "rust-src", "llvm-tools-preview", "lldb-preview", "rust-analysis", "miri-preview" ]); - - // The compiler libraries are not stable for end users, but `rustc-dev` was only recently - // split out of `rust-std`. We'll include it by default as a transition for nightly users. - if self.rust_release == "nightly" { - self.extend_profile("default", &mut manifest.profiles, &["rustc-dev"]); - self.extend_profile("complete", &mut manifest.profiles, &["rustc-dev"]); - } } fn add_renames_to(&self, manifest: &mut Manifest) { @@ -489,15 +481,6 @@ impl Builder { components.push(host_component("rust-mingw")); } - // The compiler libraries are not stable for end users, but `rustc-dev` was only recently - // split out of `rust-std`. We'll include it by default as a transition for nightly users, - // but ship it as an optional component on the beta and stable channels. - if self.rust_release == "nightly" { - components.push(host_component("rustc-dev")); - } else { - extensions.push(host_component("rustc-dev")); - } - // Tools are always present in the manifest, // but might be marked as unavailable if they weren't built. extensions.extend(vec![ @@ -515,11 +498,6 @@ impl Builder { .filter(|&&target| target != host) .map(|target| Component::from_str("rust-std", target)) ); - extensions.extend( - HOSTS.iter() - .filter(|&&target| target != host) - .map(|target| Component::from_str("rustc-dev", target)) - ); extensions.push(Component::from_str("rust-src", "*")); // If the components/extensions don't actually exist for this @@ -556,14 +534,6 @@ impl Builder { dst.insert(profile_name.to_owned(), pkgs.iter().map(|s| (*s).to_owned()).collect()); } - fn extend_profile(&mut self, - profile_name: &str, - dst: &mut BTreeMap>, - pkgs: &[&str]) { - dst.get_mut(profile_name).expect("existing profile") - .extend(pkgs.iter().map(|s| (*s).to_owned())); - } - fn package(&mut self, pkgname: &str, dst: &mut BTreeMap, From 9a0b9c69600946c8c665705df2cec9ed7ce63d71 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 19:46:03 +0200 Subject: [PATCH 297/545] remove old branch of unwind logic --- src/librustc_codegen_llvm/attributes.rs | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 226074760211..210d6cc16967 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -275,18 +275,7 @@ pub fn from_fn_attrs( } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) { // Special attribute for allocator functions, which can't unwind false - } else if let Some(_) = id { - // rust-lang/rust#64655, rust-lang/rust#63909: to minimize - // risk associated with changing cases where nounwind - // attribute is attached, this code is deliberately mimicking - // old control flow based on whether `id` is `Some` or `None`. - // - // However, in the long term we should either: - // - fold this into final else (i.e. stop inspecting `id`) - // - or, adopt Rust PR #63909. - // - // see also Rust RFC 2753. - + } else { let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); if sig.abi == Abi::Rust || sig.abi == Abi::RustCall { // Any Rust method (or `extern "Rust" fn` or `extern @@ -312,15 +301,6 @@ pub fn from_fn_attrs( // In either case, we mark item as explicitly nounwind. false } - } else { - // assume this can possibly unwind, avoiding the application of a - // `nounwind` attribute below. - // - // (But: See comments in previous branch. Specifically, it is - // unclear whether there is real value in the assumption this - // can unwind. The conservatism here may just be papering over - // a real problem by making some UB a bit harder to hit.) - true }); // Always annotate functions with the target-cpu they are compiled for. From d6ab45d264d8f6d664838360595d2175e44ef9c2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 20:09:24 +0200 Subject: [PATCH 298/545] fix link targets --- src/libcore/sync/atomic.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 80bfb7ef614d..f2822227ac2a 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -248,9 +248,9 @@ pub enum Ordering { /// /// Corresponds to [`memory_order_release`] in C++20. /// - /// [`Release`]: #Release - /// [`Acquire`]: #Acquire - /// [`Relaxed`]: #Relaxed + /// [`Release`]: #variant.Release + /// [`Acquire`]: #variant.Acquire + /// [`Relaxed`]: #variant.Relaxed /// [`memory_order_release`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering #[stable(feature = "rust1", since = "1.0.0")] Release, @@ -266,9 +266,9 @@ pub enum Ordering { /// /// Corresponds to [`memory_order_acquire`] in C++20. /// - /// [`Acquire`]: #Acquire - /// [`Release`]: #Release - /// [`Relaxed`]: #Relaxed + /// [`Acquire`]: #variant.Acquire + /// [`Release`]: #variant.Release + /// [`Relaxed`]: #variant.Relaxed /// [`memory_order_acquire`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering #[stable(feature = "rust1", since = "1.0.0")] Acquire, @@ -284,9 +284,9 @@ pub enum Ordering { /// Corresponds to [`memory_order_acq_rel`] in C++20. /// /// [`memory_order_acq_rel`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Release-Acquire_ordering - /// [`Acquire`]: #Acquire - /// [`Release`]: #Release - /// [`Relaxed`]: #Relaxed + /// [`Acquire`]: #variant.Acquire + /// [`Release`]: #variant.Release + /// [`Relaxed`]: #variant.Relaxed #[stable(feature = "rust1", since = "1.0.0")] AcqRel, /// Like [`Acquire`]/[`Release`]/[`AcqRel`] (for load, store, and load-with-store @@ -296,9 +296,9 @@ pub enum Ordering { /// Corresponds to [`memory_order_seq_cst`] in C++20. /// /// [`memory_order_seq_cst`]: https://en.cppreference.com/w/cpp/atomic/memory_order#Sequentially-consistent_ordering - /// [`Acquire`]: #Acquire - /// [`Release`]: #Release - /// [`AcqRel`]: #AcqRel + /// [`Acquire`]: #variant.Acquire + /// [`Release`]: #variant.Release + /// [`AcqRel`]: #variant.AcqRel #[stable(feature = "rust1", since = "1.0.0")] SeqCst, } From a1a8f33abbf5ee00e6918246f4525c6e4458225f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 19:48:58 +0200 Subject: [PATCH 299/545] update test for nounwind on FFI imports --- src/test/codegen/extern-functions.rs | 19 ----------- src/test/codegen/unwind-extern-imports.rs | 41 +++++++++++++++++++++++ 2 files changed, 41 insertions(+), 19 deletions(-) delete mode 100644 src/test/codegen/extern-functions.rs create mode 100644 src/test/codegen/unwind-extern-imports.rs diff --git a/src/test/codegen/extern-functions.rs b/src/test/codegen/extern-functions.rs deleted file mode 100644 index a935d8865226..000000000000 --- a/src/test/codegen/extern-functions.rs +++ /dev/null @@ -1,19 +0,0 @@ -// compile-flags: -C no-prepopulate-passes - -#![crate_type = "lib"] -#![feature(unwind_attributes)] - -extern { -// CHECK: Function Attrs: nounwind -// CHECK-NEXT: declare void @extern_fn - fn extern_fn(); -// CHECK-NOT: Function Attrs: nounwind -// CHECK: declare void @unwinding_extern_fn - #[unwind(allowed)] - fn unwinding_extern_fn(); -} - -pub unsafe fn force_declare() { - extern_fn(); - unwinding_extern_fn(); -} diff --git a/src/test/codegen/unwind-extern-imports.rs b/src/test/codegen/unwind-extern-imports.rs new file mode 100644 index 000000000000..1c79162536f3 --- /dev/null +++ b/src/test/codegen/unwind-extern-imports.rs @@ -0,0 +1,41 @@ +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] +#![feature(unwind_attributes)] + +extern { +// CHECK: Function Attrs: nounwind +// CHECK-NEXT: declare void @extern_fn + fn extern_fn(); +// CHECK-NOT: Function Attrs: nounwind +// CHECK: declare void @unwinding_extern_fn + #[unwind(allowed)] + fn unwinding_extern_fn(); +// CHECK-NOT: nounwind +// CHECK: declare void @aborting_extern_fn + #[unwind(aborts)] + fn aborting_extern_fn(); // FIXME: we want to have the attribute here +} + +extern "Rust" { +// CHECK-NOT: nounwind +// CHECK: declare void @rust_extern_fn + fn rust_extern_fn(); +// CHECK-NOT: nounwind +// CHECK: declare void @rust_unwinding_extern_fn + #[unwind(allowed)] + fn rust_unwinding_extern_fn(); +// CHECK-NOT: nounwind +// CHECK: declare void @rust_aborting_extern_fn + #[unwind(aborts)] + fn rust_aborting_extern_fn(); // FIXME: we want to have the attribute here +} + +pub unsafe fn force_declare() { + extern_fn(); + unwinding_extern_fn(); + aborting_extern_fn(); + rust_extern_fn(); + rust_unwinding_extern_fn(); + rust_aborting_extern_fn(); +} From 63af27f9ea81a71eb4ea9fb076228993f923cebb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 20:40:03 +0200 Subject: [PATCH 300/545] also (properly) test nounwind on function definitions --- src/test/codegen/nounwind-extern.rs | 6 ------ src/test/codegen/unwind-extern-exports.rs | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) delete mode 100644 src/test/codegen/nounwind-extern.rs create mode 100644 src/test/codegen/unwind-extern-exports.rs diff --git a/src/test/codegen/nounwind-extern.rs b/src/test/codegen/nounwind-extern.rs deleted file mode 100644 index 54d6a8d2794b..000000000000 --- a/src/test/codegen/nounwind-extern.rs +++ /dev/null @@ -1,6 +0,0 @@ -// compile-flags: -O - -#![crate_type = "lib"] - -// CHECK: Function Attrs: norecurse nounwind -pub extern fn foo() {} diff --git a/src/test/codegen/unwind-extern-exports.rs b/src/test/codegen/unwind-extern-exports.rs new file mode 100644 index 000000000000..e7aad9ac7233 --- /dev/null +++ b/src/test/codegen/unwind-extern-exports.rs @@ -0,0 +1,19 @@ +// compile-flags: -C opt-level=0 + +#![crate_type = "lib"] +#![feature(unwind_attributes)] + +// Make sure these all do *not* get the attribute. +// We disable optimizations to prevent LLVM from infering the attribute. +// CHECK-NOT: nounwind + +// "C" ABI +// pub extern fn foo() {} // FIXME right now we don't abort-on-panic but add `nounwind` nevertheless +#[unwind(allowed)] +pub extern fn foo_allowed() {} + +// "Rust" ABI (`extrn "Rust"` could be removed as all `fn` get it implicitly; we leave it +// in for clarity.) +pub extern "Rust" fn bar() {} +#[unwind(allowed)] +pub extern "Rust" fn bar_allowed() {} From 79c623f1462646da2c480b6b1c662aa9cf8afee7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 20:40:10 +0200 Subject: [PATCH 301/545] some typography --- src/librustc_codegen_llvm/attributes.rs | 4 ++-- src/test/codegen/unwind-extern-exports.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index 210d6cc16967..6a36a4a50cbf 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -270,10 +270,10 @@ pub fn from_fn_attrs( // optimize based on this! false } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::UNWIND) { - // If a specific #[unwind] attribute is present, use that + // If a specific #[unwind] attribute is present, use that. true } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_ALLOCATOR_NOUNWIND) { - // Special attribute for allocator functions, which can't unwind + // Special attribute for allocator functions, which can't unwind. false } else { let sig = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); diff --git a/src/test/codegen/unwind-extern-exports.rs b/src/test/codegen/unwind-extern-exports.rs index e7aad9ac7233..ddb3a4f6b4dd 100644 --- a/src/test/codegen/unwind-extern-exports.rs +++ b/src/test/codegen/unwind-extern-exports.rs @@ -12,8 +12,8 @@ #[unwind(allowed)] pub extern fn foo_allowed() {} -// "Rust" ABI (`extrn "Rust"` could be removed as all `fn` get it implicitly; we leave it -// in for clarity.) +// "Rust" +// (`extern "Rust"` could be removed as all `fn` get it implicitly; we leave it in for clarity.) pub extern "Rust" fn bar() {} #[unwind(allowed)] pub extern "Rust" fn bar_allowed() {} From a0106527c65310adb642ac4e407622a8eff3f364 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 20:48:19 +0200 Subject: [PATCH 302/545] fix #[unwind(abort)] for Rust ABIs --- src/librustc_mir/build/mod.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 8c35342d324b..ffb70180bbb4 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -502,24 +502,21 @@ macro_rules! unpack { }; } -fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, abi: Abi) -> bool { - // Not callable from C, so we can safely unwind through these - if abi == Abi::Rust || abi == Abi::RustCall { return false; } - - // Validate `#[unwind]` syntax regardless of platform-specific panic strategy +fn should_abort_on_panic(tcx: TyCtxt<'_>, fn_def_id: DefId, _abi: Abi) -> bool { + // Validate `#[unwind]` syntax regardless of platform-specific panic strategy. let attrs = &tcx.get_attrs(fn_def_id); let unwind_attr = attr::find_unwind_attr(Some(tcx.sess.diagnostic()), attrs); - // We never unwind, so it's not relevant to stop an unwind + // We never unwind, so it's not relevant to stop an unwind. if tcx.sess.panic_strategy() != PanicStrategy::Unwind { return false; } - // We cannot add landing pads, so don't add one + // We cannot add landing pads, so don't add one. if tcx.sess.no_landing_pads() { return false; } // This is a special case: some functions have a C abi but are meant to // unwind anyway. Don't stop them. match unwind_attr { - None => false, // FIXME(#58794) + None => false, // FIXME(#58794); should be `!(abi == Abi::Rust || abi == Abi::RustCall)` Some(UnwindAttr::Allowed) => false, Some(UnwindAttr::Aborts) => true, } From df9335120b2bc2ad4c5f619b3173f20958dcd406 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 21:02:38 +0200 Subject: [PATCH 303/545] test unwind(abort) with Rust ABI --- .../abort-on-panic.rs} | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) rename src/test/ui/{abi/abort-on-c-abi.rs => panics/abort-on-panic.rs} (50%) diff --git a/src/test/ui/abi/abort-on-c-abi.rs b/src/test/ui/panics/abort-on-panic.rs similarity index 50% rename from src/test/ui/abi/abort-on-c-abi.rs rename to src/test/ui/panics/abort-on-panic.rs index 2f08730ec613..c6e8dbf012cf 100644 --- a/src/test/ui/abi/abort-on-c-abi.rs +++ b/src/test/ui/panics/abort-on-panic.rs @@ -14,11 +14,16 @@ use std::io::prelude::*; use std::io; use std::process::{Command, Stdio}; -#[unwind(aborts)] // FIXME(#58794) +#[unwind(aborts)] // FIXME(#58794) should work even without the attribute extern "C" fn panic_in_ffi() { panic!("Test"); } +#[unwind(aborts)] +extern "Rust" fn panic_in_rust_abi() { + panic!("TestRust"); +} + fn test() { let _ = panic::catch_unwind(|| { panic_in_ffi(); }); // The process should have aborted by now. @@ -26,15 +31,34 @@ fn test() { let _ = io::stdout().flush(); } +fn testrust() { + let _ = panic::catch_unwind(|| { panic_in_rust_abi(); }); + // The process should have aborted by now. + io::stdout().write(b"This should never be printed.\n"); + let _ = io::stdout().flush(); +} + fn main() { let args: Vec = env::args().collect(); - if args.len() > 1 && args[1] == "test" { - return test(); + if args.len() > 1 { + // This is inside the self-executed command. + match &*args[1] { + "test" => return test(), + "testrust" => return testrust(), + _ => panic!("bad test"), + } } + // These end up calling the self-execution branches above. let mut p = Command::new(&args[0]) .stdout(Stdio::piped()) .stdin(Stdio::piped()) .arg("test").spawn().unwrap(); assert!(!p.wait().unwrap().success()); + + let mut p = Command::new(&args[0]) + .stdout(Stdio::piped()) + .stdin(Stdio::piped()) + .arg("testrust").spawn().unwrap(); + assert!(!p.wait().unwrap().success()); } From 09d7be39fadf00e0b179bfaef86679fc489e796f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Oct 2019 23:08:57 +0200 Subject: [PATCH 304/545] make tests more robust --- src/test/codegen/unwind-extern-imports.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/codegen/unwind-extern-imports.rs b/src/test/codegen/unwind-extern-imports.rs index 1c79162536f3..485e8bbcd428 100644 --- a/src/test/codegen/unwind-extern-imports.rs +++ b/src/test/codegen/unwind-extern-imports.rs @@ -4,10 +4,10 @@ #![feature(unwind_attributes)] extern { -// CHECK: Function Attrs: nounwind +// CHECK: Function Attrs:{{.*}}nounwind // CHECK-NEXT: declare void @extern_fn fn extern_fn(); -// CHECK-NOT: Function Attrs: nounwind +// CHECK-NOT: Function Attrs:{{.*}}nounwind // CHECK: declare void @unwinding_extern_fn #[unwind(allowed)] fn unwinding_extern_fn(); From 19f26fafdd6e27847a155a2ba8854c8d4ff61597 Mon Sep 17 00:00:00 2001 From: Adam Perry Date: Sat, 12 Oct 2019 14:25:34 -0700 Subject: [PATCH 305/545] Remove the fn pointer #[track_caller] test. The ICE stderr isn't normalizing correctly on some builders. --- .../taking-fn-pointer.rs | 16 -------------- .../taking-fn-pointer.stderr | 21 ------------------- 2 files changed, 37 deletions(-) delete mode 100644 src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs delete mode 100644 src/test/ui/rfc-2091-track-caller/taking-fn-pointer.stderr diff --git a/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs b/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs deleted file mode 100644 index 2882d2d83ff8..000000000000 --- a/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.rs +++ /dev/null @@ -1,16 +0,0 @@ -// failure-status: 101 -// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" -// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" - -#![feature(track_caller)] //~ WARN the feature `track_caller` is incomplete - -#[track_caller] -fn f() {} - -fn call_it(x: fn()) { - x(); -} - -fn main() { - call_it(f); -} diff --git a/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.stderr b/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.stderr deleted file mode 100644 index fb625ae116e7..000000000000 --- a/src/test/ui/rfc-2091-track-caller/taking-fn-pointer.stderr +++ /dev/null @@ -1,21 +0,0 @@ -warning: the feature `track_caller` is incomplete and may cause the compiler to crash - --> $DIR/taking-fn-pointer.rs:5:12 - | -LL | #![feature(track_caller)] - | ^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - -thread 'rustc' panicked at 'index out of bounds: the len is 1 but the index is 1', $SRC_DIR/libcore/slice/mod.rs:LL:COL -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. - -error: internal compiler error: unexpected panic - -note: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports - -note: rustc VERSION running on TARGET - -note: compiler flags: FLAGS - From 429fc9d7b714feebeb78893f9b92b7bdab3b8b93 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sun, 13 Oct 2019 00:18:19 +0200 Subject: [PATCH 306/545] Test an assoc. type in struct member def inside fn --- src/test/ui/save-analysis/issue-64659.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/test/ui/save-analysis/issue-64659.rs diff --git a/src/test/ui/save-analysis/issue-64659.rs b/src/test/ui/save-analysis/issue-64659.rs new file mode 100644 index 000000000000..a3d88a203778 --- /dev/null +++ b/src/test/ui/save-analysis/issue-64659.rs @@ -0,0 +1,10 @@ +// check-pass +// compile-flags: -Zsave-analysis + +trait Trait { type Assoc; } + +fn main() { + struct Data { + x: T::Assoc, + } +} From 7b3cd1b674eb7aa7da8fe00192404e4c9f254ad8 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sat, 5 Oct 2019 01:25:20 +0200 Subject: [PATCH 307/545] Use empty typeck tables when nesting on items without those --- src/librustc_save_analysis/dump_visitor.rs | 18 ++++++++++-------- src/librustc_save_analysis/lib.rs | 4 ++++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index edd2db3c8f73..2f2b8fee27d2 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -115,15 +115,17 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { F: FnOnce(&mut Self), { let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id); - if self.tcx.has_typeck_tables(item_def_id) { - let tables = self.tcx.typeck_tables_of(item_def_id); - let old_tables = self.save_ctxt.tables; - self.save_ctxt.tables = tables; - f(self); - self.save_ctxt.tables = old_tables; + + let tables = if self.tcx.has_typeck_tables(item_def_id) { + self.tcx.typeck_tables_of(item_def_id) } else { - f(self); - } + self.save_ctxt.empty_tables + }; + + let old_tables = self.save_ctxt.tables; + self.save_ctxt.tables = tables; + f(self); + self.save_ctxt.tables = old_tables; } fn span_from_span(&self, span: Span) -> SpanData { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 70b508d47869..1cfb84bb511e 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -48,6 +48,9 @@ use log::{debug, error, info}; pub struct SaveContext<'l, 'tcx> { tcx: TyCtxt<'tcx>, tables: &'l ty::TypeckTables<'tcx>, + /// Used as a fallback when nesting the typeck tables during item processing + /// (if these are not available for that item, e.g. don't own a body) + empty_tables: &'l ty::TypeckTables<'tcx>, access_levels: &'l AccessLevels, span_utils: SpanUtils<'tcx>, config: Config, @@ -1114,6 +1117,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>( let save_ctxt = SaveContext { tcx, tables: &ty::TypeckTables::empty(None), + empty_tables: &ty::TypeckTables::empty(None), access_levels: &access_levels, span_utils: SpanUtils::new(&tcx.sess), config: find_config(config), From eefc1697c5d3ba52c2af46994ed158e4457171b8 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Sun, 13 Oct 2019 01:45:48 +0200 Subject: [PATCH 308/545] Nest typeck tables when processing struct member types --- src/librustc_save_analysis/dump_visitor.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 2f2b8fee27d2..502ae337b527 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -532,12 +532,14 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ); } - for field in def.fields() { - self.process_struct_field_def(field, item.id); - self.visit_ty(&field.ty); - } + self.nest_tables(item.id, |v| { + for field in def.fields() { + v.process_struct_field_def(field, item.id); + v.visit_ty(&field.ty); + } - self.process_generic_params(ty_params, &qualname, item.id); + v.process_generic_params(ty_params, &qualname, item.id); + }); } fn process_enum( From 9f09387f53792740edcb5dd0eea49ab02d3fe891 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 10:46:08 +0200 Subject: [PATCH 309/545] syntax: simplify maybe_annotate_with_ascription --- src/libsyntax/parse/diagnostics.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index f376c19a66cc..42cbe28fc17d 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -2,7 +2,7 @@ use crate::ast::{ self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData, }; -use crate::feature_gate::{feature_err, UnstableFeatures}; +use crate::feature_gate::feature_err; use crate::parse::{SeqSep, PResult, Parser, ParseSess}; use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType}; use crate::parse::token::{self, TokenKind}; @@ -387,14 +387,17 @@ impl<'a> Parser<'a> { let next_pos = sm.lookup_char_pos(self.token.span.lo()); let op_pos = sm.lookup_char_pos(sp.hi()); + let allow_unstable = self.sess.unstable_features.is_nightly_build(); + if likely_path { err.span_suggestion( sp, "maybe write a path separator here", "::".to_string(), - match self.sess.unstable_features { - UnstableFeatures::Disallow => Applicability::MachineApplicable, - _ => Applicability::MaybeIncorrect, + if allow_unstable { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable }, ); } else if op_pos.line != next_pos.line && maybe_expected_semicolon { @@ -404,14 +407,13 @@ impl<'a> Parser<'a> { ";".to_string(), Applicability::MaybeIncorrect, ); - } else if let UnstableFeatures::Disallow = self.sess.unstable_features { - err.span_label(sp, "tried to parse a type due to this"); - } else { + } else if allow_unstable { err.span_label(sp, "tried to parse a type due to this type ascription"); - } - if let UnstableFeatures::Disallow = self.sess.unstable_features { - // Give extra information about type ascription only if it's a nightly compiler. } else { + err.span_label(sp, "tried to parse a type due to this"); + } + if allow_unstable { + // Give extra information about type ascription only if it's a nightly compiler. err.note("`#![feature(type_ascription)]` lets you annotate an expression with a \ type: `: `"); err.note("for more information, see \ From 477a68b720ffa7aad13a2f321af47b1851fe5ddb Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 10:46:41 +0200 Subject: [PATCH 310/545] simplify maybe_stage_features --- src/libsyntax/feature_gate/check.rs | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 9e40b1a26ac1..6008f8f3005b 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -855,25 +855,19 @@ impl UnstableFeatures { pub fn is_nightly_build(&self) -> bool { match *self { UnstableFeatures::Allow | UnstableFeatures::Cheat => true, - _ => false, + UnstableFeatures::Disallow => false, } } } fn maybe_stage_features(span_handler: &Handler, krate: &ast::Crate, unstable: UnstableFeatures) { - let allow_features = match unstable { - UnstableFeatures::Allow => true, - UnstableFeatures::Disallow => false, - UnstableFeatures::Cheat => true - }; - if !allow_features { - for attr in &krate.attrs { - if attr.check_name(sym::feature) { - let release_channel = option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)"); - span_err!(span_handler, attr.span, E0554, - "`#![feature]` may not be used on the {} release channel", - release_channel); - } + if !unstable.is_nightly_build() { + for attr in krate.attrs.iter().filter(|attr| attr.check_name(sym::feature)) { + span_err!( + span_handler, attr.span, E0554, + "`#![feature]` may not be used on the {} release channel", + option_env!("CFG_RELEASE_CHANNEL").unwrap_or("(unknown)") + ); } } } From c6cc29d8cfa0e2c18cd01861df542e7772ae26a6 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 13 Oct 2019 13:19:40 +0900 Subject: [PATCH 311/545] Apply suggestion --- src/librustc/error_codes.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/error_codes.rs b/src/librustc/error_codes.rs index a4c1afc4f1da..78aa9e79e101 100644 --- a/src/librustc/error_codes.rs +++ b/src/librustc/error_codes.rs @@ -2012,11 +2012,11 @@ fn main() { } ``` -Closures cannot be used as `static`. They "save" the environment. -Therefore, having a static closure with a static environment doesn't -really make sense since all you can capture inside it would be variables -with static lifetime. In this condition, better use a function directly. -The easiest fix is to remove `static` keyword. +Closures cannot be used as `static`. They "save" the environment, +and as such a static closure would save only a static environment +which would consist only of variables with a static lifetime. Given +this it would be better to use a proper function. The easiest fix +is to remove the `static` keyword. "##, E0698: r##" From 7effe633b0a729b641c7b8f1f8a21b97f9154b14 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 10:59:05 +0200 Subject: [PATCH 312/545] simplify integer_lit --- src/libsyntax/lib.rs | 1 + src/libsyntax/parse/literal.rs | 15 ++++++--------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 03b00188e255..09a47795a822 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -17,6 +17,7 @@ #![feature(proc_macro_internals)] #![feature(proc_macro_span)] #![feature(try_trait)] +#![feature(slice_patterns)] #![feature(unicode_internals)] #![recursion_limit="256"] diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index fcd5b2782fd6..56a79bfe5d51 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -426,15 +426,12 @@ fn integer_lit(symbol: Symbol, suffix: Option) -> Result 1 && s.as_bytes()[0] == b'0' { - match s.as_bytes()[1] { - b'x' => base = 16, - b'o' => base = 8, - b'b' => base = 2, - _ => {} - } - } + let base = match s.as_bytes() { + [b'0', b'x', ..] => 16, + [b'0', b'o', ..] => 8, + [b'0', b'b', ..] => 2, + _ => 10, + }; let ty = match suffix { Some(suf) => match suf { From 94db37a4f5add29a0a7d993eafc5595f4df01574 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 12:21:01 +0200 Subject: [PATCH 313/545] mbe: reduce panictry! uses. --- src/libsyntax/ext/mbe/macro_parser.rs | 52 ++++++++++++++------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs index d1c50fd85945..0cb5eff1ef29 100644 --- a/src/libsyntax/ext/mbe/macro_parser.rs +++ b/src/libsyntax/ext/mbe/macro_parser.rs @@ -76,7 +76,7 @@ use TokenTreeOrTokenTreeSlice::*; use crate::ast::{Ident, Name}; use crate::ext::mbe::{self, TokenTree}; -use crate::parse::{Directory, ParseSess}; +use crate::parse::{Directory, ParseSess, PResult}; use crate::parse::parser::{Parser, PathStyle}; use crate::parse::token::{self, DocComment, Nonterminal, Token}; use crate::print::pprust; @@ -893,26 +893,30 @@ fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal { } // check at the beginning and the parser checks after each bump p.process_potential_macro_variable(); - match name { - sym::item => match panictry!(p.parse_item()) { + match parse_nt_inner(p, sp, name) { + Ok(nt) => nt, + Err(mut err) => { + err.emit(); + FatalError.raise(); + } + } +} + +fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, Nonterminal> { + Ok(match name { + sym::item => match p.parse_item()? { Some(i) => token::NtItem(i), - None => { - p.fatal("expected an item keyword").emit(); - FatalError.raise(); - } + None => return Err(p.fatal("expected an item keyword")), }, - sym::block => token::NtBlock(panictry!(p.parse_block())), - sym::stmt => match panictry!(p.parse_stmt()) { + sym::block => token::NtBlock(p.parse_block()?), + sym::stmt => match p.parse_stmt()? { Some(s) => token::NtStmt(s), - None => { - p.fatal("expected a statement").emit(); - FatalError.raise(); - } + None => return Err(p.fatal("expected a statement")), }, - sym::pat => token::NtPat(panictry!(p.parse_pat(None))), - sym::expr => token::NtExpr(panictry!(p.parse_expr())), - sym::literal => token::NtLiteral(panictry!(p.parse_literal_maybe_minus())), - sym::ty => token::NtTy(panictry!(p.parse_ty())), + sym::pat => token::NtPat(p.parse_pat(None)?), + sym::expr => token::NtExpr(p.parse_expr()?), + sym::literal => token::NtLiteral(p.parse_literal_maybe_minus()?), + 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) { let span = p.token.span; @@ -920,21 +924,19 @@ fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal { token::NtIdent(Ident::new(name, span), is_raw) } else { let token_str = pprust::token_to_string(&p.token); - p.fatal(&format!("expected ident, found {}", &token_str)).emit(); - FatalError.raise() + return Err(p.fatal(&format!("expected ident, found {}", &token_str))); } - sym::path => token::NtPath(panictry!(p.parse_path(PathStyle::Type))), - sym::meta => token::NtMeta(panictry!(p.parse_attr_item())), - sym::vis => token::NtVis(panictry!(p.parse_visibility(true))), + sym::path => token::NtPath(p.parse_path(PathStyle::Type)?), + sym::meta => token::NtMeta(p.parse_attr_item()?), + sym::vis => token::NtVis(p.parse_visibility(true)?), sym::lifetime => if p.check_lifetime() { token::NtLifetime(p.expect_lifetime().ident) } else { let token_str = pprust::token_to_string(&p.token); - p.fatal(&format!("expected a lifetime, found `{}`", &token_str)).emit(); - FatalError.raise(); + return Err(p.fatal(&format!("expected a lifetime, found `{}`", &token_str))); } // this is not supposed to happen, since it has been checked // when compiling the macro. _ => p.span_bug(sp, "invalid fragment specifier"), - } + }) } From d131abefc3aa53fc6376593729e6931326270503 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 21:50:09 +0200 Subject: [PATCH 314/545] ast: don't use pprust in Debug --- src/libsyntax/ast.rs | 47 ++++++-------------------------------------- 1 file changed, 6 insertions(+), 41 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 023952042e6d..1c78672da1ae 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -70,7 +70,7 @@ impl fmt::Display for Lifetime { /// along with a bunch of supporting information. /// /// E.g., `std::cmp::PartialEq`. -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Path { pub span: Span, /// The segments in the path: the things separated by `::`. @@ -86,12 +86,6 @@ impl PartialEq for Path { } } -impl fmt::Debug for Path { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "path({})", pprust::path_to_string(self)) - } -} - impl fmt::Display for Path { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", pprust::path_to_string(self)) @@ -507,19 +501,13 @@ pub struct Block { pub span: Span, } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Pat { pub id: NodeId, pub kind: PatKind, pub span: Span, } -impl fmt::Debug for Pat { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "pat({}: {})", self.id, pprust::pat_to_string(self)) - } -} - impl Pat { /// Attempt reparsing the pattern as a type. /// This is intended for use by diagnostics. @@ -831,7 +819,7 @@ impl UnOp { } /// A statement -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Stmt { pub id: NodeId, pub kind: StmtKind, @@ -865,18 +853,7 @@ impl Stmt { } } -impl fmt::Debug for Stmt { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "stmt({}: {})", - self.id.to_string(), - pprust::stmt_to_string(self) - ) - } -} - -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum StmtKind { /// A local (let) binding. Local(P), @@ -973,7 +950,7 @@ pub struct AnonConst { } /// An expression. -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Expr { pub id: NodeId, pub kind: ExprKind, @@ -1100,12 +1077,6 @@ impl Expr { } } -impl fmt::Debug for Expr { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "expr({}: {})", self.id, pprust::expr_to_string(self)) - } -} - /// Limit types of a range (inclusive or exclusive) #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)] pub enum RangeLimits { @@ -1660,19 +1631,13 @@ pub enum AssocTyConstraintKind { }, } -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Ty { pub id: NodeId, pub kind: TyKind, pub span: Span, } -impl fmt::Debug for Ty { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "type({})", pprust::ty_to_string(self)) - } -} - #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct BareFnTy { pub unsafety: Unsafety, From 742ec4b9bf7ae7d693da7fe75e5f974e0fafb9d0 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 22:17:46 +0200 Subject: [PATCH 315/545] ast: remove implicit pprust dependency via Display. Instead just use `pprust::path_to_string(..)` where needed. This has two benefits: a) The AST definition is now independent of printing it. (Therefore we get closer to extracting a data-crate.) b) Debugging should be easier as program flow is clearer. --- src/librustc/lint/levels.rs | 3 +- src/librustc_lint/builtin.rs | 5 +-- src/librustc_mir/dataflow/mod.rs | 6 ++-- src/librustc_passes/ast_validation.rs | 3 +- src/librustc_resolve/build_reduced_graph.rs | 3 +- src/librustc_resolve/lib.rs | 5 +-- src/librustc_resolve/macros.rs | 10 ++++-- src/librustdoc/html/render.rs | 3 +- src/libsyntax/ast.rs | 7 ----- src/libsyntax/attr/builtin.rs | 34 +++++++++++++++------ src/libsyntax/ext/expand.rs | 13 +++++--- src/libsyntax/parse/diagnostics.rs | 2 +- src/libsyntax/parse/parser.rs | 6 ++-- src/libsyntax/parse/parser/expr.rs | 7 +++-- src/libsyntax_ext/proc_macro_harness.rs | 28 ++++++++++++----- 15 files changed, 88 insertions(+), 47 deletions(-) diff --git a/src/librustc/lint/levels.rs b/src/librustc/lint/levels.rs index 28afe9730a03..60b1b192d10d 100644 --- a/src/librustc/lint/levels.rs +++ b/src/librustc/lint/levels.rs @@ -12,6 +12,7 @@ use rustc_data_structures::stable_hasher::{HashStable, ToStableHashKey, StableHa use syntax::ast; use syntax::attr; use syntax::feature_gate; +use syntax::print::pprust; use syntax::source_map::MultiSpan; use syntax::symbol::{Symbol, sym}; @@ -285,7 +286,7 @@ impl<'a> LintLevelsBuilder<'a> { tool_ident.span, E0710, "an unknown tool name found in scoped lint: `{}`", - meta_item.path + pprust::path_to_string(&meta_item.path), ); continue; } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index d0a7eab071c3..9a16d0a0715f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -45,7 +45,7 @@ use syntax::feature_gate::{Stability, deprecated_attributes}; use syntax_pos::{BytePos, Span}; use syntax::symbol::{Symbol, kw, sym}; use syntax::errors::{Applicability, DiagnosticBuilder}; -use syntax::print::pprust::expr_to_string; +use syntax::print::pprust::{self, expr_to_string}; use syntax::visit::FnKind; use rustc::hir::{self, GenericParamKind, PatKind}; @@ -701,7 +701,8 @@ impl EarlyLintPass for DeprecatedAttr { } } if attr.check_name(sym::no_start) || attr.check_name(sym::crate_id) { - let msg = format!("use of deprecated attribute `{}`: no longer used.", attr.path); + let path_str = pprust::path_to_string(&attr.path); + let msg = format!("use of deprecated attribute `{}`: no longer used.", path_str); lint_deprecated_attr(cx, attr, &msg, None); } } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 06999abdc8b2..ad0f75d77254 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -1,4 +1,5 @@ use syntax::ast::{self, MetaItem}; +use syntax::print::pprust; use syntax::symbol::{Symbol, sym}; use rustc_index::bit_set::{BitSet, HybridBitSet}; @@ -159,9 +160,8 @@ where if let Some(s) = item.value_str() { return Some(s.to_string()) } else { - sess.span_err( - item.span, - &format!("{} attribute requires a path", item.path)); + let path = pprust::path_to_string(&item.path); + sess.span_err(item.span, &format!("{} attribute requires a path", path)); return None; } } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 0339b85ca55e..43c4f720ad41 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -263,7 +263,8 @@ impl<'a> AstValidator<'a> { let mut err = self.err_handler().struct_span_err(poly.span, &format!("`?Trait` is not permitted in {}", where_)); if is_trait { - err.note(&format!("traits are `?{}` by default", poly.trait_ref.path)); + let path_str = pprust::path_to_string(&poly.trait_ref.path); + err.note(&format!("traits are `?{}` by default", path_str)); } err.emit(); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 030f9b97eb8b..2b8965aa5d41 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -37,6 +37,7 @@ use syntax::ext::expand::AstFragment; use syntax::ext::hygiene::ExpnId; use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; +use syntax::print::pprust; use syntax::{span_err, struct_span_err}; use syntax::source_map::{respan, Spanned}; use syntax::symbol::{kw, sym}; @@ -228,7 +229,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { .span_suggestion( path.span, "try", - format!("crate::{}", path), + format!("crate::{}", pprust::path_to_string(&path)), Applicability::MaybeIncorrect, ) .emit(); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 6aa85820ba8a..ff8f7fc7aa41 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -38,6 +38,7 @@ use rustc_metadata::cstore::CStore; use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext}; use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives}; +use syntax::print::pprust; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; @@ -2011,13 +2012,13 @@ impl<'a> Resolver<'a> { let mut candidates = self.lookup_import_candidates(ident, TypeNS, is_mod); candidates.sort_by_cached_key(|c| { - (c.path.segments.len(), c.path.to_string()) + (c.path.segments.len(), pprust::path_to_string(&c.path)) }); if let Some(candidate) = candidates.get(0) { ( String::from("unresolved import"), Some(( - vec![(ident.span, candidate.path.to_string())], + vec![(ident.span, pprust::path_to_string(&candidate.path))], String::from("a similar path exists"), Applicability::MaybeIncorrect, )), diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 2b87bba83861..49186088fa06 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -21,6 +21,7 @@ use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind}; use syntax::ext::compile_declarative_macro; use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::GateIssue; +use syntax::print::pprust; use syntax::symbol::{Symbol, kw, sym}; use syntax_pos::{Span, DUMMY_SP}; @@ -324,7 +325,8 @@ impl<'a> Resolver<'a> { Ok(if ext.macro_kind() != kind { let expected = kind.descr_expected(); - let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path); + let path_str = pprust::path_to_string(path); + let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path_str); self.session.struct_span_err(path.span, &msg) .span_label(path.span, format!("not {} {}", kind.article(), expected)) .emit(); @@ -805,14 +807,16 @@ impl<'a> Resolver<'a> { } } if let Some(depr) = &stability.rustc_depr { - let (message, lint) = stability::rustc_deprecation_message(depr, &path.to_string()); + let path = pprust::path_to_string(path); + let (message, lint) = stability::rustc_deprecation_message(depr, &path); stability::early_report_deprecation( self.session, &message, depr.suggestion, lint, span ); } } if let Some(depr) = &ext.deprecation { - let (message, lint) = stability::deprecation_message(depr, &path.to_string()); + let path = pprust::path_to_string(&path); + let (message, lint) = stability::deprecation_message(depr, &path); stability::early_report_deprecation(self.session, &message, None, lint, span); } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 1ff71a0024b2..b726ad1e0d63 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -46,6 +46,7 @@ use serialize::json::{ToJson, Json, as_json}; use syntax::ast; use syntax::edition::Edition; use syntax::ext::base::MacroKind; +use syntax::print::pprust; use syntax::source_map::FileName; use syntax::feature_gate::UnstableFeatures; use syntax::symbol::{Symbol, sym}; @@ -2957,7 +2958,7 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) { } fn render_attribute(attr: &ast::MetaItem) -> Option { - let path = attr.path.to_string(); + let path = pprust::path_to_string(&attr.path); if attr.is_word() { Some(path) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1c78672da1ae..79d91125ec4c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -7,7 +7,6 @@ pub use crate::util::parser::ExprPrecedence; use crate::ext::hygiene::ExpnId; use crate::parse::token::{self, DelimToken}; -use crate::print::pprust; use crate::ptr::P; use crate::source_map::{dummy_spanned, respan, Spanned}; use crate::symbol::{kw, sym, Symbol}; @@ -86,12 +85,6 @@ impl PartialEq for Path { } } -impl fmt::Display for Path { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", pprust::path_to_string(self)) - } -} - impl Path { // Convert a span and an identifier to the corresponding // one-segment path. diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 2a8e6b2cc951..efc48256e7ce 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -5,6 +5,7 @@ use crate::early_buffered_lints::BufferedEarlyLintId; use crate::ext::base::ExtCtxt; use crate::feature_gate::{Features, GatedCfg}; use crate::parse::ParseSess; +use crate::print::pprust; use errors::{Applicability, Handler}; use syntax_pos::hygiene::Transparency; @@ -243,7 +244,11 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, let meta = meta.as_ref().unwrap(); let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { - handle_errors(sess, meta.span, AttrError::MultipleItem(meta.path.to_string())); + handle_errors( + sess, + meta.span, + AttrError::MultipleItem(pprust::path_to_string(&meta.path)), + ); return false } if let Some(v) = meta.value_str() { @@ -271,7 +276,10 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, handle_errors( sess, mi.span, - AttrError::UnknownMetaItem(mi.path.to_string(), expected), + AttrError::UnknownMetaItem( + pprust::path_to_string(&mi.path), + expected, + ), ); continue 'outer } @@ -362,7 +370,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, sess, meta.span(), AttrError::UnknownMetaItem( - mi.path.to_string(), + pprust::path_to_string(&mi.path), &["feature", "reason", "issue", "soft"] ), ); @@ -434,7 +442,8 @@ fn find_stability_generic<'a, I>(sess: &ParseSess, sess, meta.span(), AttrError::UnknownMetaItem( - mi.path.to_string(), &["since", "note"], + pprust::path_to_string(&mi.path), + &["since", "note"], ), ); continue 'outer @@ -597,8 +606,11 @@ pub fn eval_condition(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F) !eval_condition(mis[0].meta_item().unwrap(), sess, eval) }, _ => { - span_err!(sess.span_diagnostic, cfg.span, E0537, - "invalid predicate `{}`", cfg.path); + span_err!( + sess.span_diagnostic, cfg.span, E0537, + "invalid predicate `{}`", + pprust::path_to_string(&cfg.path) + ); false } } @@ -653,7 +665,9 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, let get = |meta: &MetaItem, item: &mut Option| { if item.is_some() { handle_errors( - sess, meta.span, AttrError::MultipleItem(meta.path.to_string()) + sess, + meta.span, + AttrError::MultipleItem(pprust::path_to_string(&meta.path)), ); return false } @@ -691,8 +705,10 @@ fn find_deprecation_generic<'a, I>(sess: &ParseSess, handle_errors( sess, meta.span(), - AttrError::UnknownMetaItem(mi.path.to_string(), - &["since", "note"]), + AttrError::UnknownMetaItem( + pprust::path_to_string(&mi.path), + &["since", "note"], + ), ); continue 'outer } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index bbd8da2acef0..1e44f3dd5e59 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -13,6 +13,7 @@ use crate::mut_visit::*; use crate::parse::{DirectoryOwnership, PResult, ParseSess}; use crate::parse::token; use crate::parse::parser::Parser; +use crate::print::pprust; use crate::ptr::P; use crate::symbol::{sym, Symbol}; use crate::tokenstream::{TokenStream, TokenTree}; @@ -388,7 +389,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { "`derive` may only be applied to structs, enums and unions"); if let ast::AttrStyle::Inner = attr.style { let trait_list = derives.iter() - .map(|t| t.to_string()).collect::>(); + .map(|t| pprust::path_to_string(t)) + .collect::>(); let suggestion = format!("#[derive({})]", trait_list.join(", ")); err.span_suggestion( span, "try an outer attribute", suggestion, @@ -587,8 +589,11 @@ 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 = mac.path); + 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(); fragment_kind.dummy(span) @@ -878,7 +883,7 @@ impl<'a> Parser<'a> { err.span_label(span, "caused by the macro expansion here"); let msg = format!( "the usage of `{}!` is likely invalid in {} context", - macro_path, + pprust::path_to_string(¯o_path), kind_name, ); err.note(&msg); diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index f376c19a66cc..df744e403d84 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -854,7 +854,7 @@ impl<'a> Parser<'a> { // This is a best-effort recovery. path.span, "try", - format!("<{}>::{}", ty_str, path), + format!("<{}>::{}", ty_str, pprust::path_to_string(&path)), Applicability::MaybeIncorrect, ) .emit(); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4a457f5a43ca..a19380657fdf 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1454,12 +1454,14 @@ impl<'a> Parser<'a> { `pub(super)`: visible only in the current module's parent `pub(in path::to::module)`: visible only on the specified path"##; + let path_str = pprust::path_to_string(&path); + struct_span_err!(self.sess.span_diagnostic, path.span, E0704, "{}", msg) .help(suggestion) .span_suggestion( path.span, - &format!("make this visible only to module `{}` with `in`", path), - format!("in {}", path), + &format!("make this visible only to module `{}` with `in`", path_str), + format!("in {}", path_str), Applicability::MachineApplicable, ) .emit(); diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index b459782d237c..660bf9b7d65f 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -552,8 +552,11 @@ impl<'a> Parser<'a> { // Report non-fatal diagnostics, keep `x as usize` as an expression // in AST and continue parsing. - let msg = format!("`<` is interpreted as a start of generic \ - arguments for `{}`, not a {}", path, op_noun); + let msg = format!( + "`<` is interpreted as a start of generic arguments for `{}`, not a {}", + pprust::path_to_string(&path), + op_noun, + ); let span_after_type = parser_snapshot_after_type.token.span; let expr = mk_expr(self, P(Ty { span: path.span, diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 9b53bcb841c6..1d48e8231b40 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -7,6 +7,7 @@ use syntax::ext::base::ExtCtxt; use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::ext::proc_macro::is_proc_macro_attr; use syntax::parse::ParseSess; +use syntax::print::pprust; use syntax::ptr::P; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; @@ -248,13 +249,20 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { for attr in &item.attrs { if is_proc_macro_attr(&attr) { if let Some(prev_attr) = found_attr { + let path_str = pprust::path_to_string(&attr.path); let msg = if attr.path.segments[0].ident.name == prev_attr.path.segments[0].ident.name { - format!("only one `#[{}]` attribute is allowed on any given function", - attr.path) + format!( + "only one `#[{}]` attribute is allowed on any given function", + path_str, + ) } else { - format!("`#[{}]` and `#[{}]` attributes cannot both be applied \ - to the same function", attr.path, prev_attr.path) + format!( + "`#[{}]` and `#[{}]` attributes cannot both be applied + to the same function", + path_str, + pprust::path_to_string(&prev_attr.path), + ) }; self.handler.struct_span_err(attr.span, &msg) @@ -280,8 +288,10 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { }; if !is_fn { - let msg = format!("the `#[{}]` attribute may only be used on bare functions", - attr.path); + let msg = format!( + "the `#[{}]` attribute may only be used on bare functions", + pprust::path_to_string(&attr.path), + ); self.handler.span_err(attr.span, &msg); return; @@ -292,8 +302,10 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { } if !self.is_proc_macro_crate { - let msg = format!("the `#[{}]` attribute is only usable with crates of the \ - `proc-macro` crate type", attr.path); + let msg = format!( + "the `#[{}]` attribute is only usable with crates of the `proc-macro` crate type", + pprust::path_to_string(&attr.path), + ); self.handler.span_err(attr.span, &msg); return; From ab8105ee9703882534203237b3a6494842d65a75 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 9 Oct 2019 01:45:40 +0200 Subject: [PATCH 316/545] tokenstream: don't depend on pprust --- src/libsyntax/ext/mbe/macro_rules.rs | 6 ++++-- src/libsyntax/ext/proc_macro_server.rs | 3 ++- src/libsyntax/tokenstream.rs | 9 +-------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs index aec4a6831412..e4fc269d1479 100644 --- a/src/libsyntax/ext/mbe/macro_rules.rs +++ b/src/libsyntax/ext/mbe/macro_rules.rs @@ -174,7 +174,8 @@ fn generic_extension<'cx>( rhses: &[mbe::TokenTree], ) -> Box { if cx.trace_macros() { - trace_macros_note(cx, sp, format!("expanding `{}! {{ {} }}`", name, arg)); + let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone())); + trace_macros_note(cx, sp, msg); } // Which arm's failure should we report? (the one furthest along) @@ -212,7 +213,8 @@ fn generic_extension<'cx>( } if cx.trace_macros() { - trace_macros_note(cx, sp, format!("to `{}`", tts)); + let msg = format!("to `{}`", pprust::tts_to_string(tts.clone())); + trace_macros_note(cx, sp, msg); } let directory = Directory { diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 021ec46d987c..3ed6f4114ae2 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -2,6 +2,7 @@ use crate::ast; use crate::ext::base::ExtCtxt; use crate::parse::{self, token, ParseSess}; use crate::parse::lexer::comments; +use crate::print::pprust; use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}; use errors::Diagnostic; @@ -407,7 +408,7 @@ impl server::TokenStream for Rustc<'_> { ) } fn to_string(&mut self, stream: &Self::TokenStream) -> String { - stream.to_string() + pprust::tts_to_string(stream.clone()) } fn from_token_tree( &mut self, diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index bef12ed4fada..970bacdde13a 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -14,7 +14,6 @@ //! ownership of the original. use crate::parse::token::{self, DelimToken, Token, TokenKind}; -use crate::print::pprust; use syntax_pos::{BytePos, Span, DUMMY_SP}; #[cfg(target_arch = "x86_64")] @@ -23,7 +22,7 @@ use rustc_data_structures::sync::Lrc; use rustc_serialize::{Decoder, Decodable, Encoder, Encodable}; use smallvec::{SmallVec, smallvec}; -use std::{fmt, iter, mem}; +use std::{iter, mem}; #[cfg(test)] mod tests; @@ -507,12 +506,6 @@ impl Cursor { } } -impl fmt::Display for TokenStream { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&pprust::tts_to_string(self.clone())) - } -} - impl Encodable for TokenStream { fn encode(&self, encoder: &mut E) -> Result<(), E::Error> { self.trees().collect::>().encode(encoder) From e6ce3ef80aad6df7e9971d126bb22619ab34927e Mon Sep 17 00:00:00 2001 From: wangxiangqing Date: Sun, 13 Oct 2019 12:59:23 +0800 Subject: [PATCH 317/545] Collect occurrences of for mismatched braces diagnostic Change-Id: I20ba0b62308370ee961141fa1aefc4b9c9f0cb3a --- src/libsyntax/parse/lexer/tokentrees.rs | 18 ++++++++++++++++-- src/libsyntax/parse/token.rs | 2 +- .../mismatched-delim-brace-empty-block.rs | 3 +++ .../mismatched-delim-brace-empty-block.stderr | 11 +++++++++++ 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/parser/mismatched-delim-brace-empty-block.rs create mode 100644 src/test/ui/parser/mismatched-delim-brace-empty-block.stderr diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index e5ba7e45309d..fa494db2f9f3 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -1,3 +1,4 @@ +use rustc_data_structures::fx::FxHashMap; use syntax_pos::Span; use crate::print::pprust::token_to_string; @@ -16,6 +17,7 @@ impl<'a> StringReader<'a> { unmatched_braces: Vec::new(), matching_delim_spans: Vec::new(), last_unclosed_found_span: None, + last_delim_empty_block_spans: FxHashMap::default() }; let res = tt_reader.parse_all_token_trees(); (res, tt_reader.unmatched_braces) @@ -34,6 +36,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, + last_delim_empty_block_spans: FxHashMap } impl<'a> TokenTreesReader<'a> { @@ -121,13 +124,20 @@ impl<'a> TokenTreesReader<'a> { // Correct delimiter. token::CloseDelim(d) if d == delim => { let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); + let close_brace_span = self.token.span; + + if close_brace_span.lo() == open_brace_span.hi() { + let empty_block_span = open_brace_span.to(close_brace_span); + self.last_delim_empty_block_spans.insert(delim, empty_block_span); + } + if self.open_braces.len() == 0 { // 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(); } else { self.matching_delim_spans.push( - (open_brace, open_brace_span, self.token.span), + (open_brace, open_brace_span, close_brace_span), ); } // Parse the close delimiter. @@ -193,13 +203,17 @@ impl<'a> TokenTreesReader<'a> { tts.into() ).into()) }, - token::CloseDelim(_) => { + token::CloseDelim(delim) => { // An unexpected closing delimiter (i.e., there is no // matching opening delimiter). let token_str = token_to_string(&self.token); let msg = format!("unexpected close delimiter: `{}`", token_str); let mut err = self.string_reader.sess.span_diagnostic .struct_span_err(self.token.span, &msg); + + if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) { + err.span_label(span, "this block is empty, you might have not meant to close it"); + } err.span_label(self.token.span, "unexpected close delimiter"); Err(err) }, diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index fd78a2bd5344..6038bcae5aef 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -36,7 +36,7 @@ pub enum BinOpToken { } /// A delimiter token. -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] +#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub enum DelimToken { /// A round parenthesis (i.e., `(` or `)`). Paren, diff --git a/src/test/ui/parser/mismatched-delim-brace-empty-block.rs b/src/test/ui/parser/mismatched-delim-brace-empty-block.rs new file mode 100644 index 000000000000..bcc95c09e1e9 --- /dev/null +++ b/src/test/ui/parser/mismatched-delim-brace-empty-block.rs @@ -0,0 +1,3 @@ +fn main() {} + let _ = (); +} //~ ERROR unexpected close delimiter diff --git a/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr b/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr new file mode 100644 index 000000000000..82fe8930c325 --- /dev/null +++ b/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr @@ -0,0 +1,11 @@ +error: unexpected close delimiter: `}` + --> $DIR/mismatched-delim-brace-empty-block.rs:3:1 + | +LL | fn main() {} + | -- this block is empty, you might have not meant to close it +LL | let _ = (); +LL | } + | ^ unexpected close delimiter + +error: aborting due to previous error + From 888d0ba8df38681c08ac25f30ff4cbfad8168d90 Mon Sep 17 00:00:00 2001 From: wangxiangqing Date: Sun, 13 Oct 2019 12:59:23 +0800 Subject: [PATCH 318/545] Collect occurrences of for mismatched braces diagnostic Change-Id: I20ba0b62308370ee961141fa1aefc4b9c9f0cb3a --- src/libsyntax/parse/lexer/tokentrees.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index fa494db2f9f3..b088d160b923 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -212,7 +212,10 @@ impl<'a> TokenTreesReader<'a> { .struct_span_err(self.token.span, &msg); if let Some(span) = self.last_delim_empty_block_spans.remove(&delim) { - err.span_label(span, "this block is empty, you might have not meant to close it"); + err.span_label( + span, + "this block is empty, you might have not meant to close it" + ); } err.span_label(self.token.span, "unexpected close delimiter"); Err(err) From e58ad8dedfd2befc601363e5f4930e45b201f686 Mon Sep 17 00:00:00 2001 From: qtmlabs Date: Sun, 13 Oct 2019 14:06:25 +0700 Subject: [PATCH 319/545] Fix path to crosstool-ng.sh --- src/ci/docker/dist-armv7-linux/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/dist-armv7-linux/Dockerfile b/src/ci/docker/dist-armv7-linux/Dockerfile index d3ea563eab12..417171a861d4 100644 --- a/src/ci/docker/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/dist-armv7-linux/Dockerfile @@ -3,7 +3,7 @@ FROM ubuntu:16.04 COPY scripts/cross-apt-packages.sh /scripts/ RUN sh /scripts/cross-apt-packages.sh -COPY crosstool-ng.sh /scripts/ +COPY dist-armv7-linux/crosstool-ng.sh /scripts/ RUN sh /scripts/crosstool-ng.sh COPY scripts/rustbuild-setup.sh /scripts/ From cd0e4c32635cf648f70153f0a25974e687ccd197 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Sun, 13 Oct 2019 11:43:26 +0200 Subject: [PATCH 320/545] Implement Error::source on IntoStringError IntoStringError only implemented Error::cause, which is deprecated. This implemements Error::source instead. Error::cause will still work as before, thanks to the default implementation. --- src/libstd/ffi/c_str.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index d7f4cc5d1fda..483f2ba52eca 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -919,7 +919,7 @@ impl Error for IntoStringError { "C string contained non-utf8 bytes" } - fn cause(&self) -> Option<&dyn Error> { + fn source(&self) -> Option<&(dyn Error + 'static)> { Some(&self.error) } } From d488500812424061264a69c9ecfe0247bc00d1af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 13 Oct 2019 00:00:00 +0000 Subject: [PATCH 321/545] Don't discard value names when using address or memory sanitizer The value names are used when reporting issues found by address sanitizer or memory sanitizer. Avoid discarding names when those sanitizers are enabled, unless explicitly requested to do otherwise. --- src/librustc/session/mod.rs | 10 +++++++++- src/test/run-make-fulldeps/sanitizer-address/Makefile | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 9d60221fa3d7..fa2902e4f0ed 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fingerprint::Fingerprint; use crate::lint; use crate::lint::builtin::BuiltinLintDiagnostics; -use crate::session::config::{OutputType, PrintRequest, SwitchWithOptPath}; +use crate::session::config::{OutputType, PrintRequest, Sanitizer, SwitchWithOptPath}; use crate::session::search_paths::{PathKind, SearchPath}; use crate::util::nodemap::{FxHashMap, FxHashSet}; use crate::util::common::{duration_to_secs_str, ErrorReported}; @@ -626,6 +626,14 @@ impl Session { .output_types .contains_key(&OutputType::LlvmAssembly) || self.opts.output_types.contains_key(&OutputType::Bitcode); + + // Address sanitizer and memory sanitizer use alloca name when reporting an issue. + let more_names = match self.opts.debugging_opts.sanitizer { + Some(Sanitizer::Address) => true, + Some(Sanitizer::Memory) => true, + _ => more_names, + }; + self.opts.debugging_opts.fewer_names || !more_names } diff --git a/src/test/run-make-fulldeps/sanitizer-address/Makefile b/src/test/run-make-fulldeps/sanitizer-address/Makefile index 51d8a4a947ad..3a377c32993d 100644 --- a/src/test/run-make-fulldeps/sanitizer-address/Makefile +++ b/src/test/run-make-fulldeps/sanitizer-address/Makefile @@ -24,4 +24,7 @@ endif all: $(RUSTC) -g -Z sanitizer=address -Z print-link-args $(EXTRA_RUSTFLAG) overflow.rs | $(CGREP) librustc_asan + # Verify that stack buffer overflow is detected: $(TMPDIR)/overflow 2>&1 | $(CGREP) stack-buffer-overflow + # Verify that variable name is included in address sanitizer report: + $(TMPDIR)/overflow 2>&1 | $(CGREP) "'xs'" From 37018e0f9b71e7fa4f27632add8be98b4d2c4b44 Mon Sep 17 00:00:00 2001 From: BO41 Date: Sun, 13 Oct 2019 12:12:46 +0200 Subject: [PATCH 322/545] Fix typos in error.rs --- src/libstd/error.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index 4a1bb75d588c..6b9a35fccc4d 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -269,8 +269,8 @@ impl<'a, E: Error + 'a> From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, E: Error + Send + Sync + 'a> From for Box { - /// Converts a type of [`Error`] + [`trait@Send`] + [`trait@Sync`] into a box of - /// dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. + /// Converts a type of [`Error`] + [`Send`] + [`Sync`] into a box of + /// dyn [`Error`] + [`Send`] + [`Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -313,7 +313,7 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box for Box { - /// Converts a [`String`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. + /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -377,7 +377,7 @@ impl From for Box { #[stable(feature = "rust1", since = "1.0.0")] impl<'a> From<&str> for Box { - /// Converts a [`str`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. + /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// [`Error`]: ../error/trait.Error.html /// @@ -420,7 +420,7 @@ impl From<&str> for Box { #[stable(feature = "cow_box_error", since = "1.22.0")] impl<'a, 'b> From> for Box { - /// Converts a [`Cow`] into a box of dyn [`Error`] + [`trait@Send`] + [`trait@Sync`]. + /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// /// [`Cow`]: ../borrow/enum.Cow.html /// [`Error`]: ../error/trait.Error.html From b8e7f761819da1e50171f79e6de95122eef816a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Sun, 13 Oct 2019 12:26:45 +0200 Subject: [PATCH 323/545] Remove Error::cause impls equal to deafult impl --- src/libstd/sync/mpsc/mod.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index 69ecd201063b..c2884a28f3cc 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -1581,10 +1581,6 @@ impl error::Error for SendError { fn description(&self) -> &str { "sending on a closed channel" } - - fn cause(&self) -> Option<&dyn error::Error> { - None - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1624,10 +1620,6 @@ impl error::Error for TrySendError { } } } - - fn cause(&self) -> Option<&dyn error::Error> { - None - } } #[stable(feature = "mpsc_error_conversions", since = "1.24.0")] @@ -1652,10 +1644,6 @@ impl error::Error for RecvError { fn description(&self) -> &str { "receiving on a closed channel" } - - fn cause(&self) -> Option<&dyn error::Error> { - None - } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1685,10 +1673,6 @@ impl error::Error for TryRecvError { } } } - - fn cause(&self) -> Option<&dyn error::Error> { - None - } } #[stable(feature = "mpsc_error_conversions", since = "1.24.0")] @@ -1726,10 +1710,6 @@ impl error::Error for RecvTimeoutError { } } } - - fn cause(&self) -> Option<&dyn error::Error> { - None - } } #[stable(feature = "mpsc_error_conversions", since = "1.24.0")] From cfda050c01bba4a9b2ca9356b317ba22d6da0ca7 Mon Sep 17 00:00:00 2001 From: Cerberuser Date: Sun, 13 Oct 2019 18:48:07 +0700 Subject: [PATCH 324/545] Add `dyn` to `Any` documentation I noticed that in documentation to `Any` trait the old trait object syntax is used, which could be confusing for newcomers, since we generally recommend using `dyn Trait` instead of just `Trait`. This PR changes the documentation comment, so that it uses `&dyn Any`, `&mut dyn Any` and `Box`, correspondingly. --- src/libcore/any.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 85b59162620f..ba0b06796967 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -2,14 +2,14 @@ //! of any `'static` type through runtime reflection. //! //! `Any` itself can be used to get a `TypeId`, and has more features when used -//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and -//! `downcast_ref` methods, to test if the contained value is of a given type, -//! and to get a reference to the inner value as a type. As `&mut Any`, there +//! as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is` +//! and `downcast_ref` methods, to test if the contained value is of a given type, +//! and to get a reference to the inner value as a type. As `&mut dyn Any`, there //! is also the `downcast_mut` method, for getting a mutable reference to the -//! inner value. `Box` adds the `downcast` method, which attempts to +//! inner value. `Box` adds the `downcast` method, which attempts to //! convert to a `Box`. See the [`Box`] documentation for the full details. //! -//! Note that &Any is limited to testing whether a value is of a specified +//! Note that &dyn Any is limited to testing whether a value is of a specified //! concrete type, and cannot be used to test whether a type implements a trait. //! //! [`Box`]: ../../std/boxed/struct.Box.html From 0510bbfb35c4628f4574b6b798d395bfa9f9a218 Mon Sep 17 00:00:00 2001 From: Cerberuser Date: Sun, 13 Oct 2019 19:03:21 +0700 Subject: [PATCH 325/545] Added code element Co-Authored-By: Jonas Schievink --- src/libcore/any.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index ba0b06796967..f75b7a454438 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -9,7 +9,7 @@ //! inner value. `Box` adds the `downcast` method, which attempts to //! convert to a `Box`. See the [`Box`] documentation for the full details. //! -//! Note that &dyn Any is limited to testing whether a value is of a specified +//! Note that `&dyn Any` is limited to testing whether a value is of a specified //! concrete type, and cannot be used to test whether a type implements a trait. //! //! [`Box`]: ../../std/boxed/struct.Box.html From 4a0c487d1bfe483a9341a8e477475dbc4a72b3a6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 11 Oct 2019 10:54:26 +0200 Subject: [PATCH 326/545] syntax: consolidate function parsing in `item.rs` --- src/libsyntax/parse/parser.rs | 285 +----------- src/libsyntax/parse/parser/item.rs | 690 ++++++++++++++++++++--------- src/libsyntax/parse/parser/ty.rs | 3 +- 3 files changed, 491 insertions(+), 487 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4a457f5a43ca..920208c8fd9e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -9,20 +9,19 @@ mod path; pub use path::PathStyle; mod stmt; mod generics; +use super::diagnostics::Error; use crate::ast::{ - self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, Ident, - IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility, - VisibilityKind, Unsafety, + self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, + IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, }; use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep, literal, token}; -use crate::parse::diagnostics::{Error, dummy_arg}; use crate::parse::lexer::UnmatchedBrace; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::token::{Token, TokenKind, DelimToken}; use crate::print::pprust; use crate::ptr::P; -use crate::source_map::{self, respan}; +use crate::source_map::respan; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; use crate::ThinVec; @@ -56,17 +55,6 @@ crate enum BlockMode { Ignore, } -/// The parsing configuration used to parse a parameter list (see `parse_fn_params`). -struct ParamCfg { - /// Is `self` is allowed as the first parameter? - is_self_allowed: bool, - /// Is `...` allowed as the tail of the parameter list? - allow_c_variadic: bool, - /// `is_name_required` decides if, per-parameter, - /// the parameter must have a pattern or just a type. - is_name_required: fn(&token::Token) -> bool, -} - /// Like `maybe_whole_expr`, but for things other than expressions. #[macro_export] macro_rules! maybe_whole { @@ -1105,271 +1093,6 @@ impl<'a> Parser<'a> { res } - /// Parses the parameter list of a function, including the `(` and `)` delimiters. - fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec> { - let sp = self.token.span; - let is_trait_item = cfg.is_self_allowed; - let mut c_variadic = false; - // Parse the arguments, starting out with `self` being possibly allowed... - let (params, _) = self.parse_paren_comma_seq(|p| { - let param = p.parse_param_general(&cfg, is_trait_item); - // ...now that we've parsed the first argument, `self` is no longer allowed. - cfg.is_self_allowed = false; - - match param { - Ok(param) => Ok( - if let TyKind::CVarArgs = param.ty.kind { - c_variadic = true; - if p.token != token::CloseDelim(token::Paren) { - p.span_err( - p.token.span, - "`...` must be the last argument of a C-variadic function", - ); - // FIXME(eddyb) this should probably still push `CVarArgs`. - // Maybe AST validation/HIR lowering should emit the above error? - None - } else { - Some(param) - } - } else { - Some(param) - } - ), - Err(mut e) => { - e.emit(); - let lo = p.prev_span; - // Skip every token until next possible arg or end. - p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); - // Create a placeholder argument for proper arg count (issue #34264). - let span = lo.to(p.prev_span); - Ok(Some(dummy_arg(Ident::new(kw::Invalid, span)))) - } - } - })?; - - let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); - - // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. - self.deduplicate_recovered_params_names(&mut params); - - if c_variadic && params.len() <= 1 { - self.span_err( - sp, - "C-variadic function must be declared with at least one named argument", - ); - } - - Ok(params) - } - - /// Skips unexpected attributes and doc comments in this position and emits an appropriate - /// error. - /// This version of parse param doesn't necessarily require identifier names. - fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> { - let lo = self.token.span; - let attrs = self.parse_outer_attributes()?; - - // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. - if let Some(mut param) = self.parse_self_param()? { - param.attrs = attrs.into(); - return if cfg.is_self_allowed { - Ok(param) - } else { - self.recover_bad_self_param(param, is_trait_item) - }; - } - - let is_name_required = match self.token.kind { - token::DotDotDot => false, - _ => (cfg.is_name_required)(&self.token), - }; - let (pat, ty) = if is_name_required || self.is_named_param() { - debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); - - let pat = self.parse_fn_param_pat()?; - if let Err(mut err) = self.expect(&token::Colon) { - return if let Some(ident) = self.parameter_without_type( - &mut err, - pat, - is_name_required, - cfg.is_self_allowed, - is_trait_item, - ) { - err.emit(); - Ok(dummy_arg(ident)) - } else { - Err(err) - }; - } - - self.eat_incorrect_doc_comment_for_param_type(); - (pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?) - } else { - debug!("parse_param_general ident_to_pat"); - let parser_snapshot_before_ty = self.clone(); - self.eat_incorrect_doc_comment_for_param_type(); - let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic); - if ty.is_ok() && self.token != token::Comma && - self.token != token::CloseDelim(token::Paren) { - // This wasn't actually a type, but a pattern looking like a type, - // so we are going to rollback and re-parse for recovery. - ty = self.unexpected(); - } - match ty { - Ok(ty) => { - let ident = Ident::new(kw::Invalid, self.prev_span); - let bm = BindingMode::ByValue(Mutability::Immutable); - let pat = self.mk_pat_ident(ty.span, bm, ident); - (pat, ty) - } - // If this is a C-variadic argument and we hit an error, return the error. - Err(err) if self.token == token::DotDotDot => return Err(err), - // Recover from attempting to parse the argument as a type without pattern. - Err(mut err) => { - err.cancel(); - mem::replace(self, parser_snapshot_before_ty); - self.recover_arg_parse()? - } - } - }; - - let span = lo.to(self.token.span); - - Ok(Param { - attrs: attrs.into(), - id: ast::DUMMY_NODE_ID, - is_placeholder: false, - pat, - span, - ty, - }) - } - - /// Returns the parsed optional self parameter and whether a self shortcut was used. - /// - /// See `parse_self_param_with_attrs` to collect attributes. - 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.token.kind { - // Preserve hygienic context. - token::Ident(name, _) => { - let span = this.token.span; - this.bump(); - Ident::new(name, span) - } - _ => unreachable!(), - } - }; - // Is `self` `n` tokens ahead? - let is_isolated_self = |this: &Self, n| { - this.is_keyword_ahead(n, &[kw::SelfLower]) - && this.look_ahead(n + 1, |t| t != &token::ModSep) - }; - // Is `mut self` `n` tokens ahead? - let is_isolated_mut_self = |this: &Self, n| { - this.is_keyword_ahead(n, &[kw::Mut]) - && is_isolated_self(this, n + 1) - }; - // Parse `self` or `self: TYPE`. We already know the current token is `self`. - let parse_self_possibly_typed = |this: &mut Self, m| { - let eself_ident = expect_self_ident(this); - let eself_hi = this.prev_span; - let eself = if this.eat(&token::Colon) { - SelfKind::Explicit(this.parse_ty()?, m) - } else { - SelfKind::Value(m) - }; - Ok((eself, eself_ident, eself_hi)) - }; - // Recover for the grammar `*self`, `*const self`, and `*mut self`. - let recover_self_ptr = |this: &mut Self| { - let msg = "cannot pass `self` by raw pointer"; - let span = this.token.span; - this.struct_span_err(span, msg) - .span_label(span, msg) - .emit(); - - Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span)) - }; - - // Parse optional `self` parameter of a method. - // 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.token.kind { - token::BinOp(token::And) => { - let eself = if is_isolated_self(self, 1) { - // `&self` - self.bump(); - SelfKind::Region(None, Mutability::Immutable) - } else if is_isolated_mut_self(self, 1) { - // `&mut self` - self.bump(); - self.bump(); - SelfKind::Region(None, Mutability::Mutable) - } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) { - // `&'lt self` - self.bump(); - let lt = self.expect_lifetime(); - SelfKind::Region(Some(lt), Mutability::Immutable) - } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) { - // `&'lt mut self` - self.bump(); - let lt = self.expect_lifetime(); - self.bump(); - SelfKind::Region(Some(lt), Mutability::Mutable) - } else { - // `¬_self` - return Ok(None); - }; - (eself, expect_self_ident(self), self.prev_span) - } - // `*self` - token::BinOp(token::Star) if is_isolated_self(self, 1) => { - self.bump(); - recover_self_ptr(self)? - } - // `*mut self` and `*const self` - token::BinOp(token::Star) if - self.look_ahead(1, |t| t.is_mutability()) - && is_isolated_self(self, 2) => - { - self.bump(); - self.bump(); - recover_self_ptr(self)? - } - // `self` and `self: TYPE` - token::Ident(..) if is_isolated_self(self, 0) => { - parse_self_possibly_typed(self, Mutability::Immutable)? - } - // `mut self` and `mut self: TYPE` - token::Ident(..) if is_isolated_mut_self(self, 0) => { - self.bump(); - parse_self_possibly_typed(self, Mutability::Mutable)? - } - _ => return Ok(None), - }; - - let eself = source_map::respan(eself_lo.to(eself_hi), eself); - Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident))) - } - - fn is_named_param(&self) -> bool { - let offset = match self.token.kind { - token::Interpolated(ref nt) => match **nt { - token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), - _ => 0, - } - token::BinOp(token::And) | token::AndAnd => 1, - _ if self.token.is_keyword(kw::Mut) => 1, - _ => 0, - }; - - self.look_ahead(offset, |t| t.is_ident()) && - self.look_ahead(offset + 1, |t| t == &token::Colon) - } - fn is_crate_vis(&self) -> bool { self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep) } diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 3c60c88e2aa5..08c624b5539d 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -1,28 +1,23 @@ -use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode, ParamCfg}; - +use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode}; use crate::maybe_whole; use crate::ptr::P; -use crate::ast::{ - self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle, - Item, ItemKind, ImplItem, ImplItemKind, TraitItem, TraitItemKind, - UseTree, UseTreeKind, PathSegment, - IsAuto, Constness, IsAsync, Unsafety, Defaultness, - Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, MethodSig, Block, - ForeignItem, ForeignItemKind, - Ty, TyKind, Generics, GenericBounds, TraitRef, - EnumDef, VariantData, StructField, AnonConst, - Mac, MacDelimiter, -}; +use crate::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle, AnonConst, Item, ItemKind}; +use crate::ast::{ImplItem, ImplItemKind, TraitItem, TraitItemKind, UseTree, UseTreeKind}; +use crate::ast::{PathSegment, IsAuto, Constness, IsAsync, Unsafety, Defaultness}; +use crate::ast::{Visibility, VisibilityKind, Mutability, FnHeader, ForeignItem, ForeignItemKind}; +use crate::ast::{Ty, TyKind, Generics, GenericBounds, TraitRef, EnumDef, VariantData, StructField}; +use crate::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, MethodSig, SelfKind, Param}; use crate::ext::base::DummyResult; use crate::parse::token; use crate::parse::parser::maybe_append; -use crate::parse::diagnostics::Error; +use crate::parse::diagnostics::{Error, dummy_arg}; use crate::tokenstream::{TokenTree, TokenStream}; -use crate::source_map::{respan, Span}; use crate::symbol::{kw, sym}; +use crate::source_map::{self, respan, Span}; +use crate::ThinVec; -use std::mem; use log::debug; +use std::mem; use rustc_target::spec::abi::Abi; use errors::{Applicability, DiagnosticBuilder, DiagnosticId, StashKey}; @@ -412,7 +407,7 @@ impl<'a> Parser<'a> { self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) } - fn mk_item_with_info( + pub(super) fn mk_item_with_info( &self, attrs: Vec, lo: Span, @@ -425,16 +420,6 @@ impl<'a> Parser<'a> { Ok(Some(self.mk_item(span, ident, item, vis, attrs))) } - fn recover_first_param(&mut self) -> &'static str { - match self.parse_outer_attributes() - .and_then(|_| self.parse_self_param()) - .map_err(|mut e| e.cancel()) - { - Ok(Some(_)) => "method", - _ => "function", - } - } - /// This is the fall-through for parsing items. fn parse_macro_use_or_failure( &mut self, @@ -707,9 +692,11 @@ impl<'a> Parser<'a> { Ok(item) } - fn parse_impl_item_(&mut self, - at_end: &mut bool, - mut attrs: Vec) -> PResult<'a, ImplItem> { + fn parse_impl_item_( + &mut self, + at_end: &mut bool, + mut attrs: Vec, + ) -> PResult<'a, ImplItem> { let lo = self.token.span; let vis = self.parse_visibility(false)?; let defaultness = self.parse_defaultness(); @@ -722,8 +709,11 @@ impl<'a> Parser<'a> { (name, kind, generics) } else if self.is_const_item() { self.parse_impl_const()? + } else if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(&vis), at_end)? { + // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! + (Ident::invalid(), ast::ImplItemKind::Macro(mac), Generics::default()) } else { - let (name, inner_attrs, generics, kind) = self.parse_impl_method(&vis, at_end)?; + let (name, inner_attrs, generics, kind) = self.parse_impl_method(at_end)?; attrs.extend(inner_attrs); (name, kind, generics) }; @@ -783,71 +773,6 @@ impl<'a> Parser<'a> { Ok((name, ImplItemKind::Const(typ, expr), Generics::default())) } - /// Parses a method or a macro invocation in a trait impl. - fn parse_impl_method( - &mut self, - vis: &Visibility, - at_end: &mut bool - ) -> PResult<'a, (Ident, Vec, Generics, ImplItemKind)> { - // FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction! - if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? { - // method macro - Ok((Ident::invalid(), vec![], Generics::default(), ast::ImplItemKind::Macro(mac))) - } else { - let (ident, sig, generics) = self.parse_method_sig(|_| true)?; - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body))) - } - } - - /// Parse the "signature", including the identifier, parameters, and generics - /// of a method. The body is not parsed as that differs between `trait`s and `impl`s. - fn parse_method_sig( - &mut self, - is_name_required: fn(&token::Token) -> bool, - ) -> PResult<'a, (Ident, MethodSig, Generics)> { - let header = self.parse_fn_front_matter()?; - let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { - is_self_allowed: true, - allow_c_variadic: false, - is_name_required, - })?; - Ok((ident, MethodSig { header, decl }, generics)) - } - - /// Parses all the "front matter" for a `fn` declaration, up to - /// and including the `fn` keyword: - /// - /// - `const fn` - /// - `unsafe fn` - /// - `const unsafe fn` - /// - `extern fn` - /// - etc. - fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { - let is_const_fn = self.eat_keyword(kw::Const); - let const_span = self.prev_span; - let asyncness = self.parse_asyncness(); - if let IsAsync::Async { .. } = asyncness { - self.ban_async_in_2015(self.prev_span); - } - let asyncness = respan(self.prev_span, asyncness); - let unsafety = self.parse_unsafety(); - let (constness, unsafety, abi) = if is_const_fn { - (respan(const_span, Constness::Const), unsafety, Abi::Rust) - } else { - let abi = self.parse_extern_abi()?; - (respan(self.prev_span, Constness::NotConst), unsafety, abi) - }; - if !self.eat_keyword(kw::Fn) { - // It is possible for `expect_one_of` to recover given the contents of - // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't - // account for this. - if !self.expect_one_of(&[], &[])? { unreachable!() } - } - Ok(FnHeader { constness, unsafety, asyncness, abi }) - } - /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. @@ -957,13 +882,7 @@ impl<'a> Parser<'a> { // trait item macro. (Ident::invalid(), TraitItemKind::Macro(mac), Generics::default()) } else { - // This is somewhat dubious; We don't want to allow - // argument names to be left off if there is a definition... - // - // We don't allow argument names to be left off in edition 2018. - let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?; - let body = self.parse_trait_method_body(at_end, &mut attrs)?; - (ident, TraitItemKind::Method(sig, body), generics) + self.parse_trait_item_method(at_end, &mut attrs)? }; Ok(TraitItem { @@ -991,43 +910,6 @@ impl<'a> Parser<'a> { Ok((ident, TraitItemKind::Const(ty, default), Generics::default())) } - /// Parse the "body" of a method in a trait item definition. - /// This can either be `;` when there's no body, - /// or e.g. a block when the method is a provided one. - fn parse_trait_method_body( - &mut self, - at_end: &mut bool, - attrs: &mut Vec, - ) -> PResult<'a, Option>> { - Ok(match self.token.kind { - token::Semi => { - debug!("parse_trait_method_body(): parsing required method"); - self.bump(); - *at_end = true; - None - } - token::OpenDelim(token::Brace) => { - debug!("parse_trait_method_body(): parsing provided method"); - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - attrs.extend(inner_attrs.iter().cloned()); - Some(body) - } - token::Interpolated(ref nt) => { - match **nt { - token::NtBlock(..) => { - *at_end = true; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - attrs.extend(inner_attrs.iter().cloned()); - Some(body) - } - _ => return self.expected_semi_or_open_brace(), - } - } - _ => return self.expected_semi_or_open_brace(), - }) - } - /// Parses the following grammar: /// /// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] @@ -1194,45 +1076,6 @@ impl<'a> Parser<'a> { Ok(ident) } - /// Parses an item-position function declaration. - fn parse_item_fn( - &mut self, - lo: Span, - vis: Visibility, - attrs: Vec, - header: FnHeader, - ) -> PResult<'a, Option>> { - let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { - is_self_allowed: false, - allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe, - is_name_required: |_| true, - })?; - let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; - let kind = ItemKind::Fn(decl, header, generics, body); - self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs))) - } - - /// Parse the "signature", including the identifier, parameters, and generics of a function. - fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P, Generics)> { - let ident = self.parse_ident()?; - let mut generics = self.parse_generics()?; - let decl = self.parse_fn_decl(cfg, true)?; - generics.where_clause = self.parse_where_clause()?; - Ok((ident, decl, generics)) - } - - /// Parses the parameter list and result type of a function declaration. - pub(super) fn parse_fn_decl( - &mut self, - cfg: ParamCfg, - ret_allow_plus: bool, - ) -> PResult<'a, P> { - Ok(P(FnDecl { - inputs: self.parse_fn_params(cfg)?, - output: self.parse_ret_ty(ret_allow_plus)?, - })) - } - /// Parses `extern` for foreign ABIs modules. /// /// `extern` is expected to have been @@ -1344,32 +1187,6 @@ impl<'a> Parser<'a> { } } - /// Parses a function declaration from a foreign module. - fn parse_item_foreign_fn( - &mut self, - vis: ast::Visibility, - lo: Span, - attrs: Vec, - extern_sp: Span, - ) -> PResult<'a, ForeignItem> { - self.expect_keyword(kw::Fn)?; - let (ident, decl, generics) = self.parse_fn_sig(super::ParamCfg { - is_self_allowed: false, - allow_c_variadic: true, - is_name_required: |_| true, - })?; - let span = lo.to(self.token.span); - self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?; - Ok(ast::ForeignItem { - ident, - attrs, - kind: ForeignItemKind::Fn(decl, generics), - id: DUMMY_NODE_ID, - span, - vis, - }) - } - /// 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) @@ -1910,3 +1727,466 @@ impl<'a> Parser<'a> { }) } } + +/// The parsing configuration used to parse a parameter list (see `parse_fn_params`). +pub(super) struct ParamCfg { + /// Is `self` is allowed as the first parameter? + pub is_self_allowed: bool, + /// Is `...` allowed as the tail of the parameter list? + pub allow_c_variadic: bool, + /// `is_name_required` decides if, per-parameter, + /// the parameter must have a pattern or just a type. + pub is_name_required: fn(&token::Token) -> bool, +} + +/// Parsing of functions and methods. +impl<'a> Parser<'a> { + /// Parses an item-position function declaration. + fn parse_item_fn( + &mut self, + lo: Span, + vis: Visibility, + attrs: Vec, + header: FnHeader, + ) -> PResult<'a, Option>> { + let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { + is_self_allowed: false, + allow_c_variadic: header.abi == Abi::C && header.unsafety == Unsafety::Unsafe, + is_name_required: |_| true, + })?; + let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + let kind = ItemKind::Fn(decl, header, generics, body); + self.mk_item_with_info(attrs, lo, vis, (ident, kind, Some(inner_attrs))) + } + + /// Parses a function declaration from a foreign module. + fn parse_item_foreign_fn( + &mut self, + vis: ast::Visibility, + lo: Span, + attrs: Vec, + extern_sp: Span, + ) -> PResult<'a, ForeignItem> { + self.expect_keyword(kw::Fn)?; + let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { + is_self_allowed: false, + allow_c_variadic: true, + is_name_required: |_| true, + })?; + let span = lo.to(self.token.span); + self.parse_semi_or_incorrect_foreign_fn_body(&ident, extern_sp)?; + Ok(ast::ForeignItem { + ident, + attrs, + kind: ForeignItemKind::Fn(decl, generics), + id: DUMMY_NODE_ID, + span, + vis, + }) + } + + /// Parses a method or a macro invocation in a trait impl. + fn parse_impl_method( + &mut self, + at_end: &mut bool, + ) -> PResult<'a, (Ident, Vec, Generics, ImplItemKind)> { + let (ident, sig, generics) = self.parse_method_sig(|_| true)?; + *at_end = true; + let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body))) + } + + fn parse_trait_item_method( + &mut self, + at_end: &mut bool, + attrs: &mut Vec, + ) -> PResult<'a, (Ident, TraitItemKind, Generics)> { + // This is somewhat dubious; We don't want to allow + // argument names to be left off if there is a definition... + // + // We don't allow argument names to be left off in edition 2018. + let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?; + let body = self.parse_trait_method_body(at_end, attrs)?; + Ok((ident, TraitItemKind::Method(sig, body), generics)) + } + + /// Parse the "body" of a method in a trait item definition. + /// This can either be `;` when there's no body, + /// or e.g. a block when the method is a provided one. + fn parse_trait_method_body( + &mut self, + at_end: &mut bool, + attrs: &mut Vec, + ) -> PResult<'a, Option>> { + Ok(match self.token.kind { + token::Semi => { + debug!("parse_trait_method_body(): parsing required method"); + self.bump(); + *at_end = true; + None + } + token::OpenDelim(token::Brace) => { + debug!("parse_trait_method_body(): parsing provided method"); + *at_end = true; + let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + attrs.extend(inner_attrs.iter().cloned()); + Some(body) + } + token::Interpolated(ref nt) => { + match **nt { + token::NtBlock(..) => { + *at_end = true; + let (inner_attrs, body) = self.parse_inner_attrs_and_block()?; + attrs.extend(inner_attrs.iter().cloned()); + Some(body) + } + _ => return self.expected_semi_or_open_brace(), + } + } + _ => return self.expected_semi_or_open_brace(), + }) + } + + /// Parse the "signature", including the identifier, parameters, and generics + /// of a method. The body is not parsed as that differs between `trait`s and `impl`s. + fn parse_method_sig( + &mut self, + is_name_required: fn(&token::Token) -> bool, + ) -> PResult<'a, (Ident, MethodSig, Generics)> { + let header = self.parse_fn_front_matter()?; + let (ident, decl, generics) = self.parse_fn_sig(ParamCfg { + is_self_allowed: true, + allow_c_variadic: false, + is_name_required, + })?; + Ok((ident, MethodSig { header, decl }, generics)) + } + + /// Parses all the "front matter" for a `fn` declaration, up to + /// and including the `fn` keyword: + /// + /// - `const fn` + /// - `unsafe fn` + /// - `const unsafe fn` + /// - `extern fn` + /// - etc. + fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { + let is_const_fn = self.eat_keyword(kw::Const); + let const_span = self.prev_span; + let asyncness = self.parse_asyncness(); + if let IsAsync::Async { .. } = asyncness { + self.ban_async_in_2015(self.prev_span); + } + let asyncness = respan(self.prev_span, asyncness); + let unsafety = self.parse_unsafety(); + let (constness, unsafety, abi) = if is_const_fn { + (respan(const_span, Constness::Const), unsafety, Abi::Rust) + } else { + let abi = self.parse_extern_abi()?; + (respan(self.prev_span, Constness::NotConst), unsafety, abi) + }; + if !self.eat_keyword(kw::Fn) { + // It is possible for `expect_one_of` to recover given the contents of + // `self.expected_tokens`, therefore, do not use `self.unexpected()` which doesn't + // account for this. + if !self.expect_one_of(&[], &[])? { unreachable!() } + } + Ok(FnHeader { constness, unsafety, asyncness, abi }) + } + + /// Parse the "signature", including the identifier, parameters, and generics of a function. + fn parse_fn_sig(&mut self, cfg: ParamCfg) -> PResult<'a, (Ident, P, Generics)> { + let ident = self.parse_ident()?; + let mut generics = self.parse_generics()?; + let decl = self.parse_fn_decl(cfg, true)?; + generics.where_clause = self.parse_where_clause()?; + Ok((ident, decl, generics)) + } + + /// Parses the parameter list and result type of a function declaration. + pub(super) fn parse_fn_decl( + &mut self, + cfg: ParamCfg, + ret_allow_plus: bool, + ) -> PResult<'a, P> { + Ok(P(FnDecl { + inputs: self.parse_fn_params(cfg)?, + output: self.parse_ret_ty(ret_allow_plus)?, + })) + } + + /// Parses the parameter list of a function, including the `(` and `)` delimiters. + fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec> { + let sp = self.token.span; + let is_trait_item = cfg.is_self_allowed; + let mut c_variadic = false; + // Parse the arguments, starting out with `self` being possibly allowed... + let (params, _) = self.parse_paren_comma_seq(|p| { + let param = p.parse_param_general(&cfg, is_trait_item); + // ...now that we've parsed the first argument, `self` is no longer allowed. + cfg.is_self_allowed = false; + + match param { + Ok(param) => Ok( + if let TyKind::CVarArgs = param.ty.kind { + c_variadic = true; + if p.token != token::CloseDelim(token::Paren) { + p.span_err( + p.token.span, + "`...` must be the last argument of a C-variadic function", + ); + // FIXME(eddyb) this should probably still push `CVarArgs`. + // Maybe AST validation/HIR lowering should emit the above error? + None + } else { + Some(param) + } + } else { + Some(param) + } + ), + Err(mut e) => { + e.emit(); + let lo = p.prev_span; + // Skip every token until next possible arg or end. + p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]); + // Create a placeholder argument for proper arg count (issue #34264). + let span = lo.to(p.prev_span); + Ok(Some(dummy_arg(Ident::new(kw::Invalid, span)))) + } + } + })?; + + let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect(); + + // Replace duplicated recovered params with `_` pattern to avoid unecessary errors. + self.deduplicate_recovered_params_names(&mut params); + + if c_variadic && params.len() <= 1 { + self.span_err( + sp, + "C-variadic function must be declared with at least one named argument", + ); + } + + Ok(params) + } + + /// Skips unexpected attributes and doc comments in this position and emits an appropriate + /// error. + /// This version of parse param doesn't necessarily require identifier names. + fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> { + let lo = self.token.span; + let attrs = self.parse_outer_attributes()?; + + // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here. + if let Some(mut param) = self.parse_self_param()? { + param.attrs = attrs.into(); + return if cfg.is_self_allowed { + Ok(param) + } else { + self.recover_bad_self_param(param, is_trait_item) + }; + } + + let is_name_required = match self.token.kind { + token::DotDotDot => false, + _ => (cfg.is_name_required)(&self.token), + }; + let (pat, ty) = if is_name_required || self.is_named_param() { + debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); + + let pat = self.parse_fn_param_pat()?; + if let Err(mut err) = self.expect(&token::Colon) { + return if let Some(ident) = self.parameter_without_type( + &mut err, + pat, + is_name_required, + cfg.is_self_allowed, + is_trait_item, + ) { + err.emit(); + Ok(dummy_arg(ident)) + } else { + Err(err) + }; + } + + self.eat_incorrect_doc_comment_for_param_type(); + (pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?) + } else { + debug!("parse_param_general ident_to_pat"); + let parser_snapshot_before_ty = self.clone(); + self.eat_incorrect_doc_comment_for_param_type(); + let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic); + if ty.is_ok() && self.token != token::Comma && + self.token != token::CloseDelim(token::Paren) { + // This wasn't actually a type, but a pattern looking like a type, + // so we are going to rollback and re-parse for recovery. + ty = self.unexpected(); + } + match ty { + Ok(ty) => { + let ident = Ident::new(kw::Invalid, self.prev_span); + let bm = BindingMode::ByValue(Mutability::Immutable); + let pat = self.mk_pat_ident(ty.span, bm, ident); + (pat, ty) + } + // If this is a C-variadic argument and we hit an error, return the error. + Err(err) if self.token == token::DotDotDot => return Err(err), + // Recover from attempting to parse the argument as a type without pattern. + Err(mut err) => { + err.cancel(); + mem::replace(self, parser_snapshot_before_ty); + self.recover_arg_parse()? + } + } + }; + + let span = lo.to(self.token.span); + + Ok(Param { + attrs: attrs.into(), + id: ast::DUMMY_NODE_ID, + is_placeholder: false, + pat, + span, + ty, + }) + } + + /// Returns the parsed optional self parameter and whether a self shortcut was used. + /// + /// See `parse_self_param_with_attrs` to collect attributes. + 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.token.kind { + // Preserve hygienic context. + token::Ident(name, _) => { + let span = this.token.span; + this.bump(); + Ident::new(name, span) + } + _ => unreachable!(), + } + }; + // Is `self` `n` tokens ahead? + let is_isolated_self = |this: &Self, n| { + this.is_keyword_ahead(n, &[kw::SelfLower]) + && this.look_ahead(n + 1, |t| t != &token::ModSep) + }; + // Is `mut self` `n` tokens ahead? + let is_isolated_mut_self = |this: &Self, n| { + this.is_keyword_ahead(n, &[kw::Mut]) + && is_isolated_self(this, n + 1) + }; + // Parse `self` or `self: TYPE`. We already know the current token is `self`. + let parse_self_possibly_typed = |this: &mut Self, m| { + let eself_ident = expect_self_ident(this); + let eself_hi = this.prev_span; + let eself = if this.eat(&token::Colon) { + SelfKind::Explicit(this.parse_ty()?, m) + } else { + SelfKind::Value(m) + }; + Ok((eself, eself_ident, eself_hi)) + }; + // Recover for the grammar `*self`, `*const self`, and `*mut self`. + let recover_self_ptr = |this: &mut Self| { + let msg = "cannot pass `self` by raw pointer"; + let span = this.token.span; + this.struct_span_err(span, msg) + .span_label(span, msg) + .emit(); + + Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span)) + }; + + // Parse optional `self` parameter of a method. + // 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.token.kind { + token::BinOp(token::And) => { + let eself = if is_isolated_self(self, 1) { + // `&self` + self.bump(); + SelfKind::Region(None, Mutability::Immutable) + } else if is_isolated_mut_self(self, 1) { + // `&mut self` + self.bump(); + self.bump(); + SelfKind::Region(None, Mutability::Mutable) + } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) { + // `&'lt self` + self.bump(); + let lt = self.expect_lifetime(); + SelfKind::Region(Some(lt), Mutability::Immutable) + } else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) { + // `&'lt mut self` + self.bump(); + let lt = self.expect_lifetime(); + self.bump(); + SelfKind::Region(Some(lt), Mutability::Mutable) + } else { + // `¬_self` + return Ok(None); + }; + (eself, expect_self_ident(self), self.prev_span) + } + // `*self` + token::BinOp(token::Star) if is_isolated_self(self, 1) => { + self.bump(); + recover_self_ptr(self)? + } + // `*mut self` and `*const self` + token::BinOp(token::Star) if + self.look_ahead(1, |t| t.is_mutability()) + && is_isolated_self(self, 2) => + { + self.bump(); + self.bump(); + recover_self_ptr(self)? + } + // `self` and `self: TYPE` + token::Ident(..) if is_isolated_self(self, 0) => { + parse_self_possibly_typed(self, Mutability::Immutable)? + } + // `mut self` and `mut self: TYPE` + token::Ident(..) if is_isolated_mut_self(self, 0) => { + self.bump(); + parse_self_possibly_typed(self, Mutability::Mutable)? + } + _ => return Ok(None), + }; + + let eself = source_map::respan(eself_lo.to(eself_hi), eself); + Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident))) + } + + fn is_named_param(&self) -> bool { + let offset = match self.token.kind { + token::Interpolated(ref nt) => match **nt { + token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon), + _ => 0, + } + token::BinOp(token::And) | token::AndAnd => 1, + _ if self.token.is_keyword(kw::Mut) => 1, + _ => 0, + }; + + self.look_ahead(offset, |t| t.is_ident()) && + self.look_ahead(offset + 1, |t| t == &token::Colon) + } + + fn recover_first_param(&mut self) -> &'static str { + match self.parse_outer_attributes() + .and_then(|_| self.parse_self_param()) + .map_err(|mut e| e.cancel()) + { + Ok(Some(_)) => "method", + _ => "function", + } + } +} diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index 018b5951e6e2..e696ab0804d6 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -1,4 +1,5 @@ use super::{Parser, PResult, PathStyle, PrevTokenKind, TokenType}; +use super::item::ParamCfg; use crate::{maybe_whole, maybe_recover_from_interpolated_ty_qpath}; use crate::ptr::P; @@ -281,7 +282,7 @@ impl<'a> Parser<'a> { let unsafety = self.parse_unsafety(); let abi = self.parse_extern_abi()?; self.expect_keyword(kw::Fn)?; - let cfg = super::ParamCfg { + let cfg = ParamCfg { is_self_allowed: false, allow_c_variadic: true, is_name_required: |_| false, From 4d1a5ade9b8bf83c410250521f489e074fa1f929 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 27 Aug 2019 11:45:03 +0200 Subject: [PATCH 327/545] Introduce FuncId backend type --- src/librustc_codegen_llvm/builder.rs | 1 + src/librustc_codegen_llvm/common.rs | 2 ++ src/librustc_codegen_ssa/README.md | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 4 ++-- src/librustc_codegen_ssa/traits/backend.rs | 2 ++ src/librustc_codegen_ssa/traits/builder.rs | 2 +- src/librustc_codegen_ssa/traits/debuginfo.rs | 2 +- src/librustc_codegen_ssa/traits/declare.rs | 4 ++-- src/librustc_codegen_ssa/traits/misc.rs | 6 +++--- src/librustc_codegen_ssa/traits/mod.rs | 1 + 10 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 71a6067fd48a..a2cbfdfe827c 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -52,6 +52,7 @@ const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr(); impl BackendTypes for Builder<'_, 'll, 'tcx> { type Value = as BackendTypes>::Value; + type FuncId = as BackendTypes>::FuncId; type BasicBlock = as BackendTypes>::BasicBlock; type Type = as BackendTypes>::Type; type Funclet = as BackendTypes>::Funclet; diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 6fbea9646b8a..d1a7b4dd6bf7 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -86,6 +86,8 @@ impl Funclet<'ll> { impl BackendTypes for CodegenCx<'ll, 'tcx> { type Value = &'ll Value; + type FuncId = &'ll Value; + type BasicBlock = &'ll BasicBlock; type Type = &'ll Type; type Funclet = Funclet<'ll>; diff --git a/src/librustc_codegen_ssa/README.md b/src/librustc_codegen_ssa/README.md index c8bb2e7ee996..890b8325fd9c 100644 --- a/src/librustc_codegen_ssa/README.md +++ b/src/librustc_codegen_ssa/README.md @@ -84,7 +84,7 @@ pub trait BuilderMethods<'a, 'tcx>: { fn new_block<'b>( cx: &'a Self::CodegenCx, - llfn: Self::Value, + llfn: Self::FuncId, name: &'b str ) -> Self; /* ... */ diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index d5612d7b072a..50a245f67113 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -30,7 +30,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { debug_context: FunctionDebugContext, - llfn: Bx::Value, + llfn: Bx::FuncId, cx: &'a Bx::CodegenCx, @@ -183,7 +183,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, - llfn: Bx::Value, + llfn: Bx::FuncId, mir: &'a Body<'tcx>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index cb197f51460a..499deaa0fb0c 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -14,6 +14,8 @@ use syntax_pos::symbol::InternedString; pub trait BackendTypes { type Value: CodegenObject; + type FuncId: CodegenObject; + type BasicBlock: Copy; type Type: CodegenObject; type Funclet; diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 1886701fb3a8..b252b20f2295 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -34,7 +34,7 @@ pub trait BuilderMethods<'a, 'tcx>: + HasTargetSpec { - fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Value, name: &'b str) -> Self; + fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::FuncId, name: &'b str) -> Self; fn with_cx(cx: &'a Self::CodegenCx) -> Self; fn build_sibling_block(&self, name: &str) -> Self; fn cx(&self) -> &Self::CodegenCx; diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs index e75f247da961..71594240a9ea 100644 --- a/src/librustc_codegen_ssa/traits/debuginfo.rs +++ b/src/librustc_codegen_ssa/traits/debuginfo.rs @@ -20,7 +20,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes { &self, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, - llfn: Self::Value, + llfn: Self::FuncId, mir: &mir::Body<'_>, ) -> FunctionDebugContext; diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs index 624a982b619e..c087e64feab3 100644 --- a/src/librustc_codegen_ssa/traits/declare.rs +++ b/src/librustc_codegen_ssa/traits/declare.rs @@ -17,13 +17,13 @@ pub trait DeclareMethods<'tcx>: BackendTypes { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Value; + fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::FuncId; /// Declare a Rust function. /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::Value; + fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::FuncId; /// Declare a global with an intention to define it. /// diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index 46c88a6113eb..83435edb98f7 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -11,14 +11,14 @@ pub trait MiscMethods<'tcx>: BackendTypes { &self, ) -> &RefCell, Option>), Self::Value>>; fn check_overflow(&self) -> bool; - fn instances(&self) -> &RefCell, Self::Value>>; + fn instances(&self) -> &RefCell, Self::FuncId>>; fn get_fn(&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>; - fn set_frame_pointer_elimination(&self, llfn: Self::Value); - fn apply_target_cpu_attr(&self, llfn: Self::Value); + fn set_frame_pointer_elimination(&self, llfn: Self::FuncId); + fn apply_target_cpu_attr(&self, llfn: Self::FuncId); fn create_used_variable(&self); } diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index efe4a2557010..22a544c03241 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -88,6 +88,7 @@ pub trait HasCodegen<'tcx>: type CodegenCx: CodegenMethods<'tcx> + BackendTypes< Value = Self::Value, + FuncId = Self::FuncId, BasicBlock = Self::BasicBlock, Type = Self::Type, Funclet = Self::Funclet, From cf858a8ac099e684195d5d9bcb8f547476414739 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Tue, 27 Aug 2019 11:51:53 +0200 Subject: [PATCH 328/545] Remove is_const_integral method from ConstMethods --- src/librustc_codegen_llvm/common.rs | 24 +++++++++++++---------- src/librustc_codegen_ssa/mir/place.rs | 4 ++-- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_codegen_ssa/traits/consts.rs | 4 +--- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index d1a7b4dd6bf7..cc2f1b6776e4 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -245,21 +245,19 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { struct_in_context(self.llcx, elts, packed) } - fn const_to_uint(&self, v: &'ll Value) -> u64 { - unsafe { - llvm::LLVMConstIntGetZExtValue(v) - } - } - - fn is_const_integral(&self, v: &'ll Value) -> bool { - unsafe { - llvm::LLVMIsAConstantInt(v).is_some() + fn const_to_opt_uint(&self, v: &'ll Value) -> Option { + if is_const_integral(v) { + unsafe { + Some(llvm::LLVMConstIntGetZExtValue(v)) + } + } else { + None } } fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option { unsafe { - if self.is_const_integral(v) { + if is_const_integral(v) { let (mut lo, mut hi) = (0u64, 0u64); let success = llvm::LLVMRustConstInt128Get(v, sign_ext, &mut hi, &mut lo); @@ -388,3 +386,9 @@ pub fn struct_in_context( fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 { ((hi as u128) << 64) | (lo as u128) } + +fn is_const_integral(v: &'ll Value) -> bool { + unsafe { + llvm::LLVMIsAConstantInt(v).is_some() + } +} diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 2d97f828f073..1d1bc2a81a2c 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -394,8 +394,8 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { // Statically compute the offset if we can, otherwise just use the element size, // as this will yield the lowest alignment. let layout = self.layout.field(bx, 0); - let offset = if bx.is_const_integral(llindex) { - layout.size.checked_mul(bx.const_to_uint(llindex), bx).unwrap_or(layout.size) + let offset = if let Some(llindex) = bx.const_to_opt_uint(llindex) { + layout.size.checked_mul(llindex, bx).unwrap_or(layout.size) } else { layout.size }; diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 978e7218aa74..3e88c7379daf 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let size = bx.const_usize(dest.layout.size.bytes()); // Use llvm.memset.p0i8.* to initialize all zero arrays - if bx.cx().is_const_integral(v) && bx.cx().const_to_uint(v) == 0 { + if bx.cx().const_to_opt_uint(v) == Some(0) { let fill = bx.cx().const_u8(0); bx.memset(start, fill, size, dest.align, MemFlags::empty()); return bx; diff --git a/src/librustc_codegen_ssa/traits/consts.rs b/src/librustc_codegen_ssa/traits/consts.rs index e7ce03f18361..95ada60fae08 100644 --- a/src/librustc_codegen_ssa/traits/consts.rs +++ b/src/librustc_codegen_ssa/traits/consts.rs @@ -21,11 +21,9 @@ pub trait ConstMethods<'tcx>: BackendTypes { fn const_struct(&self, elts: &[Self::Value], packed: bool) -> Self::Value; - fn const_to_uint(&self, v: Self::Value) -> u64; + fn const_to_opt_uint(&self, v: Self::Value) -> Option; fn const_to_opt_u128(&self, v: Self::Value, sign_ext: bool) -> Option; - fn is_const_integral(&self, v: Self::Value) -> bool; - fn scalar_to_backend( &self, cv: Scalar, From 41d329c10d68d1ddefde134d6c276d384a68d1a1 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 12 Oct 2019 12:36:48 +0200 Subject: [PATCH 329/545] Remove unused method CodegenBackend::diagnostics --- src/librustc_codegen_llvm/lib.rs | 4 ---- src/librustc_codegen_utils/codegen_backend.rs | 1 - 2 files changed, 5 deletions(-) diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 52797e64f7df..6c44c6b8464e 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -258,10 +258,6 @@ impl CodegenBackend for LlvmCodegenBackend { llvm_util::print_version(); } - fn diagnostics(&self) -> &[(&'static str, &'static str)] { - &error_codes::DIAGNOSTICS - } - fn target_features(&self, sess: &Session) -> Vec { target_features(sess) } diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 2e3af8431eed..1077c1f42637 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -25,7 +25,6 @@ pub trait CodegenBackend { fn target_features(&self, _sess: &Session) -> Vec { vec![] } fn print_passes(&self) {} fn print_version(&self) {} - fn diagnostics(&self) -> &[(&'static str, &'static str)] { &[] } fn metadata_loader(&self) -> Box; fn provide(&self, _providers: &mut Providers<'_>); From 5f203d5988e86a23d806c3d16c3a24bcb99610e3 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 12 Oct 2019 12:57:36 +0200 Subject: [PATCH 330/545] Move some provides from cg_llvm to rustc_interface --- src/librustc_codegen_llvm/lib.rs | 5 ----- src/librustc_interface/passes.rs | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 6c44c6b8464e..e675e976358c 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -267,15 +267,10 @@ impl CodegenBackend for LlvmCodegenBackend { } fn provide(&self, providers: &mut ty::query::Providers<'_>) { - rustc_codegen_utils::symbol_names::provide(providers); - rustc_codegen_ssa::back::symbol_export::provide(providers); - rustc_codegen_ssa::base::provide_both(providers); attributes::provide(providers); } fn provide_extern(&self, providers: &mut ty::query::Providers<'_>) { - rustc_codegen_ssa::back::symbol_export::provide_extern(providers); - rustc_codegen_ssa::base::provide_both(providers); attributes::provide_extern(providers); } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index a1dc5b01aba8..0f120bc606ff 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -789,10 +789,15 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { cstore::provide(providers); lint::provide(providers); rustc_lint::provide(providers); + rustc_codegen_utils::symbol_names::provide(providers); + rustc_codegen_ssa::back::symbol_export::provide(providers); + rustc_codegen_ssa::base::provide_both(providers); } pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) { cstore::provide_extern(providers); + rustc_codegen_ssa::back::symbol_export::provide_extern(providers); + rustc_codegen_ssa::base::provide_both(providers); } declare_box_region_type!( From 5f6ddb94a619ba12f83549a65d0e6167e2c08c1c Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 12 Oct 2019 14:49:03 +0200 Subject: [PATCH 331/545] Move span_invalid_monomorphization_error from cg_llvm to cg_ssa The associated long diagnostic didn't get registered before --- src/librustc_codegen_llvm/error_codes.rs | 38 ------------------------ src/librustc_codegen_llvm/intrinsic.rs | 6 +--- src/librustc_codegen_llvm/lib.rs | 4 +-- src/librustc_codegen_ssa/common.rs | 5 ++++ src/librustc_codegen_ssa/error_codes.rs | 35 ++++++++++++++++++++++ 5 files changed, 42 insertions(+), 46 deletions(-) delete mode 100644 src/librustc_codegen_llvm/error_codes.rs diff --git a/src/librustc_codegen_llvm/error_codes.rs b/src/librustc_codegen_llvm/error_codes.rs deleted file mode 100644 index 042e51ed2ba7..000000000000 --- a/src/librustc_codegen_llvm/error_codes.rs +++ /dev/null @@ -1,38 +0,0 @@ -register_diagnostics! { - -E0511: r##" -Invalid monomorphization of an intrinsic function was used. Erroneous code -example: - -```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) -#![feature(platform_intrinsics)] - -extern "platform-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} - -fn main() { - unsafe { simd_add(0, 1); } - // error: invalid monomorphization of `simd_add` intrinsic -} -``` - -The generic type has to be a SIMD type. Example: - -``` -#![feature(repr_simd)] -#![feature(platform_intrinsics)] - -#[repr(simd)] -#[derive(Copy, Clone)] -struct i32x2(i32, i32); - -extern "platform-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} - -unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok! -``` -"##, - -} diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 68d9af09c42b..3df8d4c26903 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -20,9 +20,9 @@ use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc::hir; use syntax::ast::{self, FloatTy}; +use rustc_codegen_ssa::common::span_invalid_monomorphization_error; use rustc_codegen_ssa::traits::*; -use rustc::session::Session; use syntax_pos::Span; use std::cmp::Ordering; @@ -1026,10 +1026,6 @@ fn get_rust_try_fn<'ll, 'tcx>( rust_try } -fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { - span_err!(a, b, E0511, "{}", c); -} - fn generic_simd_intrinsic( bx: &mut Builder<'a, 'll, 'tcx>, name: &str, diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index e675e976358c..fde04a68457d 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -38,7 +38,7 @@ extern crate rustc_fs_util; extern crate rustc_driver as _; #[macro_use] extern crate log; -#[macro_use] extern crate syntax; +extern crate syntax; extern crate syntax_pos; extern crate rustc_errors as errors; @@ -64,8 +64,6 @@ use rustc::util::common::ErrorReported; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_utils::codegen_backend::CodegenBackend; -mod error_codes; - mod back { pub mod archive; pub mod bytecode; diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs index e3aa35ef4eb5..ac39ca984766 100644 --- a/src/librustc_codegen_ssa/common.rs +++ b/src/librustc_codegen_ssa/common.rs @@ -1,6 +1,7 @@ #![allow(non_camel_case_types, non_snake_case)] use rustc::ty::{Ty, TyCtxt}; +use rustc::session::Session; use syntax_pos::Span; use rustc::hir::def_id::DefId; @@ -200,3 +201,7 @@ pub fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind), } } + +pub fn span_invalid_monomorphization_error(a: &Session, b: Span, c: &str) { + span_err!(a, b, E0511, "{}", c); +} diff --git a/src/librustc_codegen_ssa/error_codes.rs b/src/librustc_codegen_ssa/error_codes.rs index 8ff41c275a8f..02e26d8f6ecf 100644 --- a/src/librustc_codegen_ssa/error_codes.rs +++ b/src/librustc_codegen_ssa/error_codes.rs @@ -1,5 +1,40 @@ syntax::register_diagnostics! { +E0511: r##" +Invalid monomorphization of an intrinsic function was used. Erroneous code +example: + +```ignore (error-emitted-at-codegen-which-cannot-be-handled-by-compile_fail) +#![feature(platform_intrinsics)] + +extern "platform-intrinsic" { + fn simd_add(a: T, b: T) -> T; +} + +fn main() { + unsafe { simd_add(0, 1); } + // error: invalid monomorphization of `simd_add` intrinsic +} +``` + +The generic type has to be a SIMD type. Example: + +``` +#![feature(repr_simd)] +#![feature(platform_intrinsics)] + +#[repr(simd)] +#[derive(Copy, Clone)] +struct i32x2(i32, i32); + +extern "platform-intrinsic" { + fn simd_add(a: T, b: T) -> T; +} + +unsafe { simd_add(i32x2(0, 0), i32x2(1, 2)); } // ok! +``` +"##, + E0668: r##" Malformed inline assembly rejected by LLVM. From f1ed3a878622ae6d593bc8aa5974b80831fca9f2 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 Oct 2019 11:28:19 +0200 Subject: [PATCH 332/545] s/FuncId/Function --- src/librustc_codegen_llvm/builder.rs | 2 +- src/librustc_codegen_llvm/common.rs | 2 +- src/librustc_codegen_ssa/README.md | 2 +- src/librustc_codegen_ssa/mir/mod.rs | 4 ++-- src/librustc_codegen_ssa/traits/backend.rs | 2 +- src/librustc_codegen_ssa/traits/builder.rs | 2 +- src/librustc_codegen_ssa/traits/debuginfo.rs | 2 +- src/librustc_codegen_ssa/traits/declare.rs | 4 ++-- src/librustc_codegen_ssa/traits/misc.rs | 6 +++--- src/librustc_codegen_ssa/traits/mod.rs | 2 +- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index a2cbfdfe827c..98be0ae44335 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -52,7 +52,7 @@ const UNNAMED: *const c_char = EMPTY_C_STR.as_ptr(); impl BackendTypes for Builder<'_, 'll, 'tcx> { type Value = as BackendTypes>::Value; - type FuncId = as BackendTypes>::FuncId; + type Function = as BackendTypes>::Function; type BasicBlock = as BackendTypes>::BasicBlock; type Type = as BackendTypes>::Type; type Funclet = as BackendTypes>::Funclet; diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index cc2f1b6776e4..01055bedc682 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -86,7 +86,7 @@ impl Funclet<'ll> { impl BackendTypes for CodegenCx<'ll, 'tcx> { type Value = &'ll Value; - type FuncId = &'ll Value; + type Function = &'ll Value; type BasicBlock = &'ll BasicBlock; type Type = &'ll Type; diff --git a/src/librustc_codegen_ssa/README.md b/src/librustc_codegen_ssa/README.md index 890b8325fd9c..a09a0c22c1ba 100644 --- a/src/librustc_codegen_ssa/README.md +++ b/src/librustc_codegen_ssa/README.md @@ -84,7 +84,7 @@ pub trait BuilderMethods<'a, 'tcx>: { fn new_block<'b>( cx: &'a Self::CodegenCx, - llfn: Self::FuncId, + llfn: Self::Function, name: &'b str ) -> Self; /* ... */ diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 50a245f67113..1a2e796a5b7b 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -30,7 +30,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> { debug_context: FunctionDebugContext, - llfn: Bx::FuncId, + llfn: Bx::Function, cx: &'a Bx::CodegenCx, @@ -183,7 +183,7 @@ impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> { pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( cx: &'a Bx::CodegenCx, - llfn: Bx::FuncId, + llfn: Bx::Function, mir: &'a Body<'tcx>, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 499deaa0fb0c..a7faf4eaf102 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -14,7 +14,7 @@ use syntax_pos::symbol::InternedString; pub trait BackendTypes { type Value: CodegenObject; - type FuncId: CodegenObject; + type Function: CodegenObject; type BasicBlock: Copy; type Type: CodegenObject; diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index b252b20f2295..62b5bcbb6c9d 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -34,7 +34,7 @@ pub trait BuilderMethods<'a, 'tcx>: + HasTargetSpec { - fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::FuncId, name: &'b str) -> Self; + fn new_block<'b>(cx: &'a Self::CodegenCx, llfn: Self::Function, name: &'b str) -> Self; fn with_cx(cx: &'a Self::CodegenCx) -> Self; fn build_sibling_block(&self, name: &str) -> Self; fn cx(&self) -> &Self::CodegenCx; diff --git a/src/librustc_codegen_ssa/traits/debuginfo.rs b/src/librustc_codegen_ssa/traits/debuginfo.rs index 71594240a9ea..989e6cf9dcaf 100644 --- a/src/librustc_codegen_ssa/traits/debuginfo.rs +++ b/src/librustc_codegen_ssa/traits/debuginfo.rs @@ -20,7 +20,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes { &self, instance: Instance<'tcx>, sig: ty::FnSig<'tcx>, - llfn: Self::FuncId, + llfn: Self::Function, mir: &mir::Body<'_>, ) -> FunctionDebugContext; diff --git a/src/librustc_codegen_ssa/traits/declare.rs b/src/librustc_codegen_ssa/traits/declare.rs index c087e64feab3..cd42044e48df 100644 --- a/src/librustc_codegen_ssa/traits/declare.rs +++ b/src/librustc_codegen_ssa/traits/declare.rs @@ -17,13 +17,13 @@ pub trait DeclareMethods<'tcx>: BackendTypes { /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::FuncId; + fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Function; /// Declare a Rust function. /// /// If there’s a value with the same name already declared, the function will /// update the declaration and return existing Value instead. - fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::FuncId; + fn declare_fn(&self, name: &str, sig: ty::PolyFnSig<'tcx>) -> Self::Function; /// Declare a global with an intention to define it. /// diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index 83435edb98f7..fc704d55fd9b 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -11,14 +11,14 @@ pub trait MiscMethods<'tcx>: BackendTypes { &self, ) -> &RefCell, Option>), Self::Value>>; fn check_overflow(&self) -> bool; - fn instances(&self) -> &RefCell, Self::FuncId>>; + fn instances(&self) -> &RefCell, Self::Function>>; fn get_fn(&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>; - fn set_frame_pointer_elimination(&self, llfn: Self::FuncId); - fn apply_target_cpu_attr(&self, llfn: Self::FuncId); + fn set_frame_pointer_elimination(&self, llfn: Self::Function); + fn apply_target_cpu_attr(&self, llfn: Self::Function); fn create_used_variable(&self); } diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index 22a544c03241..4318ef16494a 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -88,7 +88,7 @@ pub trait HasCodegen<'tcx>: type CodegenCx: CodegenMethods<'tcx> + BackendTypes< Value = Self::Value, - FuncId = Self::FuncId, + Function = Self::Function, BasicBlock = Self::BasicBlock, Type = Self::Type, Funclet = Self::Funclet, From dad8ddbfdd86556fa8a5a287d0256c74ead59f59 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 Oct 2019 11:45:34 +0200 Subject: [PATCH 333/545] Inline functions from cg_ssa::callee and remove the mod Fixes #65271 --- src/librustc_codegen_llvm/context.rs | 19 +++++++-- src/librustc_codegen_ssa/base.rs | 12 +++--- src/librustc_codegen_ssa/callee.rs | 53 -------------------------- src/librustc_codegen_ssa/lib.rs | 1 - src/librustc_codegen_ssa/meth.rs | 10 ++++- src/librustc_codegen_ssa/mir/rvalue.rs | 11 +++++- 6 files changed, 40 insertions(+), 66 deletions(-) delete mode 100644 src/librustc_codegen_ssa/callee.rs diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 7ca226914a5a..6b3caf80d85e 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -20,7 +20,6 @@ use rustc::ty::layout::{ use rustc::ty::{self, Ty, TyCtxt, Instance}; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; -use rustc_codegen_ssa::callee::resolve_and_get_fn; use rustc_codegen_ssa::base::wants_msvc_seh; use crate::callee::get_fn; @@ -362,7 +361,14 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { let tcx = self.tcx; let llfn = match tcx.lang_items().eh_personality() { Some(def_id) if !wants_msvc_seh(self.sess()) => { - resolve_and_get_fn(self, def_id, tcx.intern_substs(&[])) + self.get_fn( + ty::Instance::resolve( + tcx, + ty::ParamEnv::reveal_all(), + def_id, + tcx.intern_substs(&[]), + ).unwrap() + ) } _ => { let name = if wants_msvc_seh(self.sess()) { @@ -390,7 +396,14 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { 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 = resolve_and_get_fn(self, def_id, tcx.intern_substs(&[])); + let llfn = self.get_fn( + ty::Instance::resolve( + tcx, + ty::ParamEnv::reveal_all(), + def_id, + tcx.intern_substs(&[]), + ).unwrap() + ); unwresume.set(Some(llfn)); return llfn; } diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 935087714a7e..18680ba73d6b 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -36,7 +36,6 @@ use crate::mir::place::PlaceRef; use crate::back::write::{OngoingCodegen, start_async_codegen, submit_pre_lto_module_to_llvm, submit_post_lto_module_to_llvm}; use crate::{MemFlags, CrateInfo}; -use crate::callee; use crate::common::{RealPredicate, TypeKind, IntPredicate}; use crate::meth; use crate::mir; @@ -455,10 +454,13 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' let (start_fn, args) = if use_start_lang_item { let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); - let start_fn = callee::resolve_and_get_fn( - cx, - start_def_id, - cx.tcx().intern_substs(&[main_ret_ty.into()]), + let start_fn = cx.get_fn( + ty::Instance::resolve( + cx.tcx(), + ty::ParamEnv::reveal_all(), + start_def_id, + cx.tcx().intern_substs(&[main_ret_ty.into()]), + ).unwrap() ); (start_fn, vec![bx.pointercast(rust_main, cx.type_ptr_to(cx.type_i8p())), arg_argc, arg_argv]) diff --git a/src/librustc_codegen_ssa/callee.rs b/src/librustc_codegen_ssa/callee.rs deleted file mode 100644 index 6ba6774cbf88..000000000000 --- a/src/librustc_codegen_ssa/callee.rs +++ /dev/null @@ -1,53 +0,0 @@ -use crate::traits::*; -use rustc::ty; -use rustc::ty::subst::SubstsRef; -use rustc::hir::def_id::DefId; - -pub fn resolve_and_get_fn<'tcx, Cx: CodegenMethods<'tcx>>( - cx: &Cx, - def_id: DefId, - substs: SubstsRef<'tcx>, -) -> Cx::Value { - cx.get_fn( - ty::Instance::resolve( - cx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - substs - ).unwrap() - ) -} - -pub fn resolve_and_get_fn_for_ptr<'tcx, - Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx> ->( - cx: &Cx, - def_id: DefId, - substs: SubstsRef<'tcx>, -) -> Cx::Value { - cx.get_fn( - ty::Instance::resolve_for_fn_ptr( - cx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - substs - ).unwrap() - ) -} - -pub fn resolve_and_get_fn_for_vtable<'tcx, - Cx: Backend<'tcx> + MiscMethods<'tcx> + TypeMethods<'tcx> ->( - cx: &Cx, - def_id: DefId, - substs: SubstsRef<'tcx>, -) -> Cx::Value { - cx.get_fn( - ty::Instance::resolve_for_vtable( - cx.tcx(), - ty::ParamEnv::reveal_all(), - def_id, - substs - ).unwrap() - ) -} diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index d700001430e2..55e465091aac 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -41,7 +41,6 @@ pub mod traits; pub mod mir; pub mod debuginfo; pub mod base; -pub mod callee; pub mod glue; pub mod meth; pub mod mono_item; diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 7fe9f5f25130..5c177fd7d6d2 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -1,6 +1,5 @@ use rustc_target::abi::call::FnType; -use crate::callee; use crate::traits::*; use rustc::ty::{self, Ty, Instance}; @@ -92,7 +91,14 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( let methods = methods.cloned().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { - callee::resolve_and_get_fn_for_vtable(cx, def_id, substs) + cx.get_fn( + ty::Instance::resolve_for_vtable( + cx.tcx(), + ty::ParamEnv::reveal_all(), + def_id, + substs, + ).unwrap() + ) }) }); diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 3e88c7379daf..2b9f8aabdd46 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -10,7 +10,6 @@ use syntax::source_map::{DUMMY_SP, Span}; use crate::base; use crate::MemFlags; -use crate::callee; use crate::common::{self, RealPredicate, IntPredicate}; use crate::traits::*; @@ -190,7 +189,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("reifying a fn ptr that requires const arguments"); } OperandValue::Immediate( - callee::resolve_and_get_fn_for_ptr(bx.cx(), def_id, substs)) + bx.get_fn( + ty::Instance::resolve_for_fn_ptr( + bx.tcx(), + ty::ParamEnv::reveal_all(), + def_id, + substs + ).unwrap() + ) + ) } _ => { bug!("{} cannot be reified to a fn ptr", operand.layout.ty) From bcb01bca86b4ebe10501fb918bb807edc34a7a1b Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 Oct 2019 12:05:40 +0200 Subject: [PATCH 334/545] Remove MiscMethods::instances --- src/librustc_codegen_llvm/callee.rs | 2 +- src/librustc_codegen_llvm/common.rs | 2 +- src/librustc_codegen_llvm/context.rs | 10 +++++----- src/librustc_codegen_ssa/base.rs | 7 +++---- src/librustc_codegen_ssa/meth.rs | 4 ++-- src/librustc_codegen_ssa/mir/block.rs | 8 ++++---- src/librustc_codegen_ssa/mir/rvalue.rs | 6 +++--- src/librustc_codegen_ssa/traits/misc.rs | 4 ++-- 8 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/librustc_codegen_llvm/callee.rs b/src/librustc_codegen_llvm/callee.rs index 35d5107842d5..08fa23f2a7c9 100644 --- a/src/librustc_codegen_llvm/callee.rs +++ b/src/librustc_codegen_llvm/callee.rs @@ -33,7 +33,7 @@ pub fn get_fn( assert!(!instance.substs.has_param_types()); let sig = instance.fn_sig(cx.tcx()); - if let Some(&llfn) = cx.instances().borrow().get(&instance) { + if let Some(&llfn) = cx.instances.borrow().get(&instance) { return llfn; } diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 01055bedc682..0d0ee2f6a150 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -305,7 +305,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } Some(GlobalAlloc::Function(fn_instance)) => { - self.get_fn(fn_instance) + self.get_fn_addr(fn_instance) } Some(GlobalAlloc::Static(def_id)) => { assert!(self.tcx.is_static(def_id)); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 6b3caf80d85e..2da938771721 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -326,11 +326,11 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { &self.vtables } - fn instances(&self) -> &RefCell, &'ll Value>> { - &self.instances + fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value { + get_fn(self, instance) } - fn get_fn(&self, instance: Instance<'tcx>) -> &'ll Value { + fn get_fn_addr(&self, instance: Instance<'tcx>) -> &'ll Value { get_fn(self, instance) } @@ -361,7 +361,7 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { let tcx = self.tcx; let llfn = match tcx.lang_items().eh_personality() { Some(def_id) if !wants_msvc_seh(self.sess()) => { - self.get_fn( + self.get_fn_addr( ty::Instance::resolve( tcx, ty::ParamEnv::reveal_all(), @@ -396,7 +396,7 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { 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( + let llfn = self.get_fn_addr( ty::Instance::resolve( tcx, ty::ParamEnv::reveal_all(), diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 18680ba73d6b..1c441ca7cbf2 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -376,8 +376,7 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( let sig = instance.fn_sig(cx.tcx()); let sig = cx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig); - let lldecl = cx.instances().borrow().get(&instance).cloned().unwrap_or_else(|| - bug!("Instance `{:?}` not already declared", instance)); + let lldecl = cx.get_fn(instance); let mir = cx.tcx().instance_mir(instance.def); mir::codegen_mir::(cx, lldecl, &mir, instance, sig); @@ -399,7 +398,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' return; } - let main_llfn = cx.get_fn(instance); + let main_llfn = cx.get_fn_addr(instance); let et = cx.tcx().entry_fn(LOCAL_CRATE).map(|e| e.1); match et { @@ -454,7 +453,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(cx: &' let (start_fn, args) = if use_start_lang_item { let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); - let start_fn = cx.get_fn( + let start_fn = cx.get_fn_addr( ty::Instance::resolve( cx.tcx(), ty::ParamEnv::reveal_all(), diff --git a/src/librustc_codegen_ssa/meth.rs b/src/librustc_codegen_ssa/meth.rs index 5c177fd7d6d2..266d2e5b18d2 100644 --- a/src/librustc_codegen_ssa/meth.rs +++ b/src/librustc_codegen_ssa/meth.rs @@ -91,7 +91,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( let methods = methods.cloned().map(|opt_mth| { opt_mth.map_or(nullptr, |(def_id, substs)| { - cx.get_fn( + cx.get_fn_addr( ty::Instance::resolve_for_vtable( cx.tcx(), ty::ParamEnv::reveal_all(), @@ -108,7 +108,7 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( // `get_vtable` in rust_mir/interpret/traits.rs // ///////////////////////////////////////////////////////////////////////////////////////////// let components: Vec<_> = [ - cx.get_fn(Instance::resolve_drop_in_place(cx.tcx(), ty)), + cx.get_fn_addr(Instance::resolve_drop_in_place(cx.tcx(), ty)), cx.const_usize(layout.size.bytes()), cx.const_usize(layout.align.abi.bytes()) ].iter().cloned().chain(methods).collect(); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index b0df81ba1abe..dc77d025c005 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -358,7 +358,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (meth::DESTRUCTOR.get_fn(&mut bx, vtable, &fn_ty), fn_ty) } _ => { - (bx.get_fn(drop_fn), + (bx.get_fn_addr(drop_fn), FnType::of_instance(&bx, drop_fn)) } }; @@ -460,7 +460,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let def_id = common::langcall(bx.tcx(), Some(span), "", lang_item); let instance = ty::Instance::mono(bx.tcx(), def_id); let fn_ty = FnType::of_instance(&bx, instance); - let llfn = bx.get_fn(instance); + let llfn = bx.get_fn_addr(instance); // Codegen the actual panic invoke/call. helper.do_call(self, &mut bx, fn_ty, llfn, &args, None, cleanup); @@ -576,7 +576,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); let instance = ty::Instance::mono(bx.tcx(), def_id); let fn_ty = FnType::of_instance(&bx, instance); - let llfn = bx.get_fn(instance); + let llfn = bx.get_fn_addr(instance); if let Some((_, target)) = destination.as_ref() { helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); @@ -793,7 +793,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let fn_ptr = match (llfn, instance) { (Some(llfn), _) => llfn, - (None, Some(instance)) => bx.get_fn(instance), + (None, Some(instance)) => bx.get_fn_addr(instance), _ => span_bug!(span, "no llfn for call"), }; diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 2b9f8aabdd46..27442bb6bff8 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -189,7 +189,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("reifying a fn ptr that requires const arguments"); } OperandValue::Immediate( - bx.get_fn( + bx.get_fn_addr( ty::Instance::resolve_for_fn_ptr( bx.tcx(), ty::ParamEnv::reveal_all(), @@ -212,7 +212,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { def_id, substs, ty::ClosureKind::FnOnce); - OperandValue::Immediate(bx.cx().get_fn(instance)) + OperandValue::Immediate(bx.cx().get_fn_addr(instance)) } _ => { bug!("{} cannot be cast to a fn ptr", operand.layout.ty) @@ -495,7 +495,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } }; let instance = ty::Instance::mono(bx.tcx(), def_id); - let r = bx.cx().get_fn(instance); + let r = bx.cx().get_fn_addr(instance); let call = bx.call(r, &[llsize, llalign], None); let val = bx.pointercast(call, llty_ptr); diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index fc704d55fd9b..658ddd002807 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -11,8 +11,8 @@ pub trait MiscMethods<'tcx>: BackendTypes { &self, ) -> &RefCell, Option>), Self::Value>>; fn check_overflow(&self) -> bool; - fn instances(&self) -> &RefCell, Self::Function>>; - fn get_fn(&self, instance: Instance<'tcx>) -> Self::Value; + 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; From ea60335c286f45ea14fb2049b395e1bced2a1b45 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 Oct 2019 12:11:27 +0200 Subject: [PATCH 335/545] Add top level provide/provide_extern to cg_ssa and cg_utils --- src/librustc_codegen_ssa/lib.rs | 11 +++++++++++ src/librustc_codegen_utils/lib.rs | 5 +++++ src/librustc_interface/passes.rs | 8 +++----- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index 55e465091aac..0221a04b0451 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -27,6 +27,7 @@ use rustc::dep_graph::WorkProduct; use rustc::session::config::{OutputFilenames, OutputType}; use rustc::middle::lang_items::LangItem; use rustc::hir::def_id::CrateNum; +use rustc::ty::query::Providers; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::svh::Svh; @@ -155,3 +156,13 @@ pub struct CodegenResults { pub linker_info: back::linker::LinkerInfo, pub crate_info: CrateInfo, } + +pub fn provide(providers: &mut Providers<'_>) { + crate::back::symbol_export::provide(providers); + crate::base::provide_both(providers); +} + +pub fn provide_extern(providers: &mut Providers<'_>) { + crate::back::symbol_export::provide_extern(providers); + crate::base::provide_both(providers); +} diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 1201446afb53..66920342ff6b 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -18,6 +18,7 @@ extern crate rustc; use rustc::ty::TyCtxt; +use rustc::ty::query::Providers; use rustc::hir::def_id::LOCAL_CRATE; use syntax::symbol::sym; @@ -37,3 +38,7 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt<'_>) { } } } + +pub fn provide(providers: &mut Providers<'_>) { + crate::symbol_names::provide(providers); +} diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 0f120bc606ff..346b922ddc8e 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -789,15 +789,13 @@ pub fn default_provide(providers: &mut ty::query::Providers<'_>) { cstore::provide(providers); lint::provide(providers); rustc_lint::provide(providers); - rustc_codegen_utils::symbol_names::provide(providers); - rustc_codegen_ssa::back::symbol_export::provide(providers); - rustc_codegen_ssa::base::provide_both(providers); + rustc_codegen_utils::provide(providers); + rustc_codegen_ssa::provide(providers); } pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) { cstore::provide_extern(providers); - rustc_codegen_ssa::back::symbol_export::provide_extern(providers); - rustc_codegen_ssa::base::provide_both(providers); + rustc_codegen_ssa::provide_extern(providers); } declare_box_region_type!( From f0e2fc76235cb5184e264d028d86e1ab718b6214 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 Oct 2019 12:19:14 +0200 Subject: [PATCH 336/545] Improve type safety --- src/librustc_codegen_llvm/common.rs | 34 ++++++++++----------------- src/librustc_codegen_llvm/llvm/ffi.rs | 7 +++--- 2 files changed, 17 insertions(+), 24 deletions(-) diff --git a/src/librustc_codegen_llvm/common.rs b/src/librustc_codegen_llvm/common.rs index 0d0ee2f6a150..a1a5232d5883 100644 --- a/src/librustc_codegen_llvm/common.rs +++ b/src/librustc_codegen_llvm/common.rs @@ -2,7 +2,7 @@ //! Code that is useful in various codegen modules. -use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef}; +use crate::llvm::{self, True, False, Bool, BasicBlock, OperandBundleDef, ConstantInt}; use crate::abi; use crate::consts; use crate::type_::Type; @@ -246,30 +246,22 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } fn const_to_opt_uint(&self, v: &'ll Value) -> Option { - if is_const_integral(v) { - unsafe { - Some(llvm::LLVMConstIntGetZExtValue(v)) - } - } else { - None - } + try_as_const_integral(v).map(|v| unsafe { + llvm::LLVMConstIntGetZExtValue(v) + }) } fn const_to_opt_u128(&self, v: &'ll Value, sign_ext: bool) -> Option { - unsafe { - if is_const_integral(v) { - let (mut lo, mut hi) = (0u64, 0u64); - let success = llvm::LLVMRustConstInt128Get(v, sign_ext, - &mut hi, &mut lo); - if success { - Some(hi_lo_to_u128(lo, hi)) - } else { - None - } + try_as_const_integral(v).and_then(|v| unsafe { + let (mut lo, mut hi) = (0u64, 0u64); + let success = llvm::LLVMRustConstInt128Get(v, sign_ext, + &mut hi, &mut lo); + if success { + Some(hi_lo_to_u128(lo, hi)) } else { None } - } + }) } fn scalar_to_backend( @@ -387,8 +379,8 @@ fn hi_lo_to_u128(lo: u64, hi: u64) -> u128 { ((hi as u128) << 64) | (lo as u128) } -fn is_const_integral(v: &'ll Value) -> bool { +fn try_as_const_integral(v: &'ll Value) -> Option<&'ll ConstantInt> { unsafe { - llvm::LLVMIsAConstantInt(v).is_some() + llvm::LLVMIsAConstantInt(v) } } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index b07214fdc03f..a2313b933a6c 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -510,6 +510,7 @@ extern { pub type Module; } extern { pub type Context; } extern { pub type Type; } extern { pub type Value; } +extern { pub type ConstantInt; } extern { pub type Metadata; } extern { pub type BasicBlock; } #[repr(C)] @@ -719,8 +720,8 @@ extern "C" { pub fn LLVMConstInt(IntTy: &Type, N: c_ulonglong, SignExtend: Bool) -> &Value; pub fn LLVMConstIntOfArbitraryPrecision(IntTy: &Type, Wn: c_uint, Ws: *const u64) -> &Value; pub fn LLVMConstReal(RealTy: &Type, N: f64) -> &Value; - pub fn LLVMConstIntGetZExtValue(ConstantVal: &Value) -> c_ulonglong; - pub fn LLVMRustConstInt128Get(ConstantVal: &Value, SExt: bool, + pub fn LLVMConstIntGetZExtValue(ConstantVal: &ConstantInt) -> c_ulonglong; + pub fn LLVMRustConstInt128Get(ConstantVal: &ConstantInt, SExt: bool, high: &mut u64, low: &mut u64) -> bool; @@ -1666,7 +1667,7 @@ extern "C" { #[allow(improper_ctypes)] pub fn LLVMRustWriteValueToString(value_ref: &Value, s: &RustString); - pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&Value>; + pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>; pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind; pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; From e67fa776ee749b4804c810aa35f65c477e901788 Mon Sep 17 00:00:00 2001 From: kalabukdima Date: Sun, 13 Oct 2019 15:46:28 +0300 Subject: [PATCH 337/545] Fix typo in docs for `Rc` --- src/liballoc/rc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index a28c6d22abb9..b0651f16484d 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -773,7 +773,7 @@ impl Rc { /// referred to as clone-on-write. /// /// If there are no other `Rc` pointers to this value, then [`Weak`] - /// pointers to this value will be dissassociated. + /// pointers to this value will be disassociated. /// /// See also [`get_mut`], which will fail rather than cloning. /// @@ -799,7 +799,7 @@ impl Rc { /// assert_eq!(*other_data, 12); /// ``` /// - /// [`Weak`] pointers will be dissassociated: + /// [`Weak`] pointers will be disassociated: /// /// ``` /// use std::rc::Rc; From 9d766ed593f7ab9811324856c03730312d3425e3 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 11 Oct 2019 23:30:58 +0200 Subject: [PATCH 338/545] refactor session::config::build_session_options_and_crate_config --- src/librustc/session/config.rs | 468 ++++++++++++++++----------- src/librustc/session/config/tests.rs | 15 +- src/librustc_driver/lib.rs | 3 +- 3 files changed, 300 insertions(+), 186 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 25e68e6408de..5af4460016c5 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -2035,11 +2035,7 @@ pub fn parse_error_format( return error_format; } -pub fn build_session_options_and_crate_config( - matches: &getopts::Matches, -) -> (Options, FxHashSet<(String, Option)>) { - let color = parse_color(matches); - +fn parse_crate_edition(matches: &getopts::Matches) -> Edition { let edition = match matches.opt_str("edition") { Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| early_error( @@ -2066,19 +2062,14 @@ pub fn build_session_options_and_crate_config( ) } - let (json_rendered, json_artifact_notifications) = parse_json(matches); - - let error_format = parse_error_format(matches, color, json_rendered); - - let unparsed_crate_types = matches.opt_strs("crate-type"); - let crate_types = parse_crate_types_from_list(unparsed_crate_types) - .unwrap_or_else(|e| early_error(error_format, &e[..])); - - - let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); - - let mut debugging_opts = build_debugging_options(matches, error_format); + edition +} +fn check_debug_option_stability( + debugging_opts: &DebuggingOptions, + error_format: ErrorOutputType, + json_rendered: HumanReadableErrorType, +) { if !debugging_opts.unstable_options { if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { early_error( @@ -2094,7 +2085,13 @@ pub fn build_session_options_and_crate_config( ); } } +} +fn parse_output_types( + debugging_opts: &DebuggingOptions, + matches: &getopts::Matches, + error_format: ErrorOutputType, +) -> OutputTypes { let mut output_types = BTreeMap::new(); if !debugging_opts.parse_only { for list in matches.opt_strs("emit") { @@ -2119,14 +2116,19 @@ pub fn build_session_options_and_crate_config( if output_types.is_empty() { output_types.insert(OutputType::Exe, None); } + OutputTypes(output_types) +} - let mut cg = build_codegen_options(matches, error_format); - let mut codegen_units = cg.codegen_units; +fn should_override_cgus_and_disable_thinlto( + output_types: &OutputTypes, + matches: &getopts::Matches, + error_format: ErrorOutputType, + mut codegen_units: Option, +) -> (bool, Option) { let mut disable_thinlto = false; - // Issue #30063: if user requests LLVM-related output to one // particular path, disable codegen-units. - let incompatible: Vec<_> = output_types + let incompatible: Vec<_> = output_types.0 .iter() .map(|ot_path| ot_path.0) .filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file()) @@ -2158,6 +2160,17 @@ pub fn build_session_options_and_crate_config( } } + if codegen_units == Some(0) { + early_error( + error_format, + "value for codegen units must be a positive non-zero integer", + ); + } + + (disable_thinlto, codegen_units) +} + +fn check_thread_count(debugging_opts: &DebuggingOptions, error_format: ErrorOutputType) { if debugging_opts.threads == 0 { early_error( error_format, @@ -2171,16 +2184,15 @@ pub fn build_session_options_and_crate_config( "optimization fuel is incompatible with multiple threads", ); } +} - if codegen_units == Some(0) { - early_error( - error_format, - "value for codegen units must be a positive non-zero integer", - ); - } - - let incremental = match (&debugging_opts.incremental, &cg.incremental) { - (&Some(ref path1), &Some(ref path2)) => { +fn select_incremental_path( + debugging_opts: &DebuggingOptions, + cg: &CodegenOptions, + error_format: ErrorOutputType, +) -> Option { + match (&debugging_opts.incremental, &cg.incremental) { + (Some(path1), Some(path2)) => { if path1 != path2 { early_error( error_format, @@ -2194,25 +2206,19 @@ pub fn build_session_options_and_crate_config( Some(path1) } } - (&Some(ref path), &None) => Some(path), - (&None, &Some(ref path)) => Some(path), - (&None, &None) => None, - }.map(|m| PathBuf::from(m)); - - if debugging_opts.profile && incremental.is_some() { - early_error( - error_format, - "can't instrument with gcov profiling when compiling incrementally", - ); - } - - if cg.profile_generate.enabled() && cg.profile_use.is_some() { - early_error( - error_format, - "options `-C profile-generate` and `-C profile-use` are exclusive", - ); - } + (Some(path), None) => Some(path), + (None, Some(path)) => Some(path), + (None, None) => None, + }.map(|m| PathBuf::from(m)) +} +fn collect_print_requests( + cg: &mut CodegenOptions, + dopts: &mut DebuggingOptions, + matches: &getopts::Matches, + is_unstable_enabled: bool, + error_format: ErrorOutputType, +) -> Vec { let mut prints = Vec::::new(); if cg.target_cpu.as_ref().map_or(false, |s| s == "help") { prints.push(PrintRequest::TargetCPUs); @@ -2230,72 +2236,105 @@ pub fn build_session_options_and_crate_config( prints.push(PrintRequest::CodeModels); cg.code_model = None; } - if debugging_opts + if dopts .tls_model .as_ref() .map_or(false, |s| s == "help") { prints.push(PrintRequest::TlsModels); - debugging_opts.tls_model = None; + dopts.tls_model = None; } - let cg = cg; + prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { + "crate-name" => PrintRequest::CrateName, + "file-names" => PrintRequest::FileNames, + "sysroot" => PrintRequest::Sysroot, + "cfg" => PrintRequest::Cfg, + "target-list" => PrintRequest::TargetList, + "target-cpus" => PrintRequest::TargetCPUs, + "target-features" => PrintRequest::TargetFeatures, + "relocation-models" => PrintRequest::RelocationModels, + "code-models" => PrintRequest::CodeModels, + "tls-models" => PrintRequest::TlsModels, + "native-static-libs" => PrintRequest::NativeStaticLibs, + "target-spec-json" => { + if is_unstable_enabled { + PrintRequest::TargetSpec + } else { + early_error( + error_format, + "the `-Z unstable-options` flag must also be passed to \ + enable the target-spec-json print option", + ); + } + } + req => early_error(error_format, &format!("unknown print request `{}`", req)), + })); - let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); - let target_triple = if let Some(target) = matches.opt_str("target") { - if target.ends_with(".json") { + prints +} + +fn parse_target_triple(matches: &getopts::Matches, error_format: ErrorOutputType) -> TargetTriple { + match matches.opt_str("target") { + Some(target) if target.ends_with(".json") => { let path = Path::new(&target); TargetTriple::from_path(&path).unwrap_or_else(|_| early_error(error_format, &format!("target file {:?} does not exist", path))) - } else { - TargetTriple::TargetTriple(target) } + Some(target) => TargetTriple::TargetTriple(target), + _ => TargetTriple::from_triple(host_triple()), + } +} + +fn parse_opt_level( + matches: &getopts::Matches, + cg: &CodegenOptions, + error_format: ErrorOutputType, +) -> OptLevel { + // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able + // to use them interchangeably. However, because they're technically different flags, + // we need to work out manually which should take precedence if both are supplied (i.e. + // the rightmost flag). We do this by finding the (rightmost) position of both flags and + // comparing them. Note that if a flag is not found, its position will be `None`, which + // always compared less than `Some(_)`. + let max_o = matches.opt_positions("O").into_iter().max(); + let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { + if let Some("opt-level") = s.splitn(2, '=').next() { + Some(i) + } else { + None + } + }).max(); + if max_o > max_c { + OptLevel::Default } else { - TargetTriple::from_triple(host_triple()) - }; - let opt_level = { - // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able - // to use them interchangeably. However, because they're technically different flags, - // we need to work out manually which should take precedence if both are supplied (i.e. - // the rightmost flag). We do this by finding the (rightmost) position of both flags and - // comparing them. Note that if a flag is not found, its position will be `None`, which - // always compared less than `Some(_)`. - let max_o = matches.opt_positions("O").into_iter().max(); - let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { - if let Some("opt-level") = s.splitn(2, '=').next() { - Some(i) - } else { - None - } - }).max(); - if max_o > max_c { - OptLevel::Default - } else { - match cg.opt_level.as_ref().map(String::as_ref) { - None => OptLevel::No, - Some("0") => OptLevel::No, - Some("1") => OptLevel::Less, - Some("2") => OptLevel::Default, - Some("3") => OptLevel::Aggressive, - Some("s") => OptLevel::Size, - Some("z") => OptLevel::SizeMin, - Some(arg) => { - early_error( - error_format, - &format!( - "optimization level needs to be \ - between 0-3, s or z (instead was `{}`)", - arg - ), - ); - } + match cg.opt_level.as_ref().map(String::as_ref) { + None => OptLevel::No, + Some("0") => OptLevel::No, + Some("1") => OptLevel::Less, + Some("2") => OptLevel::Default, + Some("3") => OptLevel::Aggressive, + Some("s") => OptLevel::Size, + Some("z") => OptLevel::SizeMin, + Some(arg) => { + early_error( + error_format, + &format!( + "optimization level needs to be \ + between 0-3, s or z (instead was `{}`)", + arg + ), + ); } } - }; - // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able - // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) - // for more details. - let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); + } +} + +fn select_debuginfo( + matches: &getopts::Matches, + cg: &CodegenOptions, + error_format: ErrorOutputType, +) -> DebugInfo { let max_g = matches.opt_positions("g").into_iter().max(); let max_c = matches.opt_strs_pos("C").into_iter().flat_map(|(i, s)| { if let Some("debuginfo") = s.splitn(2, '=').next() { @@ -2304,7 +2343,7 @@ pub fn build_session_options_and_crate_config( None } }).max(); - let debuginfo = if max_g > max_c { + if max_g > max_c { DebugInfo::Full } else { match cg.debuginfo { @@ -2322,14 +2361,14 @@ pub fn build_session_options_and_crate_config( ); } } - }; - - let mut search_paths = vec![]; - for s in &matches.opt_strs("L") { - search_paths.push(SearchPath::from_cli_opt(&s[..], error_format)); } +} - let libs = matches +fn parse_libs( + matches: &getopts::Matches, + error_format: ErrorOutputType, +) -> Vec<(String, Option, Option)> { + matches .opt_strs("l") .into_iter() .map(|s| { @@ -2368,52 +2407,23 @@ pub fn build_session_options_and_crate_config( let new_name = name_parts.next(); (name.to_owned(), new_name.map(|n| n.to_owned()), kind) }) - .collect(); + .collect() +} - let cfg = parse_cfgspecs(matches.opt_strs("cfg")); - let test = matches.opt_present("test"); - - let is_unstable_enabled = nightly_options::is_unstable_enabled(matches); - - prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { - "crate-name" => PrintRequest::CrateName, - "file-names" => PrintRequest::FileNames, - "sysroot" => PrintRequest::Sysroot, - "cfg" => PrintRequest::Cfg, - "target-list" => PrintRequest::TargetList, - "target-cpus" => PrintRequest::TargetCPUs, - "target-features" => PrintRequest::TargetFeatures, - "relocation-models" => PrintRequest::RelocationModels, - "code-models" => PrintRequest::CodeModels, - "tls-models" => PrintRequest::TlsModels, - "native-static-libs" => PrintRequest::NativeStaticLibs, - "target-spec-json" => { - if is_unstable_enabled { - PrintRequest::TargetSpec - } else { - early_error( - error_format, - "the `-Z unstable-options` flag must also be passed to \ - enable the target-spec-json print option", - ); - } - } - req => early_error(error_format, &format!("unknown print request `{}`", req)), - })); - - let borrowck_mode = match debugging_opts.borrowck.as_ref().map(|s| &s[..]) { +fn parse_borrowck_mode(dopts: &DebuggingOptions, error_format: ErrorOutputType) -> BorrowckMode { + match dopts.borrowck.as_ref().map(|s| &s[..]) { None | Some("migrate") => BorrowckMode::Migrate, Some("mir") => BorrowckMode::Mir, Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)), - }; - - if !cg.remark.is_empty() && debuginfo == DebugInfo::None { - early_warn( - error_format, - "-C remark requires \"-C debuginfo=n\" to show source locations", - ); } +} +fn parse_externs( + matches: &getopts::Matches, + debugging_opts: &DebuggingOptions, + error_format: ErrorOutputType, + is_unstable_enabled: bool, +) -> Externs { if matches.opt_present("extern-private") && !debugging_opts.unstable_options { early_error( ErrorOutputType::default(), @@ -2454,10 +2464,14 @@ pub fn build_session_options_and_crate_config( // flag entry.is_private_dep |= private; } + Externs(externs) +} - let crate_name = matches.opt_str("crate-name"); - - let remap_path_prefix = matches +fn parse_remap_path_prefix( + matches: &getopts::Matches, + error_format: ErrorOutputType +) -> Vec<(PathBuf, PathBuf)> { + matches .opt_strs("remap-path-prefix") .into_iter() .map(|remap| { @@ -2472,42 +2486,130 @@ pub fn build_session_options_and_crate_config( ), } }) - .collect(); + .collect() +} - ( - Options { - crate_types, - optimize: opt_level, - debuginfo, - lint_opts, - lint_cap, - describe_lints, - output_types: OutputTypes(output_types), - search_paths, - maybe_sysroot: sysroot_opt, - target_triple, - test, - incremental, - debugging_opts, - prints, - borrowck_mode, - cg, +pub fn build_session_options(matches: &getopts::Matches) -> Options { + let color = parse_color(matches); + + let edition = parse_crate_edition(matches); + + let (json_rendered, json_artifact_notifications) = parse_json(matches); + + let error_format = parse_error_format(matches, color, json_rendered); + + let unparsed_crate_types = matches.opt_strs("crate-type"); + let crate_types = parse_crate_types_from_list(unparsed_crate_types) + .unwrap_or_else(|e| early_error(error_format, &e[..])); + + let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); + + let mut debugging_opts = build_debugging_options(matches, error_format); + check_debug_option_stability(&debugging_opts, error_format, json_rendered); + + let output_types = parse_output_types(&debugging_opts, matches, error_format); + + let mut cg = build_codegen_options(matches, error_format); + let (disable_thinlto, codegen_units) = should_override_cgus_and_disable_thinlto( + &output_types, + matches, + error_format, + cg.codegen_units, + ); + + check_thread_count(&debugging_opts, error_format); + + let incremental = select_incremental_path(&debugging_opts, &cg, error_format); + + if debugging_opts.profile && incremental.is_some() { + early_error( error_format, - externs: Externs(externs), - crate_name, - alt_std_name: None, - libs, - unstable_features: UnstableFeatures::from_environment(), - debug_assertions, - actually_rustdoc: false, - cli_forced_codegen_units: codegen_units, - cli_forced_thinlto_off: disable_thinlto, - remap_path_prefix, - edition, - json_artifact_notifications, - }, - cfg, - ) + "can't instrument with gcov profiling when compiling incrementally", + ); + } + + if cg.profile_generate.enabled() && cg.profile_use.is_some() { + early_error( + error_format, + "options `-C profile-generate` and `-C profile-use` are exclusive", + ); + } + + let is_unstable_enabled = nightly_options::is_unstable_enabled(matches); + let prints = collect_print_requests( + &mut cg, + &mut debugging_opts, + matches, + is_unstable_enabled, + error_format, + ); + + let cg = cg; + + let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); + let target_triple = parse_target_triple(matches, error_format); + let opt_level = parse_opt_level(matches, &cg, error_format); + // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able + // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) + // for more details. + let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); + let debuginfo = select_debuginfo(matches, &cg, error_format); + + let mut search_paths = vec![]; + for s in &matches.opt_strs("L") { + search_paths.push(SearchPath::from_cli_opt(&s[..], error_format)); + } + + let libs = parse_libs(matches, error_format); + + let test = matches.opt_present("test"); + + let borrowck_mode = parse_borrowck_mode(&debugging_opts, error_format); + + if !cg.remark.is_empty() && debuginfo == DebugInfo::None { + early_warn( + error_format, + "-C remark requires \"-C debuginfo=n\" to show source locations", + ); + } + + let externs = parse_externs(matches, &debugging_opts, error_format, is_unstable_enabled); + + let crate_name = matches.opt_str("crate-name"); + + let remap_path_prefix = parse_remap_path_prefix(matches, error_format); + + Options { + crate_types, + optimize: opt_level, + debuginfo, + lint_opts, + lint_cap, + describe_lints, + output_types, + search_paths, + maybe_sysroot: sysroot_opt, + target_triple, + test, + incremental, + debugging_opts, + prints, + borrowck_mode, + cg, + error_format, + externs, + crate_name, + alt_std_name: None, + libs, + unstable_features: UnstableFeatures::from_environment(), + debug_assertions, + actually_rustdoc: false, + cli_forced_codegen_units: codegen_units, + cli_forced_thinlto_off: disable_thinlto, + remap_path_prefix, + edition, + json_artifact_notifications, + } } pub fn make_crate_type_option() -> RustcOptGroup { diff --git a/src/librustc/session/config/tests.rs b/src/librustc/session/config/tests.rs index c117418f6369..061bbdc307fc 100644 --- a/src/librustc/session/config/tests.rs +++ b/src/librustc/session/config/tests.rs @@ -3,8 +3,9 @@ use crate::lint; use crate::middle::cstore; use crate::session::config::{ build_configuration, - build_session_options_and_crate_config, - to_crate_config + build_session_options, + to_crate_config, + parse_cfgspecs, }; use crate::session::config::{LtoCli, LinkerPluginLto, SwitchWithOptPath, ExternEntry}; use crate::session::build_session; @@ -18,6 +19,16 @@ use syntax::symbol::sym; use syntax::edition::{Edition, DEFAULT_EDITION}; use syntax; use super::Options; +use rustc_data_structures::fx::FxHashSet; + +pub fn build_session_options_and_crate_config( + matches: &getopts::Matches, +) -> (Options, FxHashSet<(String, Option)>) { + ( + build_session_options(matches), + parse_cfgspecs(matches.opt_strs("cfg")), + ) +} impl ExternEntry { fn new_public, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index dd088b68a239..806afbd1af68 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -166,7 +166,8 @@ pub fn run_compiler( None => return Ok(()), }; - let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); + let sopts = config::build_session_options(&matches); + let cfg = config::parse_cfgspecs(matches.opt_strs("cfg")); let mut dummy_config = |sopts, cfg, diagnostic_output| { let mut config = interface::Config { From 42f32f06d63b9947db63f0c739483e0294f588b2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 9 Oct 2019 02:34:22 +0200 Subject: [PATCH 339/545] token: extract Nonterminal::to_tokenstream to parser. --- src/librustc/hir/lowering.rs | 6 +- src/libsyntax/ext/proc_macro_server.rs | 2 +- src/libsyntax/parse/mod.rs | 138 ++++++++++++++++++++++++- src/libsyntax/parse/token.rs | 137 +----------------------- 4 files changed, 143 insertions(+), 140 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 72fd054ee8a2..513512b9f6b2 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -70,6 +70,7 @@ use syntax::print::pprust; use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned}; use syntax::symbol::{kw, sym, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; +use syntax::parse; use syntax::parse::token::{self, Token}; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -1022,7 +1023,10 @@ impl<'a> LoweringContext<'a> { fn lower_token(&mut self, token: Token) -> TokenStream { match token.kind { token::Interpolated(nt) => { - let tts = nt.to_tokenstream(&self.sess.parse_sess, token.span); + // FIXME(Centril): Consider indirection `(parse_sess.nt_to_tokenstream)(...)` + // to hack around the current hack that requires `nt_to_tokenstream` to live + // in the parser. + let tts = parse::nt_to_tokenstream(&nt, &self.sess.parse_sess, token.span); self.lower_token_stream(tts) } _ => TokenTree::Token(token).into(), diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 021ec46d987c..0647c2fa313b 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -174,7 +174,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec)> } Interpolated(nt) => { - let stream = nt.to_tokenstream(sess, span); + let stream = parse::nt_to_tokenstream(&nt, sess, span); TokenTree::Group(Group { delimiter: Delimiter::None, stream, diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1518da23b096..0df695d37b94 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -4,10 +4,9 @@ use crate::ast::{self, CrateConfig, NodeId}; use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; use crate::source_map::{SourceMap, FilePathMapping}; use crate::feature_gate::UnstableFeatures; -use crate::parse::parser::Parser; -use crate::parse::parser::emit_unclosed_delims; -use crate::parse::token::TokenKind; -use crate::tokenstream::{TokenStream, TokenTree}; +use crate::parse::parser::{Parser, emit_unclosed_delims}; +use crate::parse::token::{Nonterminal, TokenKind}; +use crate::tokenstream::{self, TokenStream, TokenTree}; use crate::print::pprust; use crate::symbol::Symbol; @@ -24,6 +23,8 @@ use std::borrow::Cow; use std::path::{Path, PathBuf}; use std::str; +use log::info; + #[cfg(test)] mod tests; @@ -407,3 +408,132 @@ impl SeqSep { } } } + +// NOTE(Centril): The following probably shouldn't be here but it acknowledges the +// fact that architecturally, we are using parsing (read on below to understand why). + +pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> TokenStream { + // A `Nonterminal` is often a parsed AST item. At this point we now + // need to convert the parsed AST to an actual token stream, e.g. + // un-parse it basically. + // + // Unfortunately there's not really a great way to do that in a + // guaranteed lossless fashion right now. The fallback here is to just + // stringify the AST node and reparse it, but this loses all span + // information. + // + // As a result, some AST nodes are annotated with the token stream they + // came from. Here we attempt to extract these lossless token streams + // before we fall back to the stringification. + let tokens = match *nt { + Nonterminal::NtItem(ref item) => { + prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) + } + Nonterminal::NtTraitItem(ref item) => { + prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) + } + Nonterminal::NtImplItem(ref item) => { + prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) + } + Nonterminal::NtIdent(ident, is_raw) => { + Some(tokenstream::TokenTree::token(token::Ident(ident.name, is_raw), ident.span).into()) + } + Nonterminal::NtLifetime(ident) => { + Some(tokenstream::TokenTree::token(token::Lifetime(ident.name), ident.span).into()) + } + Nonterminal::NtTT(ref tt) => { + Some(tt.clone().into()) + } + _ => None, + }; + + // FIXME(#43081): Avoid this pretty-print + reparse hack + let source = pprust::nonterminal_to_string(nt); + let filename = FileName::macro_expansion_source_code(&source); + let tokens_for_real = parse_stream_from_source_str(filename, source, sess, Some(span)); + + // During early phases of the compiler the AST could get modified + // directly (e.g., attributes added or removed) and the internal cache + // of tokens my not be invalidated or updated. Consequently if the + // "lossless" token stream disagrees with our actual stringification + // (which has historically been much more battle-tested) then we go + // with the lossy stream anyway (losing span information). + // + // Note that the comparison isn't `==` here to avoid comparing spans, + // but it *also* is a "probable" equality which is a pretty weird + // definition. We mostly want to catch actual changes to the AST + // like a `#[cfg]` being processed or some weird `macro_rules!` + // expansion. + // + // What we *don't* want to catch is the fact that a user-defined + // literal like `0xf` is stringified as `15`, causing the cached token + // stream to not be literal `==` token-wise (ignoring spans) to the + // token stream we got from stringification. + // + // Instead the "probably equal" check here is "does each token + // recursively have the same discriminant?" We basically don't look at + // the token values here and assume that such fine grained token stream + // modifications, including adding/removing typically non-semantic + // tokens such as extra braces and commas, don't happen. + if let Some(tokens) = tokens { + if tokens.probably_equal_for_proc_macro(&tokens_for_real) { + return tokens + } + info!("cached tokens found, but they're not \"probably equal\", \ + going with stringified version"); + } + return tokens_for_real +} + +fn prepend_attrs( + sess: &ParseSess, + attrs: &[ast::Attribute], + tokens: Option<&tokenstream::TokenStream>, + span: syntax_pos::Span +) -> Option { + let tokens = tokens?; + if attrs.len() == 0 { + return Some(tokens.clone()) + } + let mut builder = tokenstream::TokenStreamBuilder::new(); + for attr in attrs { + assert_eq!(attr.style, ast::AttrStyle::Outer, + "inner attributes should prevent cached tokens from existing"); + + let source = pprust::attribute_to_string(attr); + let macro_filename = FileName::macro_expansion_source_code(&source); + if attr.is_sugared_doc { + let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); + builder.push(stream); + continue + } + + // synthesize # [ $path $tokens ] manually here + let mut brackets = tokenstream::TokenStreamBuilder::new(); + + // For simple paths, push the identifier directly + if attr.path.segments.len() == 1 && attr.path.segments[0].args.is_none() { + let ident = attr.path.segments[0].ident; + let token = token::Ident(ident.name, ident.as_str().starts_with("r#")); + brackets.push(tokenstream::TokenTree::token(token, ident.span)); + + // ... and for more complicated paths, fall back to a reparse hack that + // should eventually be removed. + } else { + let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); + brackets.push(stream); + } + + brackets.push(attr.tokens.clone()); + + // The span we list here for `#` and for `[ ... ]` are both wrong in + // that it encompasses more than each token, but it hopefully is "good + // enough" for now at least. + builder.push(tokenstream::TokenTree::token(token::Pound, attr.span)); + let delim_span = tokenstream::DelimSpan::from_single(attr.span); + builder.push(tokenstream::TokenTree::Delimited( + delim_span, token::DelimToken::Bracket, brackets.build().into())); + } + builder.push(tokens.clone()); + Some(builder.build()) +} diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index fd78a2bd5344..eb74ab2b9192 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -4,16 +4,13 @@ pub use DelimToken::*; pub use LitKind::*; pub use TokenKind::*; -use crate::ast::{self}; -use crate::parse::{parse_stream_from_source_str, ParseSess}; -use crate::print::pprust; +use crate::ast; use crate::ptr::P; use crate::symbol::kw; -use crate::tokenstream::{self, DelimSpan, TokenStream, TokenTree}; +use crate::tokenstream::TokenTree; use syntax_pos::symbol::Symbol; -use syntax_pos::{self, Span, FileName, DUMMY_SP}; -use log::info; +use syntax_pos::{self, Span, DUMMY_SP}; use std::fmt; use std::mem; @@ -737,131 +734,3 @@ impl fmt::Debug for Nonterminal { } } } - -impl Nonterminal { - pub fn to_tokenstream(&self, sess: &ParseSess, span: Span) -> TokenStream { - // A `Nonterminal` is often a parsed AST item. At this point we now - // need to convert the parsed AST to an actual token stream, e.g. - // un-parse it basically. - // - // Unfortunately there's not really a great way to do that in a - // guaranteed lossless fashion right now. The fallback here is to just - // stringify the AST node and reparse it, but this loses all span - // information. - // - // As a result, some AST nodes are annotated with the token stream they - // came from. Here we attempt to extract these lossless token streams - // before we fall back to the stringification. - let tokens = match *self { - Nonterminal::NtItem(ref item) => { - prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) - } - Nonterminal::NtTraitItem(ref item) => { - prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) - } - Nonterminal::NtImplItem(ref item) => { - prepend_attrs(sess, &item.attrs, item.tokens.as_ref(), span) - } - Nonterminal::NtIdent(ident, is_raw) => { - Some(TokenTree::token(Ident(ident.name, is_raw), ident.span).into()) - } - Nonterminal::NtLifetime(ident) => { - Some(TokenTree::token(Lifetime(ident.name), ident.span).into()) - } - Nonterminal::NtTT(ref tt) => { - Some(tt.clone().into()) - } - _ => None, - }; - - // FIXME(#43081): Avoid this pretty-print + reparse hack - let source = pprust::nonterminal_to_string(self); - let filename = FileName::macro_expansion_source_code(&source); - let tokens_for_real = parse_stream_from_source_str(filename, source, sess, Some(span)); - - // During early phases of the compiler the AST could get modified - // directly (e.g., attributes added or removed) and the internal cache - // of tokens my not be invalidated or updated. Consequently if the - // "lossless" token stream disagrees with our actual stringification - // (which has historically been much more battle-tested) then we go - // with the lossy stream anyway (losing span information). - // - // Note that the comparison isn't `==` here to avoid comparing spans, - // but it *also* is a "probable" equality which is a pretty weird - // definition. We mostly want to catch actual changes to the AST - // like a `#[cfg]` being processed or some weird `macro_rules!` - // expansion. - // - // What we *don't* want to catch is the fact that a user-defined - // literal like `0xf` is stringified as `15`, causing the cached token - // stream to not be literal `==` token-wise (ignoring spans) to the - // token stream we got from stringification. - // - // Instead the "probably equal" check here is "does each token - // recursively have the same discriminant?" We basically don't look at - // the token values here and assume that such fine grained token stream - // modifications, including adding/removing typically non-semantic - // tokens such as extra braces and commas, don't happen. - if let Some(tokens) = tokens { - if tokens.probably_equal_for_proc_macro(&tokens_for_real) { - return tokens - } - info!("cached tokens found, but they're not \"probably equal\", \ - going with stringified version"); - } - return tokens_for_real - } -} - -fn prepend_attrs(sess: &ParseSess, - attrs: &[ast::Attribute], - tokens: Option<&tokenstream::TokenStream>, - span: syntax_pos::Span) - -> Option -{ - let tokens = tokens?; - if attrs.len() == 0 { - return Some(tokens.clone()) - } - let mut builder = tokenstream::TokenStreamBuilder::new(); - for attr in attrs { - assert_eq!(attr.style, ast::AttrStyle::Outer, - "inner attributes should prevent cached tokens from existing"); - - let source = pprust::attribute_to_string(attr); - let macro_filename = FileName::macro_expansion_source_code(&source); - if attr.is_sugared_doc { - let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); - builder.push(stream); - continue - } - - // synthesize # [ $path $tokens ] manually here - let mut brackets = tokenstream::TokenStreamBuilder::new(); - - // For simple paths, push the identifier directly - if attr.path.segments.len() == 1 && attr.path.segments[0].args.is_none() { - let ident = attr.path.segments[0].ident; - let token = Ident(ident.name, ident.as_str().starts_with("r#")); - brackets.push(tokenstream::TokenTree::token(token, ident.span)); - - // ... and for more complicated paths, fall back to a reparse hack that - // should eventually be removed. - } else { - let stream = parse_stream_from_source_str(macro_filename, source, sess, Some(span)); - brackets.push(stream); - } - - brackets.push(attr.tokens.clone()); - - // The span we list here for `#` and for `[ ... ]` are both wrong in - // that it encompasses more than each token, but it hopefully is "good - // enough" for now at least. - builder.push(tokenstream::TokenTree::token(Pound, attr.span)); - let delim_span = DelimSpan::from_single(attr.span); - builder.push(tokenstream::TokenTree::Delimited( - delim_span, DelimToken::Bracket, brackets.build().into())); - } - builder.push(tokens.clone()); - Some(builder.build()) -} From 6a64e9ca49d2160df75437996bb7ac6574299d14 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 11 Oct 2019 14:38:24 +0200 Subject: [PATCH 340/545] Add long error explanation for E0574 --- src/librustc_resolve/error_codes.rs | 51 ++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 47346774180f..1e65cbada069 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1611,6 +1611,56 @@ fn print_on_failure(state: &State) { ``` "##, +E0574: r##" +Something other than a struct, variant or union has been used when one was +expected. + +Erroneous code example: + +```compile_fail,E0574 +mod Mordor {} + +let sauron = Mordor { x: () }; // error! + +enum Jak { + Daxter { i: isize }, +} + +let eco = Jak::Daxter { i: 1 }; +match eco { + Jak { i } => {} // error! +} +``` + +In all these errors, a type was expected. For example, in the first error, +we tried to instantiate the `Mordor` module, which is impossible. If you want +to instantiate a type inside a module, you can do it as follow: + +``` +mod Mordor { + pub struct TheRing { + pub x: usize, + } +} + +let sauron = Mordor::TheRing { x: 1 }; // ok! +``` + +In the second error, we tried to bind the `Jak` enum directly, which is not +possible: you can only bind one of its variants. To do so: + +``` +enum Jak { + Daxter { i: isize }, +} + +let eco = Jak::Daxter { i: 1 }; +match eco { + Jak::Daxter { i } => {} // ok! +} +``` +"##, + E0603: r##" A private item was used outside its scope. @@ -1739,7 +1789,6 @@ struct Foo> { // E0467, removed // E0470, removed E0573, - E0574, E0575, E0576, E0577, From 9f392c43dc62ab3f229fcb274393eee4e93fa630 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 11 Oct 2019 15:23:18 +0200 Subject: [PATCH 341/545] Update ui tests --- src/test/ui/issues/issue-17001.stderr | 1 + src/test/ui/issues/issue-17405.stderr | 1 + src/test/ui/issues/issue-21449.stderr | 1 + src/test/ui/issues/issue-23189.stderr | 1 + src/test/ui/issues/issue-26459.stderr | 1 + src/test/ui/issues/issue-27815.stderr | 1 + src/test/ui/lexical-scopes.stderr | 3 ++- src/test/ui/resolve/issue-16058.stderr | 1 + src/test/ui/traits/trait-as-struct-constructor.stderr | 1 + src/test/ui/try-block/try-block-in-edition2015.stderr | 1 + src/test/ui/use/issue-18986.stderr | 1 + 11 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/test/ui/issues/issue-17001.stderr b/src/test/ui/issues/issue-17001.stderr index 2374e829556e..d7e6069977b4 100644 --- a/src/test/ui/issues/issue-17001.stderr +++ b/src/test/ui/issues/issue-17001.stderr @@ -6,3 +6,4 @@ LL | let p = foo { x: () }; error: aborting due to previous error +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-17405.stderr b/src/test/ui/issues/issue-17405.stderr index 4b5678a88773..37274e239ba0 100644 --- a/src/test/ui/issues/issue-17405.stderr +++ b/src/test/ui/issues/issue-17405.stderr @@ -6,3 +6,4 @@ LL | Foo { i } => () error: aborting due to previous error +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-21449.stderr b/src/test/ui/issues/issue-21449.stderr index 21de1ea09156..ecaf6faba429 100644 --- a/src/test/ui/issues/issue-21449.stderr +++ b/src/test/ui/issues/issue-21449.stderr @@ -6,3 +6,4 @@ LL | let myVar = MyMod { T: 0 }; error: aborting due to previous error +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-23189.stderr b/src/test/ui/issues/issue-23189.stderr index 50c09f17486d..ed065212c560 100644 --- a/src/test/ui/issues/issue-23189.stderr +++ b/src/test/ui/issues/issue-23189.stderr @@ -6,3 +6,4 @@ LL | let _ = module { x: 0 }; error: aborting due to previous error +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-26459.stderr b/src/test/ui/issues/issue-26459.stderr index c7909a142bec..187369263a44 100644 --- a/src/test/ui/issues/issue-26459.stderr +++ b/src/test/ui/issues/issue-26459.stderr @@ -6,3 +6,4 @@ LL | char{ch} => true error: aborting due to previous error +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/issues/issue-27815.stderr b/src/test/ui/issues/issue-27815.stderr index 1d68e3bf558f..43f78ccf6395 100644 --- a/src/test/ui/issues/issue-27815.stderr +++ b/src/test/ui/issues/issue-27815.stderr @@ -24,3 +24,4 @@ LL | u32 { x: 1 } => {} error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr index e990f705af3f..38c7393e136a 100644 --- a/src/test/ui/lexical-scopes.stderr +++ b/src/test/ui/lexical-scopes.stderr @@ -16,4 +16,5 @@ LL | Foo::f(); error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0599`. +Some errors have detailed explanations: E0574, E0599. +For more information about an error, try `rustc --explain E0574`. diff --git a/src/test/ui/resolve/issue-16058.stderr b/src/test/ui/resolve/issue-16058.stderr index 64177ac2a831..9766f8f1412b 100644 --- a/src/test/ui/resolve/issue-16058.stderr +++ b/src/test/ui/resolve/issue-16058.stderr @@ -14,3 +14,4 @@ LL | use std::thread::Result; error: aborting due to previous error +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/traits/trait-as-struct-constructor.stderr b/src/test/ui/traits/trait-as-struct-constructor.stderr index 434dcbc8736a..e1d54fbf8aa7 100644 --- a/src/test/ui/traits/trait-as-struct-constructor.stderr +++ b/src/test/ui/traits/trait-as-struct-constructor.stderr @@ -6,3 +6,4 @@ LL | TraitNotAStruct{ value: 0 }; error: aborting due to previous error +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/try-block/try-block-in-edition2015.stderr b/src/test/ui/try-block/try-block-in-edition2015.stderr index 7034cdce7553..c94e43131faf 100644 --- a/src/test/ui/try-block/try-block-in-edition2015.stderr +++ b/src/test/ui/try-block/try-block-in-edition2015.stderr @@ -21,3 +21,4 @@ LL | let try_result: Option<_> = try { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0574`. diff --git a/src/test/ui/use/issue-18986.stderr b/src/test/ui/use/issue-18986.stderr index 14e1bb624033..6c23178c7001 100644 --- a/src/test/ui/use/issue-18986.stderr +++ b/src/test/ui/use/issue-18986.stderr @@ -6,3 +6,4 @@ LL | Trait { x: 42 } => () error: aborting due to previous error +For more information about this error, try `rustc --explain E0574`. From a9752596d3d377e34f99512eb6bc256512509610 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 7 Sep 2019 21:22:36 +0100 Subject: [PATCH 342/545] Add more tests for underscore imports --- src/test/ui/underscore-imports/hygiene-2.rs | 33 ++++++++++++++ src/test/ui/underscore-imports/hygiene.rs | 40 +++++++++++++++++ src/test/ui/underscore-imports/hygiene.stderr | 27 +++++++++++ .../ui/underscore-imports/macro-expanded.rs | 45 +++++++++++++++++++ 4 files changed, 145 insertions(+) create mode 100644 src/test/ui/underscore-imports/hygiene-2.rs create mode 100644 src/test/ui/underscore-imports/hygiene.rs create mode 100644 src/test/ui/underscore-imports/hygiene.stderr create mode 100644 src/test/ui/underscore-imports/macro-expanded.rs diff --git a/src/test/ui/underscore-imports/hygiene-2.rs b/src/test/ui/underscore-imports/hygiene-2.rs new file mode 100644 index 000000000000..bea61eae6b51 --- /dev/null +++ b/src/test/ui/underscore-imports/hygiene-2.rs @@ -0,0 +1,33 @@ +// Make sure that underscore imports with different contexts can exist in the +// same scope. + +// check-pass + +#![feature(decl_macro)] + +mod x { + pub use std::ops::Deref as _; +} + +macro n() { + pub use crate::x::*; +} + +#[macro_export] +macro_rules! p { + () => { pub use crate::x::*; } +} + +macro m($y:ident) { + mod $y { + crate::n!(); // Reexport of `Deref` should not be imported in `main` + crate::p!(); // Reexport of `Deref` should be imported into `main` + } +} + +m!(y); + +fn main() { + use crate::y::*; + (&()).deref(); +} diff --git a/src/test/ui/underscore-imports/hygiene.rs b/src/test/ui/underscore-imports/hygiene.rs new file mode 100644 index 000000000000..a254f6eaa598 --- /dev/null +++ b/src/test/ui/underscore-imports/hygiene.rs @@ -0,0 +1,40 @@ +// Make sure that underscore imports have the same hygiene considerations as +// other imports. + +#![feature(decl_macro)] + +mod x { + pub use std::ops::Deref as _; +} + + +macro glob_import() { + pub use crate::x::*; +} + +macro underscore_import() { + use std::ops::DerefMut as _; +} + +mod y { + crate::glob_import!(); + crate::underscore_import!(); +} + +macro create_module($y:ident) { + mod $y { + crate::glob_import!(); + crate::underscore_import!(); + } +} + +create_module!(z); + +fn main() { + use crate::y::*; + use crate::z::*; + glob_import!(); + underscore_import!(); + (&()).deref(); //~ ERROR no method named `deref` + (&mut ()).deref_mut(); //~ ERROR no method named `deref_mut` +} diff --git a/src/test/ui/underscore-imports/hygiene.stderr b/src/test/ui/underscore-imports/hygiene.stderr new file mode 100644 index 000000000000..44cfc5cc5d22 --- /dev/null +++ b/src/test/ui/underscore-imports/hygiene.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `deref` found for type `&()` in the current scope + --> $DIR/hygiene.rs:38:11 + | +LL | (&()).deref(); + | ^^^^^ method not found in `&()` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::ops::Deref; + | + +error[E0599]: no method named `deref_mut` found for type `&mut ()` in the current scope + --> $DIR/hygiene.rs:39:15 + | +LL | (&mut ()).deref_mut(); + | ^^^^^^^^^ method not found in `&mut ()` + | + = help: items from traits can only be used if the trait is in scope +help: the following trait is implemented but not in scope; perhaps add a `use` for it: + | +LL | use std::ops::DerefMut; + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. diff --git a/src/test/ui/underscore-imports/macro-expanded.rs b/src/test/ui/underscore-imports/macro-expanded.rs new file mode 100644 index 000000000000..43f527bc9a40 --- /dev/null +++ b/src/test/ui/underscore-imports/macro-expanded.rs @@ -0,0 +1,45 @@ +// Check that macro expanded underscore imports behave as expected + +// check-pass + +#![feature(decl_macro, rustc_attrs)] + +mod x { + pub use std::ops::Not as _; +} + +macro m() { + mod w { + mod y { + pub use std::ops::Deref as _; + } + use crate::x::*; + use self::y::*; + use std::ops::DerefMut as _; + fn f() { + false.not(); + (&()).deref(); + (&mut ()).deref_mut(); + } + } +} + +#[rustc_macro_transparency = "transparent"] +macro n() { + mod z { + pub use std::ops::Deref as _; + } + use crate::x::*; + use crate::z::*; + use std::ops::DerefMut as _; + fn f() { + false.not(); + (&()).deref(); + (&mut ()).deref_mut(); + } +} + +m!(); +n!(); + +fn main() {} From 1899432867b0f251771e7d3389b4039245f44949 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 13 Oct 2019 22:51:18 +0200 Subject: [PATCH 343/545] lowering: don't rely on parser directly. --- src/librustc/hir/lowering.rs | 20 ++++++++++++++------ src/librustc_interface/passes.rs | 19 ++++++++++++++++--- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 513512b9f6b2..062533f3d097 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -70,8 +70,8 @@ use syntax::print::pprust; use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned}; use syntax::symbol::{kw, sym, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; -use syntax::parse; -use syntax::parse::token::{self, Token}; +use syntax::parse::token::{self, Nonterminal, Token}; +use syntax::parse::ParseSess; use syntax::visit::{self, Visitor}; use syntax_pos::Span; @@ -87,6 +87,8 @@ pub struct LoweringContext<'a> { resolver: &'a mut dyn Resolver, + parser: &'static dyn Parser, + /// The items being lowered are collected here. items: BTreeMap, @@ -181,6 +183,13 @@ pub trait Resolver { fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; } +/// HACK(Centril): there is a cyclic dependency between the parser and lowering +/// if we don't have this trait. To avoid that dependency so that librustc is +/// independent of the parser, we use type erasure here. +pub trait Parser { + fn nt_to_tokenstream(&self, nt: &Nonterminal, sess: &ParseSess, span: Span) -> TokenStream; +} + /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. #[derive(Debug)] @@ -237,6 +246,7 @@ pub fn lower_crate( dep_graph: &DepGraph, krate: &Crate, resolver: &mut dyn Resolver, + parser: &'static dyn Parser, ) -> hir::Crate { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to @@ -250,6 +260,7 @@ pub fn lower_crate( sess, cstore, resolver, + parser, items: BTreeMap::new(), trait_items: BTreeMap::new(), impl_items: BTreeMap::new(), @@ -1023,10 +1034,7 @@ impl<'a> LoweringContext<'a> { fn lower_token(&mut self, token: Token) -> TokenStream { match token.kind { token::Interpolated(nt) => { - // FIXME(Centril): Consider indirection `(parse_sess.nt_to_tokenstream)(...)` - // to hack around the current hack that requires `nt_to_tokenstream` to live - // in the parser. - let tts = parse::nt_to_tokenstream(&nt, &self.sess.parse_sess, token.span); + let tts = self.parser.nt_to_tokenstream(&nt, &self.sess.parse_sess, token.span); self.lower_token_stream(tts) } _ => TokenTree::Token(token).into(), diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index a1dc5b01aba8..5078379e9205 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -5,7 +5,7 @@ use crate::proc_macro_decls; use log::{info, warn, log_enabled}; use rustc::dep_graph::DepGraph; use rustc::hir; -use rustc::hir::lowering::lower_crate; +use rustc::hir::lowering::{lower_crate, Parser}; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; @@ -38,9 +38,12 @@ use syntax::early_buffered_lints::BufferedEarlyLint; use syntax::ext::base::{NamedSyntaxExtension, ExtCtxt}; use syntax::mut_visit::MutVisitor; use syntax::parse::{self, PResult}; +use syntax::parse::token::Nonterminal; +use syntax::parse::ParseSess; +use syntax::tokenstream::TokenStream; use syntax::util::node_count::NodeCounter; use syntax::symbol::Symbol; -use syntax_pos::FileName; +use syntax_pos::{FileName, Span}; use syntax_ext; use rustc_serialize::json; @@ -532,6 +535,16 @@ fn configure_and_expand_inner<'a>( Ok((krate, resolver)) } +fn parser() -> &'static dyn Parser { + struct Parse; + impl Parser for Parse { + fn nt_to_tokenstream(&self, nt: &Nonterminal, sess: &ParseSess, span: Span) -> TokenStream { + syntax::parse::nt_to_tokenstream(nt, sess, span) + } + } + &Parse +} + pub fn lower_to_hir( sess: &Session, cstore: &CStore, @@ -541,7 +554,7 @@ pub fn lower_to_hir( ) -> Result { // Lower AST to HIR. let hir_forest = time(sess, "lowering AST -> HIR", || { - let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver); + let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver, parser()); if sess.opts.debugging_opts.hir_stats { hir_stats::print_hir_stats(&hir_crate); From 07e946caf7a4b9e5781b15f75b927b9e695b4f7c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 13 Oct 2019 23:27:18 +0200 Subject: [PATCH 344/545] lowering: connect to parser via function pointer instead --- src/librustc/hir/lowering.rs | 18 ++++++++---------- src/librustc_interface/passes.rs | 20 ++++---------------- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 062533f3d097..747848edc7a8 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -87,7 +87,10 @@ pub struct LoweringContext<'a> { resolver: &'a mut dyn Resolver, - parser: &'static dyn Parser, + /// HACK(Centril): there is a cyclic dependency between the parser and lowering + /// if we don't have this function pointer. To avoid that dependency so that + /// librustc is independent of the parser, we use dynamic dispatch here. + nt_to_tokenstream: NtToTokenstream, /// The items being lowered are collected here. items: BTreeMap, @@ -183,12 +186,7 @@ pub trait Resolver { fn has_derives(&self, node_id: NodeId, derives: SpecialDerives) -> bool; } -/// HACK(Centril): there is a cyclic dependency between the parser and lowering -/// if we don't have this trait. To avoid that dependency so that librustc is -/// independent of the parser, we use type erasure here. -pub trait Parser { - fn nt_to_tokenstream(&self, nt: &Nonterminal, sess: &ParseSess, span: Span) -> TokenStream; -} +type NtToTokenstream = fn(&Nonterminal, &ParseSess, Span) -> TokenStream; /// Context of `impl Trait` in code, which determines whether it is allowed in an HIR subtree, /// and if so, what meaning it has. @@ -246,7 +244,7 @@ pub fn lower_crate( dep_graph: &DepGraph, krate: &Crate, resolver: &mut dyn Resolver, - parser: &'static dyn Parser, + nt_to_tokenstream: NtToTokenstream, ) -> hir::Crate { // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to @@ -260,7 +258,7 @@ pub fn lower_crate( sess, cstore, resolver, - parser, + nt_to_tokenstream, items: BTreeMap::new(), trait_items: BTreeMap::new(), impl_items: BTreeMap::new(), @@ -1034,7 +1032,7 @@ impl<'a> LoweringContext<'a> { fn lower_token(&mut self, token: Token) -> TokenStream { match token.kind { token::Interpolated(nt) => { - let tts = self.parser.nt_to_tokenstream(&nt, &self.sess.parse_sess, token.span); + let tts = (self.nt_to_tokenstream)(&nt, &self.sess.parse_sess, token.span); self.lower_token_stream(tts) } _ => TokenTree::Token(token).into(), diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 5078379e9205..328798862b86 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -5,7 +5,7 @@ use crate::proc_macro_decls; use log::{info, warn, log_enabled}; use rustc::dep_graph::DepGraph; use rustc::hir; -use rustc::hir::lowering::{lower_crate, Parser}; +use rustc::hir::lowering::lower_crate; use rustc::hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc::lint; use rustc::middle::{self, reachable, resolve_lifetime, stability}; @@ -38,12 +38,9 @@ use syntax::early_buffered_lints::BufferedEarlyLint; use syntax::ext::base::{NamedSyntaxExtension, ExtCtxt}; use syntax::mut_visit::MutVisitor; use syntax::parse::{self, PResult}; -use syntax::parse::token::Nonterminal; -use syntax::parse::ParseSess; -use syntax::tokenstream::TokenStream; use syntax::util::node_count::NodeCounter; use syntax::symbol::Symbol; -use syntax_pos::{FileName, Span}; +use syntax_pos::FileName; use syntax_ext; use rustc_serialize::json; @@ -535,16 +532,6 @@ fn configure_and_expand_inner<'a>( Ok((krate, resolver)) } -fn parser() -> &'static dyn Parser { - struct Parse; - impl Parser for Parse { - fn nt_to_tokenstream(&self, nt: &Nonterminal, sess: &ParseSess, span: Span) -> TokenStream { - syntax::parse::nt_to_tokenstream(nt, sess, span) - } - } - &Parse -} - pub fn lower_to_hir( sess: &Session, cstore: &CStore, @@ -554,7 +541,8 @@ pub fn lower_to_hir( ) -> Result { // Lower AST to HIR. let hir_forest = time(sess, "lowering AST -> HIR", || { - let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver, parser()); + let nt_to_tokenstream = syntax::parse::nt_to_tokenstream; + let hir_crate = lower_crate(sess, cstore, &dep_graph, &krate, resolver, nt_to_tokenstream); if sess.opts.debugging_opts.hir_stats { hir_stats::print_hir_stats(&hir_crate); From 061b906683eccd01b59f848a7941f3fd7aff8b00 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sun, 13 Oct 2019 12:27:11 -0700 Subject: [PATCH 345/545] Return `false` from `needs_drop` for all zero-sized arrays --- src/librustc/ty/util.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 5ddf15317a31..b6e8b8b92e6c 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -1096,6 +1096,9 @@ fn needs_drop_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx> ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + // Zero-length arrays never contain anything to drop. + ty::Array(_, len) if len.try_eval_usize(tcx, param_env) == Some(0) => false, + // Structural recursion. ty::Array(ty, _) | ty::Slice(ty) => needs_drop(ty), From 8fd16baa57aafd4959bda052dad261da997e6862 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sun, 13 Oct 2019 12:27:45 -0700 Subject: [PATCH 346/545] Remove special case for zero-sized arrays from indirectly mut locals --- .../dataflow/impls/indirect_mutation.rs | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/indirect_mutation.rs b/src/librustc_mir/dataflow/impls/indirect_mutation.rs index 990425c3252e..bc09e3271792 100644 --- a/src/librustc_mir/dataflow/impls/indirect_mutation.rs +++ b/src/librustc_mir/dataflow/impls/indirect_mutation.rs @@ -104,25 +104,16 @@ impl<'tcx> TransferFunction<'_, '_, 'tcx> { kind: mir::BorrowKind, borrowed_place: &mir::Place<'tcx>, ) -> bool { - let borrowed_ty = borrowed_place.ty(self.body, self.tcx).ty; - - // Zero-sized types cannot be mutated, since there is nothing inside to mutate. - // - // FIXME: For now, we only exempt arrays of length zero. We need to carefully - // consider the effects before extending this to all ZSTs. - if let ty::Array(_, len) = borrowed_ty.kind { - if len.try_eval_usize(self.tcx, self.param_env) == Some(0) { - return false; - } - } - match kind { mir::BorrowKind::Mut { .. } => true, | mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique - => !borrowed_ty.is_freeze(self.tcx, self.param_env, DUMMY_SP), + => !borrowed_place + .ty(self.body, self.tcx) + .ty + .is_freeze(self.tcx, self.param_env, DUMMY_SP), } } } From 5c93492da914f972fb549e95db778adcbdf70480 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2019 07:29:02 +1100 Subject: [PATCH 347/545] Remove the `Option` in `TokenStream`. It means an allocation is required to create an empty `TokenStream`, but all other operations are simpler and marginally faster due to not having to check for `None`. Overall it simplifies the code for a negligible performance effect. The commit also removes `TokenStream::empty` by implementing `Default`, which is now possible. --- src/libsyntax/attr/mod.rs | 2 +- src/libsyntax/ext/expand.rs | 4 +- src/libsyntax/ext/mbe/transcribe.rs | 2 +- src/libsyntax/ext/placeholders.rs | 2 +- src/libsyntax/ext/proc_macro_server.rs | 2 +- src/libsyntax/mut_visit.rs | 6 +- src/libsyntax/parse/attr.rs | 2 +- src/libsyntax/tokenstream.rs | 216 ++++++++++--------------- src/libsyntax_ext/plugin_macro_defs.rs | 2 +- 9 files changed, 97 insertions(+), 141 deletions(-) diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 7bef693a5be4..c2c883fd20e7 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -551,7 +551,7 @@ impl MetaItem { impl MetaItemKind { pub fn tokens(&self, span: Span) -> TokenStream { match *self { - MetaItemKind::Word => TokenStream::empty(), + MetaItemKind::Word => TokenStream::default(), MetaItemKind::NameValue(ref lit) => { let mut vec = vec![TokenTree::token(token::Eq, span).into()]; lit.tokens().append_to_tree_and_joint_vec(&mut vec); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index bbd8da2acef0..ec87451edbd1 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -671,12 +671,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } Some(TokenTree::Token(..)) => {} - None => return TokenStream::empty(), + None => return TokenStream::default(), } self.cx.span_err(span, "custom attribute invocations must be \ of the form `#[foo]` or `#[foo(..)]`, the macro name must only be \ followed by a delimiter token"); - TokenStream::empty() + TokenStream::default() } fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) { diff --git a/src/libsyntax/ext/mbe/transcribe.rs b/src/libsyntax/ext/mbe/transcribe.rs index ba818ebd35c7..da930436d817 100644 --- a/src/libsyntax/ext/mbe/transcribe.rs +++ b/src/libsyntax/ext/mbe/transcribe.rs @@ -95,7 +95,7 @@ pub(super) fn transcribe( ) -> TokenStream { // Nothing for us to transcribe... if src.is_empty() { - return TokenStream::empty(); + return TokenStream::default(); } // We descend into the RHS (`src`), expanding things as we go. This stack contains the things diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 8eecef1020d0..43a49dbeb516 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -15,7 +15,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { fn mac_placeholder() -> ast::Mac { ast::Mac { path: ast::Path { span: DUMMY_SP, segments: Vec::new() }, - tts: TokenStream::empty().into(), + tts: TokenStream::default().into(), delim: ast::MacDelimiter::Brace, span: DUMMY_SP, prior_type_ascription: None, diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 021ec46d987c..27ac8a2b78e9 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -393,7 +393,7 @@ impl server::Types for Rustc<'_> { impl server::TokenStream for Rustc<'_> { fn new(&mut self) -> Self::TokenStream { - TokenStream::empty() + TokenStream::default() } fn is_empty(&mut self, stream: &Self::TokenStream) -> bool { stream.is_empty() diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 3923b9f297b9..60ee17d09b75 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -610,10 +610,8 @@ pub fn noop_visit_tt(tt: &mut TokenTree, vis: &mut T) { } pub fn noop_visit_tts(TokenStream(tts): &mut TokenStream, vis: &mut T) { - visit_opt(tts, |tts| { - let tts = Lrc::make_mut(tts); - visit_vec(tts, |(tree, _is_joint)| vis.visit_tt(tree)); - }) + let tts = Lrc::make_mut(tts); + visit_vec(tts, |(tree, _is_joint)| vis.visit_tt(tree)); } // Applies ident visitor if it's an ident; applies other visits to interpolated nodes. diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/attr.rs index e74f3045db80..0963efcfc8ac 100644 --- a/src/libsyntax/parse/attr.rs +++ b/src/libsyntax/parse/attr.rs @@ -203,7 +203,7 @@ impl<'a> Parser<'a> { }; TokenStream::from_streams(smallvec![eq.into(), tokens]) } else { - TokenStream::empty() + TokenStream::default() }; ast::AttrItem { path, tokens } }) diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index bef12ed4fada..d2def5630e6f 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -137,13 +137,8 @@ impl TokenTree { /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s /// instead of a representation of the abstract syntax tree. /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat. -/// -/// The use of `Option` is an optimization that avoids the need for an -/// allocation when the stream is empty. However, it is not guaranteed that an -/// empty stream is represented with `None`; it may be represented as a `Some` -/// around an empty `Vec`. -#[derive(Clone, Debug)] -pub struct TokenStream(pub Option>>); +#[derive(Clone, Debug, Default)] +pub struct TokenStream(pub Lrc>); pub type TreeAndJoint = (TokenTree, IsJoint); @@ -164,36 +159,34 @@ impl TokenStream { /// separating the two arguments with a comma for diagnostic suggestions. pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> { // Used to suggest if a user writes `foo!(a b);` - if let Some(ref stream) = self.0 { - let mut suggestion = None; - let mut iter = stream.iter().enumerate().peekable(); - while let Some((pos, ts)) = iter.next() { - if let Some((_, next)) = iter.peek() { - let sp = match (&ts, &next) { - (_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue, - ((TokenTree::Token(token_left), NonJoint), - (TokenTree::Token(token_right), _)) - if ((token_left.is_ident() && !token_left.is_reserved_ident()) - || token_left.is_lit()) && - ((token_right.is_ident() && !token_right.is_reserved_ident()) - || token_right.is_lit()) => token_left.span, - ((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(), - _ => continue, - }; - let sp = sp.shrink_to_hi(); - let comma = (TokenTree::token(token::Comma, sp), NonJoint); - suggestion = Some((pos, comma, sp)); - } - } - if let Some((pos, comma, sp)) = suggestion { - let mut new_stream = vec![]; - let parts = stream.split_at(pos + 1); - new_stream.extend_from_slice(parts.0); - new_stream.push(comma); - new_stream.extend_from_slice(parts.1); - return Some((TokenStream::new(new_stream), sp)); + let mut suggestion = None; + let mut iter = self.0.iter().enumerate().peekable(); + while let Some((pos, ts)) = iter.next() { + if let Some((_, next)) = iter.peek() { + let sp = match (&ts, &next) { + (_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue, + ((TokenTree::Token(token_left), NonJoint), + (TokenTree::Token(token_right), _)) + if ((token_left.is_ident() && !token_left.is_reserved_ident()) + || token_left.is_lit()) && + ((token_right.is_ident() && !token_right.is_reserved_ident()) + || token_right.is_lit()) => token_left.span, + ((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(), + _ => continue, + }; + let sp = sp.shrink_to_hi(); + let comma = (TokenTree::token(token::Comma, sp), NonJoint); + suggestion = Some((pos, comma, sp)); } } + if let Some((pos, comma, sp)) = suggestion { + let mut new_stream = vec![]; + let parts = self.0.split_at(pos + 1); + new_stream.extend_from_slice(parts.0); + new_stream.push(comma); + new_stream.extend_from_slice(parts.1); + return Some((TokenStream::new(new_stream), sp)); + } None } } @@ -225,28 +218,21 @@ impl PartialEq for TokenStream { } impl TokenStream { - pub fn len(&self) -> usize { - if let Some(ref slice) = self.0 { - slice.len() - } else { - 0 - } - } - - pub fn empty() -> TokenStream { - TokenStream(None) + pub fn new(streams: Vec) -> TokenStream { + TokenStream(Lrc::new(streams)) } pub fn is_empty(&self) -> bool { - match self.0 { - None => true, - Some(ref stream) => stream.is_empty(), - } + self.0.is_empty() + } + + pub fn len(&self) -> usize { + self.0.len() } pub(crate) fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream { match streams.len() { - 0 => TokenStream::empty(), + 0 => TokenStream::default(), 1 => streams.pop().unwrap(), _ => { // We are going to extend the first stream in `streams` with @@ -270,41 +256,24 @@ impl TokenStream { // Get the first stream. If it's `None`, create an empty // stream. let mut iter = streams.drain(); - let mut first_stream_lrc = match iter.next().unwrap().0 { - Some(first_stream_lrc) => first_stream_lrc, - None => Lrc::new(vec![]), - }; + let mut first_stream_lrc = iter.next().unwrap().0; // Append the elements to the first stream, after reserving // space for them. let first_vec_mut = Lrc::make_mut(&mut first_stream_lrc); first_vec_mut.reserve(num_appends); for stream in iter { - if let Some(stream) = stream.0 { - first_vec_mut.extend(stream.iter().cloned()); - } + first_vec_mut.extend(stream.0.iter().cloned()); } // Create the final `TokenStream`. - match first_vec_mut.len() { - 0 => TokenStream(None), - _ => TokenStream(Some(first_stream_lrc)), - } + TokenStream(first_stream_lrc) } } } - pub fn new(streams: Vec) -> TokenStream { - match streams.len() { - 0 => TokenStream(None), - _ => TokenStream(Some(Lrc::new(streams))), - } - } - pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec) { - if let Some(stream) = self.0 { - vec.extend(stream.iter().cloned()); - } + vec.extend(self.0.iter().cloned()); } pub fn trees(&self) -> Cursor { @@ -371,24 +340,22 @@ impl TokenStream { } pub fn map_enumerated TokenTree>(self, mut f: F) -> TokenStream { - TokenStream(self.0.map(|stream| { - Lrc::new( - stream - .iter() - .enumerate() - .map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint)) - .collect()) - })) + TokenStream(Lrc::new( + self.0 + .iter() + .enumerate() + .map(|(i, (tree, is_joint))| (f(i, tree.clone()), *is_joint)) + .collect() + )) } pub fn map TokenTree>(self, mut f: F) -> TokenStream { - TokenStream(self.0.map(|stream| { - Lrc::new( - stream - .iter() - .map(|(tree, is_joint)| (f(tree.clone()), *is_joint)) - .collect()) - })) + TokenStream(Lrc::new( + self.0 + .iter() + .map(|(tree, is_joint)| (f(tree.clone()), *is_joint)) + .collect() + )) } } @@ -406,44 +373,43 @@ impl TokenStreamBuilder { // If `self` is not empty and the last tree within the last stream is a // token tree marked with `Joint`... - if let Some(TokenStream(Some(ref mut last_stream_lrc))) = self.0.last_mut() { + if let Some(TokenStream(ref mut last_stream_lrc)) = self.0.last_mut() { if let Some((TokenTree::Token(last_token), Joint)) = last_stream_lrc.last() { // ...and `stream` is not empty and the first tree within it is // a token tree... - if let TokenStream(Some(ref mut stream_lrc)) = stream { - if let Some((TokenTree::Token(token), is_joint)) = stream_lrc.first() { + let TokenStream(ref mut stream_lrc) = stream; + if let Some((TokenTree::Token(token), is_joint)) = stream_lrc.first() { - // ...and the two tokens can be glued together... - if let Some(glued_tok) = last_token.glue(&token) { + // ...and the two tokens can be glued together... + if let Some(glued_tok) = last_token.glue(&token) { - // ...then do so, by overwriting the last token - // tree in `self` and removing the first token tree - // from `stream`. This requires using `make_mut()` - // on the last stream in `self` and on `stream`, - // and in practice this doesn't cause cloning 99.9% - // of the time. + // ...then do so, by overwriting the last token + // tree in `self` and removing the first token tree + // from `stream`. This requires using `make_mut()` + // on the last stream in `self` and on `stream`, + // and in practice this doesn't cause cloning 99.9% + // of the time. - // Overwrite the last token tree with the merged - // token. - let last_vec_mut = Lrc::make_mut(last_stream_lrc); - *last_vec_mut.last_mut().unwrap() = - (TokenTree::Token(glued_tok), *is_joint); + // Overwrite the last token tree with the merged + // token. + let last_vec_mut = Lrc::make_mut(last_stream_lrc); + *last_vec_mut.last_mut().unwrap() = + (TokenTree::Token(glued_tok), *is_joint); - // Remove the first token tree from `stream`. (This - // is almost always the only tree in `stream`.) - let stream_vec_mut = Lrc::make_mut(stream_lrc); - stream_vec_mut.remove(0); + // Remove the first token tree from `stream`. (This + // is almost always the only tree in `stream`.) + let stream_vec_mut = Lrc::make_mut(stream_lrc); + stream_vec_mut.remove(0); - // Don't push `stream` if it's empty -- that could - // block subsequent token gluing, by getting - // between two token trees that should be glued - // together. - if !stream.is_empty() { - self.0.push(stream); - } - return; + // Don't push `stream` if it's empty -- that could + // block subsequent token gluing, by getting + // between two token trees that should be glued + // together. + if !stream.is_empty() { + self.0.push(stream); } + return; } } } @@ -476,16 +442,11 @@ impl Cursor { } pub fn next_with_joint(&mut self) -> Option { - match self.stream.0 { - None => None, - Some(ref stream) => { - if self.index < stream.len() { - self.index += 1; - Some(stream[self.index - 1].clone()) - } else { - None - } - } + if self.index < self.stream.len() { + self.index += 1; + Some(self.stream.0[self.index - 1].clone()) + } else { + None } } @@ -494,16 +455,13 @@ impl Cursor { return; } let index = self.index; - let stream = mem::replace(&mut self.stream, TokenStream(None)); + let stream = mem::take(&mut self.stream); *self = TokenStream::from_streams(smallvec![stream, new_stream]).into_trees(); self.index = index; } pub fn look_ahead(&self, n: usize) -> Option { - match self.stream.0 { - None => None, - Some(ref stream) => stream[self.index ..].get(n).map(|(tree, _)| tree.clone()), - } + self.stream.0[self.index ..].get(n).map(|(tree, _)| tree.clone()) } } diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs index 315babceae32..62c7e188eba2 100644 --- a/src/libsyntax_ext/plugin_macro_defs.rs +++ b/src/libsyntax_ext/plugin_macro_defs.rs @@ -20,7 +20,7 @@ fn plugin_macro_def(name: Name, span: Span) -> P { attr::mk_word_item(Ident::new(sym::rustc_builtin_macro, span))); let parens: TreeAndJoint = TokenTree::Delimited( - DelimSpan::from_single(span), token::Paren, TokenStream::empty() + DelimSpan::from_single(span), token::Paren, TokenStream::default() ).into(); let trees = vec![parens.clone(), TokenTree::token(token::FatArrow, span).into(), parens]; From 1ce0347fd475424d66d4c26fb8ac70f1437982aa Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2019 12:01:12 +1100 Subject: [PATCH 348/545] Use `TokenStream::default()` in more places. --- src/libsyntax/parse/parser.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4a457f5a43ca..83a4acbe7025 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1548,7 +1548,7 @@ impl<'a> Parser<'a> { // This can happen due to a bad interaction of two unrelated recovery mechanisms with // mismatched delimiters *and* recovery lookahead on the likely typo `pub ident(` // (#62881). - return Ok((ret?, TokenStream::new(vec![]))); + return Ok((ret?, TokenStream::default())); } else { &mut self.token_cursor.stack[prev].last_token }; @@ -1563,7 +1563,7 @@ impl<'a> Parser<'a> { // This can happen due to a bad interaction of two unrelated recovery mechanisms // with mismatched delimiters *and* recovery lookahead on the likely typo // `pub ident(` (#62895, different but similar to the case above). - return Ok((ret?, TokenStream::new(vec![]))); + return Ok((ret?, TokenStream::default())); } }; From 18b48bf4b9158611cd77bd5fae123a5fa3f052a5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 10 Oct 2019 12:55:39 +1100 Subject: [PATCH 349/545] Lazify some `mac_placeholder()` calls. This avoids some unnecessary creation of empty token streams. --- src/libsyntax/ext/placeholders.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs index 43a49dbeb516..4fae25bbde62 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax/ext/placeholders.rs @@ -32,12 +32,12 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { attrs: ThinVec::new(), kind: ast::ExprKind::Mac(mac_placeholder()), }); - let ty = P(ast::Ty { + let ty = || P(ast::Ty { id, kind: ast::TyKind::Mac(mac_placeholder()), span, }); - let pat = P(ast::Pat { + let pat = || P(ast::Pat { id, kind: ast::PatKind::Mac(mac_placeholder()), span, @@ -83,7 +83,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { body: expr_placeholder(), guard: None, id, - pat, + pat: pat(), span, is_placeholder: true, } @@ -105,7 +105,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { id, ident, is_shorthand: false, - pat, + pat: pat(), span, is_placeholder: true, } @@ -124,9 +124,9 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { ast::Param { attrs: Default::default(), id, - pat, + pat: pat(), span, - ty, + ty: ty(), is_placeholder: true, } ]), @@ -136,7 +136,7 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment { id, ident: None, span, - ty, + ty: ty(), vis, is_placeholder: true, } From c08a8713381ed67caea826a793145240cd873081 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sun, 13 Oct 2019 16:00:49 -0700 Subject: [PATCH 350/545] Add regression test for #65348 --- src/test/ui/consts/issue-65348.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/ui/consts/issue-65348.rs diff --git a/src/test/ui/consts/issue-65348.rs b/src/test/ui/consts/issue-65348.rs new file mode 100644 index 000000000000..5eafa831d631 --- /dev/null +++ b/src/test/ui/consts/issue-65348.rs @@ -0,0 +1,23 @@ +// check-pass + +struct Generic(T); + +impl Generic { + const ARRAY: [T; 0] = []; + const NEWTYPE_ARRAY: Generic<[T; 0]> = Generic([]); + const ARRAY_FIELD: Generic<(i32, [T; 0])> = Generic((0, [])); +} + +pub const fn array() -> &'static T { + &Generic::::ARRAY[0] +} + +pub const fn newtype_array() -> &'static T { + &Generic::::NEWTYPE_ARRAY.0[0] +} + +pub const fn array_field() -> &'static T { + &(Generic::::ARRAY_FIELD.0).1[0] +} + +fn main() {} From 5c8fdc1954544f0e8bb3da0dfa8c4516731b0b84 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 14 Oct 2019 10:45:25 +0900 Subject: [PATCH 351/545] Add test for issue-44153 --- src/test/ui/associated-types/issue-44153.rs | 19 +++++++++++++++++++ .../ui/associated-types/issue-44153.stderr | 16 ++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/test/ui/associated-types/issue-44153.rs create mode 100644 src/test/ui/associated-types/issue-44153.stderr diff --git a/src/test/ui/associated-types/issue-44153.rs b/src/test/ui/associated-types/issue-44153.rs new file mode 100644 index 000000000000..2101cb61a94d --- /dev/null +++ b/src/test/ui/associated-types/issue-44153.rs @@ -0,0 +1,19 @@ +pub trait Array { + type Element; +} + +pub trait Visit { + fn visit() {} +} + +impl Array for () { + type Element = (); +} + +impl<'a> Visit for () where + (): Array, +{} + +fn main() { + <() as Visit>::visit(); //~ ERROR: type mismatch resolving +} diff --git a/src/test/ui/associated-types/issue-44153.stderr b/src/test/ui/associated-types/issue-44153.stderr new file mode 100644 index 000000000000..b62a866a20be --- /dev/null +++ b/src/test/ui/associated-types/issue-44153.stderr @@ -0,0 +1,16 @@ +error[E0271]: type mismatch resolving `<() as Array>::Element == &()` + --> $DIR/issue-44153.rs:18:5 + | +LL | fn visit() {} + | ---------- required by `Visit::visit` +... +LL | <() as Visit>::visit(); + | ^^^^^^^^^^^^^^^^^^^^ expected (), found &() + | + = note: expected type `()` + found type `&()` + = note: required because of the requirements on the impl of `Visit` for `()` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0271`. From 6323180b4a354c937c42d3483f5716d2d08261df Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 14 Oct 2019 10:45:56 +0900 Subject: [PATCH 352/545] Add test for issue-47486 --- src/test/ui/issues/issue-47486.rs | 4 ++++ src/test/ui/issues/issue-47486.stderr | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 src/test/ui/issues/issue-47486.rs create mode 100644 src/test/ui/issues/issue-47486.stderr diff --git a/src/test/ui/issues/issue-47486.rs b/src/test/ui/issues/issue-47486.rs new file mode 100644 index 000000000000..d686f02a9fe3 --- /dev/null +++ b/src/test/ui/issues/issue-47486.rs @@ -0,0 +1,4 @@ +fn main() { + () < std::mem::size_of::<_>(); //~ ERROR: mismatched types + [0u8; std::mem::size_of::<_>()]; //~ ERROR: type annotations needed +} diff --git a/src/test/ui/issues/issue-47486.stderr b/src/test/ui/issues/issue-47486.stderr new file mode 100644 index 000000000000..af6e3010f795 --- /dev/null +++ b/src/test/ui/issues/issue-47486.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/issue-47486.rs:2:10 + | +LL | () < std::mem::size_of::<_>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found usize + | + = note: expected type `()` + found type `usize` + +error[E0282]: type annotations needed + --> $DIR/issue-47486.rs:3:11 + | +LL | [0u8; std::mem::size_of::<_>()]; + | ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0282, E0308. +For more information about an error, try `rustc --explain E0282`. From f653db92d691ba3ebeb77dc75b6cb51cbf31519b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 14 Oct 2019 10:46:58 +0900 Subject: [PATCH 353/545] Add test for issue-48010 --- src/test/ui/associated-types/issue-48010.rs | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/ui/associated-types/issue-48010.rs diff --git a/src/test/ui/associated-types/issue-48010.rs b/src/test/ui/associated-types/issue-48010.rs new file mode 100644 index 000000000000..70e30c132d05 --- /dev/null +++ b/src/test/ui/associated-types/issue-48010.rs @@ -0,0 +1,23 @@ +// check-pass + +#![crate_type = "lib"] + +pub struct Foo; + +pub struct Path { + _inner: T::Slice, +} + +pub trait Bar: Sized { + type Slice: ?Sized; + + fn open(_: &Path); +} + +impl Bar for Foo { + type Slice = [u8]; + + fn open(_: &Path) { + unimplemented!() + } +} From 88a495cdcff92a7322c5721da3dc12acc04fb1a9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 14 Oct 2019 10:47:14 +0900 Subject: [PATCH 354/545] Add test for issue-48027 --- src/test/ui/associated-item/issue-48027.rs | 8 +++++++ .../ui/associated-item/issue-48027.stderr | 21 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/test/ui/associated-item/issue-48027.rs create mode 100644 src/test/ui/associated-item/issue-48027.stderr diff --git a/src/test/ui/associated-item/issue-48027.rs b/src/test/ui/associated-item/issue-48027.rs new file mode 100644 index 000000000000..c9b4ccd3e8a9 --- /dev/null +++ b/src/test/ui/associated-item/issue-48027.rs @@ -0,0 +1,8 @@ +trait Bar { + const X: usize; + fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: type annotations needed +} + +impl dyn Bar {} //~ ERROR: the trait `Bar` cannot be made into an object + +fn main() {} diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr new file mode 100644 index 000000000000..562146a426d2 --- /dev/null +++ b/src/test/ui/associated-item/issue-48027.stderr @@ -0,0 +1,21 @@ +error[E0038]: the trait `Bar` cannot be made into an object + --> $DIR/issue-48027.rs:6:6 + | +LL | const X: usize; + | - the trait cannot contain associated consts like `X` +... +LL | impl dyn Bar {} + | ^^^^^^^ the trait `Bar` cannot be made into an object + +error[E0283]: type annotations needed: cannot resolve `_: Bar` + --> $DIR/issue-48027.rs:3:32 + | +LL | const X: usize; + | --------------- required by `Bar::X` +LL | fn return_n(&self) -> [u8; Bar::X]; + | ^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0038, E0283. +For more information about an error, try `rustc --explain E0038`. From f6e01e8d4098eccb9234368a576342cb781265eb Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 14 Oct 2019 10:47:39 +0900 Subject: [PATCH 355/545] Add test for issue-48638 --- src/test/ui/wf/issue-48638.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/ui/wf/issue-48638.rs diff --git a/src/test/ui/wf/issue-48638.rs b/src/test/ui/wf/issue-48638.rs new file mode 100644 index 000000000000..f07843103321 --- /dev/null +++ b/src/test/ui/wf/issue-48638.rs @@ -0,0 +1,21 @@ +// check-pass + +pub trait D {} +pub struct DT; +impl D for DT {} + +pub trait A: Sized { + type AS; +} + +pub struct As(R); + +pub struct AT; +impl A for AT { + type AS = As; +} + +#[repr(packed)] +struct S(>::AS); + +fn main() {} From 4bb771615e194e64d0fc9cd97c1cdcc4972a1771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 13 Oct 2019 21:48:39 -0700 Subject: [PATCH 356/545] Bring attention to suggestions when the only difference is capitalization --- src/librustc/session/config.rs | 3 +- src/librustc_codegen_ssa/back/write.rs | 6 +++- .../annotate_snippet_emitter_writer.rs | 4 +++ src/librustc_errors/emitter.rs | 32 ++++++++++++++++--- src/librustc_errors/lib.rs | 32 ++++++++++++------- src/libsyntax/json.rs | 6 +++- src/libsyntax/source_map.rs | 3 ++ .../const-parameter-uppercase-lint.stderr | 2 +- .../ui/consts/const-eval/const_fn_ptr.stderr | 2 +- ...issue-43871-enum-instead-of-variant.stderr | 2 +- ...ssue-56028-there-is-an-enum-variant.stderr | 4 +-- .../ui/enable-unstable-lib-feature.stderr | 2 +- src/test/ui/error-codes/E0423.stderr | 2 +- src/test/ui/expr_attr_paren_order.stderr | 2 +- .../extern-prelude-from-opaque-fail.stderr | 2 +- src/test/ui/hygiene/globs.stderr | 2 +- .../hygiene/rustc-macro-transparency.stderr | 2 +- src/test/ui/issues/issue-10200.stderr | 2 +- src/test/ui/issues/issue-17546.stderr | 4 +-- .../ui/issues/issue-17718-const-naming.stderr | 2 +- src/test/ui/issues/issue-46332.stderr | 2 +- .../lint/lint-group-nonstandard-style.stderr | 2 +- ...lint-lowercase-static-const-pattern.stderr | 6 ++-- .../ui/lint/lint-non-camel-case-types.stderr | 14 ++++---- .../lint/lint-non-snake-case-functions.stderr | 12 +++---- ...lint-non-uppercase-associated-const.stderr | 2 +- .../ui/lint/lint-non-uppercase-statics.stderr | 4 +-- .../ui/lint/lint-uppercase-variables.stderr | 8 ++--- src/test/ui/lint/not_found.stderr | 4 +-- src/test/ui/lint/reasons.stderr | 2 +- src/test/ui/lint/use_suggestion_json.stderr | 2 +- src/test/ui/resolve/issue-21221-1.stderr | 2 +- src/test/ui/resolve/issue-39226.stderr | 2 +- src/test/ui/resolve/levenshtein.stderr | 4 +-- .../issue-52202-use-suggestions.stderr | 2 +- .../inaccessible-test-modules.stderr | 4 +-- .../ui/traits/trait-impl-for-module.stderr | 2 +- src/test/ui/utf8_idents.stderr | 2 +- 38 files changed, 121 insertions(+), 71 deletions(-) diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 25e68e6408de..e7542029ac63 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -23,7 +23,7 @@ use syntax::feature_gate::UnstableFeatures; use syntax::source_map::SourceMap; use errors::emitter::HumanReadableErrorType; -use errors::{ColorConfig, FatalError, Handler}; +use errors::{ColorConfig, FatalError, Handler, SourceMapperDyn}; use getopts; @@ -1854,6 +1854,7 @@ struct NullEmitter; impl errors::emitter::Emitter for NullEmitter { fn emit_diagnostic(&mut self, _: &errors::Diagnostic) {} + fn source_map(&self) -> Option<&Lrc> { None } } // Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`. diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 481db26e1a84..ef3b115890f8 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -22,7 +22,8 @@ use rustc::util::common::{time_depth, set_time_depth, print_time_passes_entry}; use rustc::util::profiling::SelfProfilerRef; use rustc_fs_util::link_or_copy; use rustc_data_structures::svh::Svh; -use rustc_errors::{Handler, Level, FatalError, DiagnosticId}; +use rustc_data_structures::sync::Lrc; +use rustc_errors::{Handler, Level, FatalError, DiagnosticId, SourceMapperDyn}; use rustc_errors::emitter::{Emitter}; use rustc_target::spec::MergeFunctions; use syntax::attr; @@ -1681,6 +1682,9 @@ impl Emitter for SharedEmitter { } drop(self.sender.send(SharedEmitterMessage::AbortIfErrors)); } + fn source_map(&self) -> Option<&Lrc> { + None + } } impl SharedEmitterMain { diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 0281d10fd930..16a1a28cd3a8 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -49,6 +49,10 @@ impl Emitter for AnnotateSnippetEmitterWriter { &suggestions); } + fn source_map(&self) -> Option<&Lrc> { + self.source_map.as_ref() + } + fn should_show_explain(&self) -> bool { !self.short_message } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 68f933363daa..040844537680 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -192,6 +192,8 @@ pub trait Emitter { true } + fn source_map(&self) -> Option<&Lrc>; + /// Formats the substitutions of the primary_span /// /// The are a lot of conditions to this method, but in short: @@ -204,7 +206,7 @@ pub trait Emitter { /// we return the original `primary_span` and the original suggestions. fn primary_span_formatted<'a>( &mut self, - db: &'a Diagnostic + db: &'a Diagnostic, ) -> (MultiSpan, &'a [CodeSuggestion]) { let mut primary_span = db.span.clone(); if let Some((sugg, rest)) = db.suggestions.split_first() { @@ -234,7 +236,20 @@ pub trait Emitter { format!("help: {}", sugg.msg) } else { // Show the default suggestion text with the substitution - format!("help: {}: `{}`", sugg.msg, substitution) + format!( + "help: {}{}: `{}`", + sugg.msg, + if self.source_map().as_ref().map(|sm| substitution.to_lowercase() == sm + .span_to_snippet(sugg.substitutions[0].parts[0].span) + .unwrap() + .to_lowercase()).unwrap_or(false) + { + " (notice the capitalization)" + } else { + "" + }, + substitution, + ) }; primary_span.push_span_label(sugg.substitutions[0].parts[0].span, msg); @@ -382,6 +397,10 @@ pub trait Emitter { } impl Emitter for EmitterWriter { + fn source_map(&self) -> Option<&Lrc> { + self.sm.as_ref() + } + fn emit_diagnostic(&mut self, db: &Diagnostic) { let mut children = db.children.clone(); let (mut primary_span, suggestions) = self.primary_span_formatted(&db); @@ -1461,7 +1480,9 @@ impl EmitterWriter { let suggestions = suggestion.splice_lines(&**sm); let mut row_num = 2; - for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) { + let mut notice_capitalization = false; + for (complete, parts, only_capitalization) in suggestions.iter().take(MAX_SUGGESTIONS) { + notice_capitalization |= only_capitalization; // Only show underline if the suggestion spans a single line and doesn't cover the // entirety of the code output. If you have multiple replacements in the same line // of code, show the underline. @@ -1552,7 +1573,10 @@ impl EmitterWriter { } if suggestions.len() > MAX_SUGGESTIONS { let msg = format!("and {} other candidates", suggestions.len() - MAX_SUGGESTIONS); - buffer.puts(row_num, 0, &msg, Style::NoStyle); + buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle); + } else if notice_capitalization { + let msg = "notice the capitalization difference"; + buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle); } emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; Ok(()) diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 2fae584c1536..babaeb7e532a 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -37,13 +37,16 @@ pub mod registry; mod styled_buffer; mod lock; -use syntax_pos::{BytePos, - Loc, - FileLinesResult, - SourceFile, - FileName, - MultiSpan, - Span}; +use syntax_pos::{ + BytePos, + FileLinesResult, + FileName, + Loc, + MultiSpan, + SourceFile, + Span, + SpanSnippetError, +}; /// Indicates the confidence in the correctness of a suggestion. /// @@ -147,6 +150,7 @@ pub trait SourceMapper { fn lookup_char_pos(&self, pos: BytePos) -> Loc; fn span_to_lines(&self, sp: Span) -> FileLinesResult; fn span_to_string(&self, sp: Span) -> String; + fn span_to_snippet(&self, sp: Span) -> Result; fn span_to_filename(&self, sp: Span) -> FileName; fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; @@ -155,9 +159,12 @@ pub trait SourceMapper { } impl CodeSuggestion { - /// Returns the assembled code suggestions and whether they should be shown with an underline. - pub fn splice_lines(&self, cm: &SourceMapperDyn) - -> Vec<(String, Vec)> { + /// 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: &SourceMapperDyn, + ) -> Vec<(String, Vec, bool)> { use syntax_pos::{CharPos, Pos}; fn push_trailing(buf: &mut String, @@ -232,6 +239,8 @@ impl CodeSuggestion { prev_hi = cm.lookup_char_pos(part.span.hi()); prev_line = fm.get_line(prev_hi.line - 1); } + let only_capitalization = buf.clone().to_lowercase() + == cm.span_to_snippet(bounding_span).unwrap().to_lowercase(); // 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); @@ -240,7 +249,8 @@ impl CodeSuggestion { while buf.ends_with('\n') { buf.pop(); } - (buf, substitution.parts) + (buf, substitution.parts, only_capitalization) + }).collect() } } diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 2423e1070fc3..4cf987417b8e 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -12,7 +12,7 @@ use crate::source_map::{SourceMap, FilePathMapping}; use errors::registry::Registry; -use errors::{SubDiagnostic, CodeSuggestion, SourceMapper}; +use errors::{SubDiagnostic, CodeSuggestion, SourceMapper, SourceMapperDyn}; use errors::{DiagnosticId, Applicability}; use errors::emitter::{Emitter, HumanReadableErrorType}; @@ -113,6 +113,10 @@ impl Emitter for JsonEmitter { } } + fn source_map(&self) -> Option<&Lrc> { + Some(&self.sm) + } + fn should_show_explain(&self) -> bool { match self.json_rendered { HumanReadableErrorType::Short(_) => false, diff --git a/src/libsyntax/source_map.rs b/src/libsyntax/source_map.rs index 7d0d2392945e..f6ba75dd5b53 100644 --- a/src/libsyntax/source_map.rs +++ b/src/libsyntax/source_map.rs @@ -987,6 +987,9 @@ impl SourceMapper for SourceMap { fn span_to_string(&self, sp: Span) -> String { self.span_to_string(sp) } + fn span_to_snippet(&self, sp: Span) -> Result { + self.span_to_snippet(sp) + } fn span_to_filename(&self, sp: Span) -> FileName { self.span_to_filename(sp) } diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr index fddb06981bc7..32cf8d8a01a7 100644 --- a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr +++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr @@ -10,7 +10,7 @@ error: const parameter `x` should have an upper case name --> $DIR/const-parameter-uppercase-lint.rs:6:15 | LL | fn noop() { - | ^ help: convert the identifier to upper case: `X` + | ^ help: convert the identifier to upper case (notice the capitalization): `X` | note: lint level defined here --> $DIR/const-parameter-uppercase-lint.rs:4:9 diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.stderr b/src/test/ui/consts/const-eval/const_fn_ptr.stderr index 2fbb19322442..9a5871905a05 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr.stderr @@ -20,7 +20,7 @@ warning: constant `X_const` should have an upper case name --> $DIR/const_fn_ptr.rs:9:7 | LL | const X_const: fn(usize) -> usize = double_const; - | ^^^^^^^ help: convert the identifier to upper case: `X_CONST` + | ^^^^^^^ help: convert the identifier to upper case (notice the capitalization): `X_CONST` | = note: `#[warn(non_upper_case_globals)]` on by default diff --git a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr index d8826d4072a9..ef68bf52cf3b 100644 --- a/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr +++ b/src/test/ui/did_you_mean/issue-43871-enum-instead-of-variant.stderr @@ -55,7 +55,7 @@ LL | let z = ManyVariants::Three(); | ^^^^^^^^^^^^^^^^^^^ LL | let z = ManyVariants::Four(); | ^^^^^^^^^^^^^^^^^^ -and 6 other candidates + and 6 other candidates error: aborting due to 5 previous errors diff --git a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr index 8d3a86df0233..cb350a1faeed 100644 --- a/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr +++ b/src/test/ui/did_you_mean/issue-56028-there-is-an-enum-variant.stderr @@ -13,7 +13,7 @@ LL | fn setup() -> Determine { Set } | ^^^^^^^^^ LL | fn setup() -> PutDown { Set } | ^^^^^^^ -and 3 other candidates + and 3 other candidates error[E0425]: cannot find value `Set` in this scope --> $DIR/issue-56028-there-is-an-enum-variant.rs:9:21 @@ -30,7 +30,7 @@ LL | use Determine::Set; | LL | use PutDown::Set; | -and 3 other candidates + and 3 other candidates error: aborting due to 2 previous errors diff --git a/src/test/ui/enable-unstable-lib-feature.stderr b/src/test/ui/enable-unstable-lib-feature.stderr index d5b8c0efaad3..d89f804f15bd 100644 --- a/src/test/ui/enable-unstable-lib-feature.stderr +++ b/src/test/ui/enable-unstable-lib-feature.stderr @@ -2,7 +2,7 @@ error: function `BOGUS` should have a snake case name --> $DIR/enable-unstable-lib-feature.rs:11:8 | LL | pub fn BOGUS() { } - | ^^^^^ help: convert the identifier to snake case: `bogus` + | ^^^^^ help: convert the identifier to snake case (notice the capitalization): `bogus` | note: lint level defined here --> $DIR/enable-unstable-lib-feature.rs:6:9 diff --git a/src/test/ui/error-codes/E0423.stderr b/src/test/ui/error-codes/E0423.stderr index ce631ca4bf78..754006bc217e 100644 --- a/src/test/ui/error-codes/E0423.stderr +++ b/src/test/ui/error-codes/E0423.stderr @@ -34,7 +34,7 @@ LL | let f = Foo(); | ^^^ | | | did you mean `Foo { /* fields */ }`? - | help: a function with a similar name exists: `foo` + | help: a function with a similar name exists (notice the capitalization): `foo` error[E0423]: expected value, found struct `T` --> $DIR/E0423.rs:14:8 diff --git a/src/test/ui/expr_attr_paren_order.stderr b/src/test/ui/expr_attr_paren_order.stderr index 89f615f53ddd..57a9350c089a 100644 --- a/src/test/ui/expr_attr_paren_order.stderr +++ b/src/test/ui/expr_attr_paren_order.stderr @@ -2,7 +2,7 @@ error: variable `X` should have a snake case name --> $DIR/expr_attr_paren_order.rs:19:17 | LL | let X = 0; - | ^ help: convert the identifier to snake case: `x` + | ^ help: convert the identifier to snake case (notice the capitalization): `x` | note: lint level defined here --> $DIR/expr_attr_paren_order.rs:17:17 diff --git a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr index 65133eb1e187..1f5e46c133dd 100644 --- a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -5,7 +5,7 @@ LL | use my_core; | ^^^^^^^ | | | no `my_core` in the root - | help: a similar name exists in the module: `my_core` + | help: a similar name exists in the module (notice the capitalization): `my_core` error[E0432]: unresolved import `my_core` --> $DIR/extern-prelude-from-opaque-fail.rs:7:13 diff --git a/src/test/ui/hygiene/globs.stderr b/src/test/ui/hygiene/globs.stderr index 7e0f4e4e0b8f..7acb266f49c0 100644 --- a/src/test/ui/hygiene/globs.stderr +++ b/src/test/ui/hygiene/globs.stderr @@ -34,7 +34,7 @@ LL | use foo::test2::test::g; | LL | use foo::test::g; | -and 2 other candidates + and 2 other candidates error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:61:12 diff --git a/src/test/ui/hygiene/rustc-macro-transparency.stderr b/src/test/ui/hygiene/rustc-macro-transparency.stderr index 5eacfdf8dee1..45a2efebbb8d 100644 --- a/src/test/ui/hygiene/rustc-macro-transparency.stderr +++ b/src/test/ui/hygiene/rustc-macro-transparency.stderr @@ -2,7 +2,7 @@ error[E0425]: cannot find value `Opaque` in this scope --> $DIR/rustc-macro-transparency.rs:26:5 | LL | Opaque; - | ^^^^^^ help: a local variable with a similar name exists: `opaque` + | ^^^^^^ help: a local variable with a similar name exists (notice the capitalization): `opaque` error[E0423]: expected value, found macro `semitransparent` --> $DIR/rustc-macro-transparency.rs:29:5 diff --git a/src/test/ui/issues/issue-10200.stderr b/src/test/ui/issues/issue-10200.stderr index 544716e89b39..b1057d45869a 100644 --- a/src/test/ui/issues/issue-10200.stderr +++ b/src/test/ui/issues/issue-10200.stderr @@ -2,7 +2,7 @@ error[E0532]: expected tuple struct/variant, found function `foo` --> $DIR/issue-10200.rs:6:9 | LL | foo(x) - | ^^^ help: a tuple struct with a similar name exists: `Foo` + | ^^^ help: a tuple struct with a similar name exists (notice the capitalization): `Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr index e27f49b4a3f0..1f71e159f182 100644 --- a/src/test/ui/issues/issue-17546.stderr +++ b/src/test/ui/issues/issue-17546.stderr @@ -27,7 +27,7 @@ LL | use std::prelude::v1::Result; | LL | use std::result::Result; | -and 1 other candidates + and 1 other candidates error[E0573]: expected type, found variant `Result` --> $DIR/issue-17546.rs:28:13 @@ -44,7 +44,7 @@ LL | use std::prelude::v1::Result; | LL | use std::result::Result; | -and 1 other candidates + and 1 other candidates error[E0573]: expected type, found variant `NoResult` --> $DIR/issue-17546.rs:33:15 diff --git a/src/test/ui/issues/issue-17718-const-naming.stderr b/src/test/ui/issues/issue-17718-const-naming.stderr index 1fe1821292c0..e320c436f5b6 100644 --- a/src/test/ui/issues/issue-17718-const-naming.stderr +++ b/src/test/ui/issues/issue-17718-const-naming.stderr @@ -15,7 +15,7 @@ error: constant `foo` should have an upper case name --> $DIR/issue-17718-const-naming.rs:4:7 | LL | const foo: isize = 3; - | ^^^ help: convert the identifier to upper case: `FOO` + | ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO` | note: lint level defined here --> $DIR/issue-17718-const-naming.rs:2:9 diff --git a/src/test/ui/issues/issue-46332.stderr b/src/test/ui/issues/issue-46332.stderr index 812a50000d1c..c7e9d71700e6 100644 --- a/src/test/ui/issues/issue-46332.stderr +++ b/src/test/ui/issues/issue-46332.stderr @@ -2,7 +2,7 @@ error[E0422]: cannot find struct, variant or union type `TyUInt` in this scope --> $DIR/issue-46332.rs:9:5 | LL | TyUInt {}; - | ^^^^^^ help: a struct with a similar name exists: `TyUint` + | ^^^^^^ help: a struct with a similar name exists (notice the capitalization): `TyUint` error: aborting due to previous error diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr index 1cc973d32c2d..1ecd0f38826a 100644 --- a/src/test/ui/lint/lint-group-nonstandard-style.stderr +++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr @@ -41,7 +41,7 @@ error: static variable `bad` should have an upper case name --> $DIR/lint-group-nonstandard-style.rs:14:16 | LL | static bad: isize = 1; - | ^^^ help: convert the identifier to upper case: `BAD` + | ^^^ help: convert the identifier to upper case (notice the capitalization): `BAD` | note: lint level defined here --> $DIR/lint-group-nonstandard-style.rs:10:14 diff --git a/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr b/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr index d95510ccd2d2..5cac1c3d0535 100644 --- a/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr +++ b/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr @@ -2,7 +2,7 @@ error: constant in pattern `a` should have an upper case name --> $DIR/lint-lowercase-static-const-pattern.rs:11:13 | LL | (0, a) => 0, - | ^ help: convert the identifier to upper case: `A` + | ^ help: convert the identifier to upper case (notice the capitalization): `A` | note: lint level defined here --> $DIR/lint-lowercase-static-const-pattern.rs:4:9 @@ -14,13 +14,13 @@ error: constant in pattern `aha` should have an upper case name --> $DIR/lint-lowercase-static-const-pattern.rs:26:13 | LL | (0, aha) => 0, - | ^^^ help: convert the identifier to upper case: `AHA` + | ^^^ help: convert the identifier to upper case (notice the capitalization): `AHA` error: constant in pattern `not_okay` should have an upper case name --> $DIR/lint-lowercase-static-const-pattern.rs:40:13 | LL | (0, not_okay) => 0, - | ^^^^^^^^ help: convert the identifier to upper case: `NOT_OKAY` + | ^^^^^^^^ help: convert the identifier to upper case (notice the capitalization): `NOT_OKAY` error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/lint-non-camel-case-types.stderr b/src/test/ui/lint/lint-non-camel-case-types.stderr index 432a16debc69..02f7db045e5c 100644 --- a/src/test/ui/lint/lint-non-camel-case-types.stderr +++ b/src/test/ui/lint/lint-non-camel-case-types.stderr @@ -14,43 +14,43 @@ error: type `foo` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:7:8 | LL | struct foo { - | ^^^ help: convert the identifier to upper camel case: `Foo` + | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo` error: type `foo2` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:11:6 | LL | enum foo2 { - | ^^^^ help: convert the identifier to upper camel case: `Foo2` + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo2` error: type `foo3` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:15:8 | LL | struct foo3 { - | ^^^^ help: convert the identifier to upper camel case: `Foo3` + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo3` error: type `foo4` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:19:6 | LL | type foo4 = isize; - | ^^^^ help: convert the identifier to upper camel case: `Foo4` + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo4` error: variant `bar` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:22:5 | LL | bar - | ^^^ help: convert the identifier to upper camel case: `Bar` + | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Bar` error: trait `foo6` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:25:7 | LL | trait foo6 { - | ^^^^ help: convert the identifier to upper camel case: `Foo6` + | ^^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo6` error: type parameter `ty` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:29:6 | LL | fn f(_: ty) {} - | ^^ help: convert the identifier to upper camel case: `Ty` + | ^^ help: convert the identifier to upper camel case (notice the capitalization): `Ty` error: aborting due to 8 previous errors diff --git a/src/test/ui/lint/lint-non-snake-case-functions.stderr b/src/test/ui/lint/lint-non-snake-case-functions.stderr index 49cbfa941261..2e7b53b05d16 100644 --- a/src/test/ui/lint/lint-non-snake-case-functions.stderr +++ b/src/test/ui/lint/lint-non-snake-case-functions.stderr @@ -2,7 +2,7 @@ error: method `Foo_Method` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:7:8 | LL | fn Foo_Method() {} - | ^^^^^^^^^^ help: convert the identifier to snake case: `foo_method` + | ^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `foo_method` | note: lint level defined here --> $DIR/lint-non-snake-case-functions.rs:1:9 @@ -26,19 +26,19 @@ error: method `render_HTML` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:17:8 | LL | fn render_HTML() {} - | ^^^^^^^^^^^ help: convert the identifier to snake case: `render_html` + | ^^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `render_html` error: trait method `ABC` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:22:8 | LL | fn ABC(); - | ^^^ help: convert the identifier to snake case: `abc` + | ^^^ help: convert the identifier to snake case (notice the capitalization): `abc` error: trait method `a_b_C` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:25:8 | LL | fn a_b_C(&self) {} - | ^^^^^ help: convert the identifier to snake case: `a_b_c` + | ^^^^^ help: convert the identifier to snake case (notice the capitalization): `a_b_c` error: trait method `something__else` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:28:8 @@ -50,13 +50,13 @@ error: function `Cookie` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:38:4 | LL | fn Cookie() {} - | ^^^^^^ help: convert the identifier to snake case: `cookie` + | ^^^^^^ help: convert the identifier to snake case (notice the capitalization): `cookie` error: function `bi_S_Cuit` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:41:8 | LL | pub fn bi_S_Cuit() {} - | ^^^^^^^^^ help: convert the identifier to snake case: `bi_s_cuit` + | ^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `bi_s_cuit` error: aborting due to 9 previous errors diff --git a/src/test/ui/lint/lint-non-uppercase-associated-const.stderr b/src/test/ui/lint/lint-non-uppercase-associated-const.stderr index 2185d5a0ab48..233048ee1ddb 100644 --- a/src/test/ui/lint/lint-non-uppercase-associated-const.stderr +++ b/src/test/ui/lint/lint-non-uppercase-associated-const.stderr @@ -2,7 +2,7 @@ error: associated constant `not_upper` should have an upper case name --> $DIR/lint-non-uppercase-associated-const.rs:7:11 | LL | const not_upper: bool = true; - | ^^^^^^^^^ help: convert the identifier to upper case: `NOT_UPPER` + | ^^^^^^^^^ help: convert the identifier to upper case (notice the capitalization): `NOT_UPPER` | note: lint level defined here --> $DIR/lint-non-uppercase-associated-const.rs:1:9 diff --git a/src/test/ui/lint/lint-non-uppercase-statics.stderr b/src/test/ui/lint/lint-non-uppercase-statics.stderr index 8b477276efc9..a03bdf52a0a6 100644 --- a/src/test/ui/lint/lint-non-uppercase-statics.stderr +++ b/src/test/ui/lint/lint-non-uppercase-statics.stderr @@ -2,7 +2,7 @@ error: static variable `foo` should have an upper case name --> $DIR/lint-non-uppercase-statics.rs:4:8 | LL | static foo: isize = 1; - | ^^^ help: convert the identifier to upper case: `FOO` + | ^^^ help: convert the identifier to upper case (notice the capitalization): `FOO` | note: lint level defined here --> $DIR/lint-non-uppercase-statics.rs:1:11 @@ -14,7 +14,7 @@ error: static variable `bar` should have an upper case name --> $DIR/lint-non-uppercase-statics.rs:6:12 | LL | static mut bar: isize = 1; - | ^^^ help: convert the identifier to upper case: `BAR` + | ^^^ help: convert the identifier to upper case (notice the capitalization): `BAR` error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr index 9ea3795f89e6..cc2be3d0bd9d 100644 --- a/src/test/ui/lint/lint-uppercase-variables.stderr +++ b/src/test/ui/lint/lint-uppercase-variables.stderr @@ -21,7 +21,7 @@ error: structure field `X` should have a snake case name --> $DIR/lint-uppercase-variables.rs:10:5 | LL | X: usize - | ^ help: convert the identifier to snake case: `x` + | ^ help: convert the identifier to snake case (notice the capitalization): `x` | note: lint level defined here --> $DIR/lint-uppercase-variables.rs:3:9 @@ -33,19 +33,19 @@ error: variable `Xx` should have a snake case name --> $DIR/lint-uppercase-variables.rs:13:9 | LL | fn test(Xx: usize) { - | ^^ help: convert the identifier to snake case: `xx` + | ^^ help: convert the identifier to snake case (notice the capitalization): `xx` error: variable `Test` should have a snake case name --> $DIR/lint-uppercase-variables.rs:18:9 | LL | let Test: usize = 0; - | ^^^^ help: convert the identifier to snake case: `test` + | ^^^^ help: convert the identifier to snake case (notice the capitalization): `test` error: variable `Foo` should have a snake case name --> $DIR/lint-uppercase-variables.rs:22:9 | LL | Foo => {} - | ^^^ help: convert the identifier to snake case: `foo` + | ^^^ help: convert the identifier to snake case (notice the capitalization): `foo` error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr index 70d49a4e69ca..8614e9f11733 100644 --- a/src/test/ui/lint/not_found.stderr +++ b/src/test/ui/lint/not_found.stderr @@ -10,11 +10,11 @@ warning: unknown lint: `DEAD_CODE` --> $DIR/not_found.rs:8:8 | LL | #[warn(DEAD_CODE)] - | ^^^^^^^^^ help: did you mean: `dead_code` + | ^^^^^^^^^ help: did you mean (notice the capitalization): `dead_code` warning: unknown lint: `Warnings` --> $DIR/not_found.rs:10:8 | LL | #[deny(Warnings)] - | ^^^^^^^^ help: did you mean: `warnings` + | ^^^^^^^^ help: did you mean (notice the capitalization): `warnings` diff --git a/src/test/ui/lint/reasons.stderr b/src/test/ui/lint/reasons.stderr index cb5f4ddf47b6..139b3f13fd6b 100644 --- a/src/test/ui/lint/reasons.stderr +++ b/src/test/ui/lint/reasons.stderr @@ -15,7 +15,7 @@ warning: variable `Social_exchange_psychology` should have a snake case name --> $DIR/reasons.rs:30:9 | LL | let Social_exchange_psychology = CheaterDetectionMechanism {}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case: `social_exchange_psychology` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `social_exchange_psychology` | = note: people shouldn't have to change their usual style habits to contribute to our project diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr index 678c88849b56..1da5acc96616 100644 --- a/src/test/ui/lint/use_suggestion_json.stderr +++ b/src/test/ui/lint/use_suggestion_json.stderr @@ -395,7 +395,7 @@ mod foo { \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m \u001b[0m\u001b[1m\u001b[38;5;12mLL\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0muse std::collections::hash_map::Iter;\u001b[0m \u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m -\u001b[0mand 8 other candidates\u001b[0m +\u001b[0m and 8 other candidates\u001b[0m " } diff --git a/src/test/ui/resolve/issue-21221-1.stderr b/src/test/ui/resolve/issue-21221-1.stderr index d00d87393aab..513e02f74e3b 100644 --- a/src/test/ui/resolve/issue-21221-1.stderr +++ b/src/test/ui/resolve/issue-21221-1.stderr @@ -27,7 +27,7 @@ LL | use mul3::Mul; | LL | use mul4::Mul; | -and 2 other candidates + and 2 other candidates error[E0405]: cannot find trait `ThisTraitReallyDoesntExistInAnyModuleReally` in this scope --> $DIR/issue-21221-1.rs:63:6 diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr index d9a28e63dce8..ad596c25551a 100644 --- a/src/test/ui/resolve/issue-39226.stderr +++ b/src/test/ui/resolve/issue-39226.stderr @@ -8,7 +8,7 @@ LL | handle: Handle | ^^^^^^ | | | did you mean `Handle { /* fields */ }`? - | help: a local variable with a similar name exists: `handle` + | help: a local variable with a similar name exists (notice the capitalization): `handle` error: aborting due to previous error diff --git a/src/test/ui/resolve/levenshtein.stderr b/src/test/ui/resolve/levenshtein.stderr index 2e3c0f5448e8..e693a0ef91fc 100644 --- a/src/test/ui/resolve/levenshtein.stderr +++ b/src/test/ui/resolve/levenshtein.stderr @@ -38,13 +38,13 @@ error[E0412]: cannot find type `first` in module `m` --> $DIR/levenshtein.rs:28:15 | LL | let b: m::first = m::second; // Misspelled item in module. - | ^^^^^ help: a struct with a similar name exists: `First` + | ^^^^^ help: a struct with a similar name exists (notice the capitalization): `First` error[E0425]: cannot find value `second` in module `m` --> $DIR/levenshtein.rs:28:26 | LL | let b: m::first = m::second; // Misspelled item in module. - | ^^^^^^ help: a unit struct with a similar name exists: `Second` + | ^^^^^^ help: a unit struct with a similar name exists (notice the capitalization): `Second` error: aborting due to 8 previous errors diff --git a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr index 030fa56dcff2..973c486970e6 100644 --- a/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr +++ b/src/test/ui/rust-2018/issue-52202-use-suggestions.stderr @@ -13,7 +13,7 @@ LL | use std::collections::hash_map::Drain; | LL | use std::collections::hash_set::Drain; | -and 3 other candidates + and 3 other candidates error: aborting due to previous error diff --git a/src/test/ui/test-attrs/inaccessible-test-modules.stderr b/src/test/ui/test-attrs/inaccessible-test-modules.stderr index a94ea1e79bc5..0b94619f689a 100644 --- a/src/test/ui/test-attrs/inaccessible-test-modules.stderr +++ b/src/test/ui/test-attrs/inaccessible-test-modules.stderr @@ -5,7 +5,7 @@ LL | use main as x; | ----^^^^^ | | | no `main` in the root - | help: a similar name exists in the module: `main` + | help: a similar name exists in the module (notice the capitalization): `main` error[E0432]: unresolved import `test` --> $DIR/inaccessible-test-modules.rs:6:5 @@ -14,7 +14,7 @@ LL | use test as y; | ----^^^^^ | | | no `test` in the root - | help: a similar name exists in the module: `test` + | help: a similar name exists in the module (notice the capitalization): `test` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-impl-for-module.stderr b/src/test/ui/traits/trait-impl-for-module.stderr index 4a06cd777d49..8b81192aa470 100644 --- a/src/test/ui/traits/trait-impl-for-module.stderr +++ b/src/test/ui/traits/trait-impl-for-module.stderr @@ -2,7 +2,7 @@ error[E0573]: expected type, found module `a` --> $DIR/trait-impl-for-module.rs:7:12 | LL | impl A for a { - | ^ help: a trait with a similar name exists: `A` + | ^ help: a trait with a similar name exists (notice the capitalization): `A` error: aborting due to previous error diff --git a/src/test/ui/utf8_idents.stderr b/src/test/ui/utf8_idents.stderr index 56de63da4f97..869bed61ea0f 100644 --- a/src/test/ui/utf8_idents.stderr +++ b/src/test/ui/utf8_idents.stderr @@ -38,7 +38,7 @@ warning: type parameter `γ` should have an upper camel case name --> $DIR/utf8_idents.rs:3:5 | LL | γ - | ^ help: convert the identifier to upper camel case: `Γ` + | ^ help: convert the identifier to upper camel case (notice the capitalization): `Γ` | = note: `#[warn(non_camel_case_types)]` on by default From f81b1548ddf886449d8ea95f82b56274b60fbac7 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 14 Oct 2019 10:34:21 +0200 Subject: [PATCH 357/545] Add troubleshooting section to PGO chapter in rustc book. --- src/doc/rustc/src/profile-guided-optimization.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/doc/rustc/src/profile-guided-optimization.md b/src/doc/rustc/src/profile-guided-optimization.md index 38be07a6440d..d066f4a9cf59 100644 --- a/src/doc/rustc/src/profile-guided-optimization.md +++ b/src/doc/rustc/src/profile-guided-optimization.md @@ -125,6 +125,17 @@ RUSTFLAGS="-Cprofile-use=/tmp/pgo-data/merged.profdata" \ cargo build --release --target=x86_64-unknown-linux-gnu ``` +### Troubleshooting + +- It is recommended to pass `-Cllvm-args=-pgo-warn-missing-function` during the + `-Cprofile-use` phase. LLVM by default does not warn if it cannot find + profiling data for a given function. Enabling this warning will make it + easier to spot errors in your setup. + +- There is a [known issue](https://github.com/rust-lang/cargo/issues/7416) in + Cargo prior to version 1.39 that will prevent PGO from working correctly. Be + sure to use Cargo 1.39 or newer when doing PGO. + ## Further Reading `rustc`'s PGO support relies entirely on LLVM's implementation of the feature From 307a3569c5025e72e3020a393689d10a6f5e2109 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 10 Oct 2019 10:29:03 +0200 Subject: [PATCH 358/545] Sort long error code explanation by error code --- src/librustc_mir/error_codes.rs | 406 ++++++++++++++++---------------- 1 file changed, 203 insertions(+), 203 deletions(-) diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index 77853ff1fe80..b2d7bc6a3066 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -208,6 +208,124 @@ match x { ``` "##, +E0010: r##" +The value of statics and constants must be known at compile time, and they live +for the entire lifetime of a program. Creating a boxed value allocates memory on +the heap at runtime, and therefore cannot be done at compile time. Erroneous +code example: + +```compile_fail,E0010 +#![feature(box_syntax)] + +const CON : Box = box 0; +``` +"##, + +E0013: r##" +Static and const variables can refer to other const variables. But a const +variable cannot refer to a static variable. For example, `Y` cannot refer to +`X` here: + +```compile_fail,E0013 +static X: i32 = 42; +const Y: i32 = X; +``` + +To fix this, the value can be extracted as a const and then used: + +``` +const A: i32 = 42; +static X: i32 = A; +const Y: i32 = A; +``` +"##, + +// FIXME(#57563) Change the language here when const fn stabilizes +E0015: r##" +The only functions that can be called in static or constant expressions are +`const` functions, and struct/enum constructors. `const` functions are only +available on a nightly compiler. Rust currently does not support more general +compile-time function execution. + +``` +const FOO: Option = Some(1); // enum constructor +struct Bar {x: u8} +const BAR: Bar = Bar {x: 1}; // struct constructor +``` + +See [RFC 911] for more details on the design of `const fn`s. + +[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md +"##, + +E0017: r##" +References in statics and constants may only refer to immutable values. +Erroneous code example: + +```compile_fail,E0017 +static X: i32 = 1; +const C: i32 = 2; + +// these three are not allowed: +const CR: &mut i32 = &mut C; +static STATIC_REF: &'static mut i32 = &mut X; +static CONST_REF: &'static mut i32 = &mut C; +``` + +Statics are shared everywhere, and if they refer to mutable data one might +violate memory safety since holding multiple mutable references to shared data +is not allowed. + +If you really want global mutable state, try using `static mut` or a global +`UnsafeCell`. +"##, + +E0019: r##" +A function call isn't allowed in the const's initialization expression +because the expression's value must be known at compile-time. Erroneous code +example: + +```compile_fail +enum Test { + V1 +} + +impl Test { + fn test(&self) -> i32 { + 12 + } +} + +fn main() { + const FOO: Test = Test::V1; + + const A: i32 = FOO.test(); // You can't call Test::func() here! +} +``` + +Remember: you can't use a function call inside a const's initialization +expression! However, you can totally use it anywhere else: + +``` +enum Test { + V1 +} + +impl Test { + fn func(&self) -> i32 { + 12 + } +} + +fn main() { + const FOO: Test = Test::V1; + + FOO.func(); // here is good + let x = FOO.func(); // or even here! +} +``` +"##, + E0030: r##" When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to @@ -226,6 +344,40 @@ match 5u32 { ``` "##, +E0133: r##" +Unsafe code was used outside of an unsafe function or block. + +Erroneous code example: + +```compile_fail,E0133 +unsafe fn f() { return; } // This is the unsafe code + +fn main() { + f(); // error: call to unsafe function requires unsafe function or block +} +``` + +Using unsafe functionality is potentially dangerous and disallowed by safety +checks. Examples: + +* Dereferencing raw pointers +* Calling functions via FFI +* Calling functions marked unsafe + +These safety checks can be relaxed for a section of the code by wrapping the +unsafe instructions with an `unsafe` block. For instance: + +``` +unsafe fn f() { return; } + +fn main() { + unsafe { f(); } // ok! +} +``` + +See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html +"##, + E0158: r##" `const` and `static` mean different things. A `const` is a compile-time constant, an alias for a literal value. This property means you can match it @@ -247,6 +399,39 @@ match Some(42) { ``` "##, +E0161: r##" +A value was moved. However, its size was not known at compile time, and only +values of a known size can be moved. + +Erroneous code example: + +```compile_fail +#![feature(box_syntax)] + +fn main() { + let array: &[isize] = &[1, 2, 3]; + let _x: Box<[isize]> = box *array; + // error: cannot move a value of type [isize]: the size of [isize] cannot + // be statically determined +} +``` + +In Rust, you can only move a value when its size is known at compile time. + +To work around this restriction, consider "hiding" the value behind a reference: +either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move +it around as usual. Example: + +``` +#![feature(box_syntax)] + +fn main() { + let array: &[isize] = &[1, 2, 3]; + let _x: Box<&[isize]> = box array; // ok! +} +``` +"##, + E0162: r##" #### Note: this error code is no longer emitted by the compiler. @@ -468,158 +653,6 @@ The `op_string_ref` binding has type `&Option<&String>` in both cases. See also https://github.com/rust-lang/rust/issues/14587 "##, -E0010: r##" -The value of statics and constants must be known at compile time, and they live -for the entire lifetime of a program. Creating a boxed value allocates memory on -the heap at runtime, and therefore cannot be done at compile time. Erroneous -code example: - -```compile_fail,E0010 -#![feature(box_syntax)] - -const CON : Box = box 0; -``` -"##, - -E0013: r##" -Static and const variables can refer to other const variables. But a const -variable cannot refer to a static variable. For example, `Y` cannot refer to -`X` here: - -```compile_fail,E0013 -static X: i32 = 42; -const Y: i32 = X; -``` - -To fix this, the value can be extracted as a const and then used: - -``` -const A: i32 = 42; -static X: i32 = A; -const Y: i32 = A; -``` -"##, - -// FIXME(#57563) Change the language here when const fn stabilizes -E0015: r##" -The only functions that can be called in static or constant expressions are -`const` functions, and struct/enum constructors. `const` functions are only -available on a nightly compiler. Rust currently does not support more general -compile-time function execution. - -``` -const FOO: Option = Some(1); // enum constructor -struct Bar {x: u8} -const BAR: Bar = Bar {x: 1}; // struct constructor -``` - -See [RFC 911] for more details on the design of `const fn`s. - -[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md -"##, - -E0017: r##" -References in statics and constants may only refer to immutable values. -Erroneous code example: - -```compile_fail,E0017 -static X: i32 = 1; -const C: i32 = 2; - -// these three are not allowed: -const CR: &mut i32 = &mut C; -static STATIC_REF: &'static mut i32 = &mut X; -static CONST_REF: &'static mut i32 = &mut C; -``` - -Statics are shared everywhere, and if they refer to mutable data one might -violate memory safety since holding multiple mutable references to shared data -is not allowed. - -If you really want global mutable state, try using `static mut` or a global -`UnsafeCell`. -"##, - -E0019: r##" -A function call isn't allowed in the const's initialization expression -because the expression's value must be known at compile-time. Erroneous code -example: - -```compile_fail -enum Test { - V1 -} - -impl Test { - fn test(&self) -> i32 { - 12 - } -} - -fn main() { - const FOO: Test = Test::V1; - - const A: i32 = FOO.test(); // You can't call Test::func() here! -} -``` - -Remember: you can't use a function call inside a const's initialization -expression! However, you can totally use it anywhere else: - -``` -enum Test { - V1 -} - -impl Test { - fn func(&self) -> i32 { - 12 - } -} - -fn main() { - const FOO: Test = Test::V1; - - FOO.func(); // here is good - let x = FOO.func(); // or even here! -} -``` -"##, - -E0133: r##" -Unsafe code was used outside of an unsafe function or block. - -Erroneous code example: - -```compile_fail,E0133 -unsafe fn f() { return; } // This is the unsafe code - -fn main() { - f(); // error: call to unsafe function requires unsafe function or block -} -``` - -Using unsafe functionality is potentially dangerous and disallowed by safety -checks. Examples: - -* Dereferencing raw pointers -* Calling functions via FFI -* Calling functions marked unsafe - -These safety checks can be relaxed for a section of the code by wrapping the -unsafe instructions with an `unsafe` block. For instance: - -``` -unsafe fn f() { return; } - -fn main() { - unsafe { f(); } // ok! -} -``` - -See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html -"##, - E0373: r##" This error occurs when an attempt is made to use data captured by a closure, when that data may no longer exist. It's most commonly seen when attempting to @@ -1022,39 +1055,6 @@ fn main() { ``` "##, -E0161: r##" -A value was moved. However, its size was not known at compile time, and only -values of a known size can be moved. - -Erroneous code example: - -```compile_fail -#![feature(box_syntax)] - -fn main() { - let array: &[isize] = &[1, 2, 3]; - let _x: Box<[isize]> = box *array; - // error: cannot move a value of type [isize]: the size of [isize] cannot - // be statically determined -} -``` - -In Rust, you can only move a value when its size is known at compile time. - -To work around this restriction, consider "hiding" the value behind a reference: -either `&x` or `&mut x`. Since a reference has a fixed size, this lets you move -it around as usual. Example: - -``` -#![feature(box_syntax)] - -fn main() { - let array: &[isize] = &[1, 2, 3]; - let _x: Box<&[isize]> = box array; // ok! -} -``` -"##, - E0492: r##" A borrow of a constant containing interior mutability was attempted. Erroneous code example: @@ -1982,24 +1982,6 @@ Here executing `x = None` would modify the value being matched and require us to go "back in time" to the `None` arm. "##, -E0579: r##" -When matching against an exclusive range, the compiler verifies that the range -is non-empty. Exclusive range patterns include the start point but not the end -point, so this is equivalent to requiring the start of the range to be less -than the end of the range. - -For example: - -```compile_fail -match 5u32 { - // This range is ok, albeit pointless. - 1 .. 2 => {} - // This range is empty, and the compiler can tell. - 5 .. 5 => {} -} -``` -"##, - E0515: r##" Cannot return value that references local variable @@ -2101,6 +2083,24 @@ fn dragoooon(x: &mut isize) { ``` "##, +E0579: r##" +When matching against an exclusive range, the compiler verifies that the range +is non-empty. Exclusive range patterns include the start point but not the end +point, so this is equivalent to requiring the start of the range to be less +than the end of the range. + +For example: + +```compile_fail +match 5u32 { + // This range is ok, albeit pointless. + 1 .. 2 => {} + // This range is empty, and the compiler can tell. + 5 .. 5 => {} +} +``` +"##, + E0595: r##" #### Note: this error code is no longer emitted by the compiler. From c6de3ebd69acc627d3a8560587e5475f2240ce8a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 10 Oct 2019 10:33:46 +0200 Subject: [PATCH 359/545] Uncomment E0386 to let users have access to its old definition --- src/librustc_mir/error_codes.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index b2d7bc6a3066..93fd00c265be 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -875,7 +875,8 @@ x = Foo { a: 2 }; E0384: r##" This error occurs when an attempt is made to reassign an immutable variable. -For example: + +Erroneous code example: ```compile_fail,E0384 fn main() { @@ -895,13 +896,15 @@ fn main() { ``` "##, -/*E0386: r##" +E0386: r##" +#### Note: this error code is no longer emitted by the compiler. + This error occurs when an attempt is made to mutate the target of a mutable reference stored inside an immutable container. For example, this can happen when storing a `&mut` inside an immutable `Box`: -```compile_fail,E0386 +``` let mut x: i64 = 1; let y: Box<_> = Box::new(&mut x); **y = 2; // error, cannot assign to data in an immutable container @@ -925,7 +928,7 @@ let x: i64 = 1; let y: Box> = Box::new(Cell::new(x)); y.set(2); ``` -"##,*/ +"##, E0387: r##" #### Note: this error code is no longer emitted by the compiler. From 65458190c55b06cc8301e6c16b06679677af3945 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 10 Oct 2019 10:53:08 +0200 Subject: [PATCH 360/545] Unification and cleanup of librustc_mir error codes --- src/librustc_mir/error_codes.rs | 142 +++++++++++++++++++++----------- 1 file changed, 92 insertions(+), 50 deletions(-) diff --git a/src/librustc_mir/error_codes.rs b/src/librustc_mir/error_codes.rs index 93fd00c265be..419c905cb512 100644 --- a/src/librustc_mir/error_codes.rs +++ b/src/librustc_mir/error_codes.rs @@ -64,7 +64,9 @@ E0004: r##" This error indicates that the compiler cannot guarantee a matching pattern for one or more possible inputs to a match expression. Guaranteed matches are required in order to assign values to match expressions, or alternatively, -determine the flow of execution. Erroneous code example: +determine the flow of execution. + +Erroneous code example: ```compile_fail,E0004 enum Terminator { @@ -109,7 +111,9 @@ match x { E0005: r##" Patterns used to bind names must be irrefutable, that is, they must guarantee -that a name will be extracted in all cases. Erroneous code example: +that a name will be extracted in all cases. + +Erroneous code example: ```compile_fail,E0005 let x = Some(1); @@ -145,6 +149,8 @@ like the following is invalid as it requires the entire `Option` to be moved into a variable called `op_string` while simultaneously requiring the inner `String` to be moved into a variable called `s`. +Erroneous code example: + ```compile_fail,E0007 let x = Some("s".to_string()); @@ -211,8 +217,9 @@ match x { E0010: r##" The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on -the heap at runtime, and therefore cannot be done at compile time. Erroneous -code example: +the heap at runtime, and therefore cannot be done at compile time. + +Erroneous code example: ```compile_fail,E0010 #![feature(box_syntax)] @@ -223,15 +230,17 @@ const CON : Box = box 0; E0013: r##" Static and const variables can refer to other const variables. But a const -variable cannot refer to a static variable. For example, `Y` cannot refer to -`X` here: +variable cannot refer to a static variable. + +Erroneous code example: ```compile_fail,E0013 static X: i32 = 42; const Y: i32 = X; ``` -To fix this, the value can be extracted as a const and then used: +In this example, `Y` cannot refer to `X` here. To fix this, the value can be +extracted as a const and then used: ``` const A: i32 = 42; @@ -260,6 +269,7 @@ See [RFC 911] for more details on the design of `const fn`s. E0017: r##" References in statics and constants may only refer to immutable values. + Erroneous code example: ```compile_fail,E0017 @@ -282,24 +292,17 @@ If you really want global mutable state, try using `static mut` or a global E0019: r##" A function call isn't allowed in the const's initialization expression -because the expression's value must be known at compile-time. Erroneous code -example: +because the expression's value must be known at compile-time. -```compile_fail -enum Test { - V1 -} +Erroneous code example: -impl Test { - fn test(&self) -> i32 { - 12 - } -} +```compile_fail,E0019 +#![feature(box_syntax)] fn main() { - const FOO: Test = Test::V1; + struct MyOwned; - const A: i32 = FOO.test(); // You can't call Test::func() here! + static STATIC11: Box = box MyOwned; // error! } ``` @@ -328,13 +331,13 @@ fn main() { E0030: r##" When matching against a range, the compiler verifies that the range is -non-empty. Range patterns include both end-points, so this is equivalent to +non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range. -For example: +Erroneous code example: -```compile_fail +```compile_fail,E0030 match 5u32 { // This range is ok, albeit pointless. 1 ..= 1 => {} @@ -379,6 +382,26 @@ See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html "##, E0158: r##" +An associated const has been referenced in a pattern. + +Erroneous code example: + +```compile_fail,E0158 +enum EFoo { A, B, C, D } + +trait Foo { + const X: EFoo; +} + +fn test(arg: EFoo) { + match arg { + A::X => { // error! + println!("A::X"); + } + } +} +``` + `const` and `static` mean different things. A `const` is a compile-time constant, an alias for a literal value. This property means you can match it directly within a pattern. @@ -405,7 +428,7 @@ values of a known size can be moved. Erroneous code example: -```compile_fail +```compile_fail,E0161 #![feature(box_syntax)] fn main() { @@ -705,7 +728,9 @@ about safety. "##, E0381: r##" -It is not allowed to use or capture an uninitialized variable. For example: +It is not allowed to use or capture an uninitialized variable. + +Erroneous code example: ```compile_fail,E0381 fn main() { @@ -727,7 +752,9 @@ fn main() { E0382: r##" This error occurs when an attempt is made to use a variable after its contents -have been moved elsewhere. For example: +have been moved elsewhere. + +Erroneous code example: ```compile_fail,E0382 struct MyStruct { s: u32 } @@ -934,7 +961,9 @@ E0387: r##" #### Note: this error code is no longer emitted by the compiler. This error occurs when an attempt is made to mutate or mutably reference data -that a closure has captured immutably. Examples of this error are shown below: +that a closure has captured immutably. + +Erroneous code example: ```compile_fail // Accepts a function or a closure that captures its environment immutably. @@ -999,7 +1028,7 @@ An attempt was made to mutate data using a non-mutable reference. This commonly occurs when attempting to assign to a non-mutable reference of a mutable reference (`&(&mut T)`). -Example of erroneous code: +Erroneous code example: ```compile_fail struct FancyNum { @@ -1059,8 +1088,9 @@ fn main() { "##, E0492: r##" -A borrow of a constant containing interior mutability was attempted. Erroneous -code example: +A borrow of a constant containing interior mutability was attempted. + +Erroneous code example: ```compile_fail,E0492 use std::sync::atomic::AtomicUsize; @@ -1177,7 +1207,9 @@ static FOO: Foo = Foo { field1: DropType::A }; // We initialize all fields "##, E0499: r##" -A variable was borrowed as mutable more than once. Erroneous code example: +A variable was borrowed as mutable more than once. + +Erroneous code example: ```compile_fail,E0499 let mut i = 0; @@ -1208,7 +1240,9 @@ a; "##, E0500: r##" -A borrowed variable was used by a closure. Example of erroneous code: +A borrowed variable was used by a closure. + +Erroneous code example: ```compile_fail,E0500 fn you_know_nothing(jon_snow: &mut i32) { @@ -1259,7 +1293,7 @@ situation, the closure is borrowing the variable. Take a look at http://rustbyexample.com/fn/closures/capture.html for more information about capturing. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0501 fn inside_closure(x: &mut i32) { @@ -1332,7 +1366,7 @@ E0502: r##" This error indicates that you are trying to borrow a variable as mutable when it has already been borrowed as immutable. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0502 fn bar(x: &mut i32) {} @@ -1363,7 +1397,7 @@ https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html. E0503: r##" A value was used after it was mutably borrowed. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0503 fn main() { @@ -1421,7 +1455,7 @@ E0504: r##" This error occurs when an attempt is made to move a borrowed variable into a closure. -Example of erroneous code: +Erroneous code example: ```compile_fail struct FancyNum { @@ -1612,7 +1646,7 @@ http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html E0506: r##" This error occurs when an attempt is made to assign to a borrowed value. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0506 struct FancyNum { @@ -1830,7 +1864,7 @@ http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html E0508: r##" A value was moved out of a non-copy fixed-size array. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0508 struct NonCopy; @@ -1875,7 +1909,7 @@ E0509: r##" This error occurs when an attempt is made to move out of a value whose type implements the `Drop` trait. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0509 struct FancyNum { @@ -1991,6 +2025,8 @@ Cannot return value that references local variable Local variables, function parameters and temporaries are all dropped before the end of the function body. So a reference to them cannot be returned. +Erroneous code example: + ```compile_fail,E0515 fn get_dangling_reference() -> &'static i32 { let x = 0; @@ -2092,14 +2128,18 @@ is non-empty. Exclusive range patterns include the start point but not the end point, so this is equivalent to requiring the start of the range to be less than the end of the range. -For example: +Erroneous code example: -```compile_fail -match 5u32 { - // This range is ok, albeit pointless. - 1 .. 2 => {} - // This range is empty, and the compiler can tell. - 5 .. 5 => {} +```compile_fail,E0579 +#![feature(exclusive_range_pattern)] + +fn main() { + match 5u32 { + // This range is ok, albeit pointless. + 1 .. 2 => {} + // This range is empty, and the compiler can tell. + 5 .. 5 => {} // error! + } } ``` "##, @@ -2127,7 +2167,7 @@ let mut c = || { x += 1 }; E0596: r##" This error occurs because you tried to mutably borrow a non-mutable variable. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0596 let x = 1; @@ -2146,7 +2186,7 @@ let y = &mut x; // ok! E0597: r##" This error occurs because a value was dropped while it was still borrowed -Example of erroneous code: +Erroneous code example: ```compile_fail,E0597 struct Foo<'a> { @@ -2183,6 +2223,8 @@ E0626: r##" This error occurs because a borrow in a generator persists across a yield point. +Erroneous code example: + ```compile_fail,E0626 # #![feature(generators, generator_trait, pin)] # use std::ops::Generator; @@ -2274,7 +2316,7 @@ E0712: r##" This error occurs because a borrow of a thread-local variable was made inside a function which outlived the lifetime of the function. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0712 #![feature(thread_local)] @@ -2296,7 +2338,7 @@ E0713: r##" This error occurs when an attempt is made to borrow state past the end of the lifetime of a type that implements the `Drop` trait. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0713 #![feature(nll)] From d4e3e6bc15ece1c017ec7bd1fd892c6a981b2020 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 14 Oct 2019 13:01:12 +0200 Subject: [PATCH 361/545] Delete extra file --- .../feature-gate-exhaustive-patterns.nll.stderr | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr deleted file mode 100644 index d77fbc1e8239..000000000000 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/feature-gate-exhaustive-patterns.rs:7:9 - | -LL | let Ok(_x) = foo(); - | ^^^^^^ pattern `Err(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Ok(_x) = foo() { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0005`. From e8c28e24b99f9da9bf797848902ab7763da54c5b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 6 Oct 2019 14:30:46 +0300 Subject: [PATCH 362/545] rustc_metadata: Privatize private code and remove dead code --- src/librustc_driver/lib.rs | 2 +- src/librustc_interface/passes.rs | 15 +- src/librustc_metadata/creader.rs | 11 +- src/librustc_metadata/cstore.rs | 74 +++++----- src/librustc_metadata/cstore_impl.rs | 21 +-- src/librustc_metadata/decoder.rs | 144 ++++++++++---------- src/librustc_metadata/dependency_format.rs | 2 +- src/librustc_metadata/dynamic_lib.rs | 61 ++------- src/librustc_metadata/encoder.rs | 19 +-- src/librustc_metadata/foreign_modules.rs | 2 +- src/librustc_metadata/index.rs | 14 +- src/librustc_metadata/link_args.rs | 2 +- src/librustc_metadata/locator.rs | 19 +-- src/librustc_metadata/native_libs.rs | 4 +- src/librustc_metadata/schema.rs | 62 ++++----- src/librustc_resolve/build_reduced_graph.rs | 5 +- src/librustc_resolve/lib.rs | 2 +- 17 files changed, 202 insertions(+), 257 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 806afbd1af68..f33cb4e215d3 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -616,7 +616,7 @@ impl RustcDefaultCalls { let mut v = Vec::new(); locator::list_file_metadata(&sess.target.target, path, - &*cstore.metadata_loader, + cstore, &mut v) .unwrap(); println!("{}", String::from_utf8(v).unwrap()); diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 328798862b86..309cf8e255be 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -663,16 +663,15 @@ fn write_out_deps(compiler: &Compiler, outputs: &OutputFilenames, out_filenames: if sess.binary_dep_depinfo() { for cnum in compiler.cstore.crates_untracked() { - let metadata = compiler.cstore.crate_data_as_rc_any(cnum); - let metadata = metadata.downcast_ref::().unwrap(); - if let Some((path, _)) = &metadata.source.dylib { - files.push(escape_dep_filename(&FileName::Real(path.clone()))); + let source = compiler.cstore.crate_source_untracked(cnum); + if let Some((path, _)) = source.dylib { + files.push(escape_dep_filename(&FileName::Real(path))); } - if let Some((path, _)) = &metadata.source.rlib { - files.push(escape_dep_filename(&FileName::Real(path.clone()))); + if let Some((path, _)) = source.rlib { + files.push(escape_dep_filename(&FileName::Real(path))); } - if let Some((path, _)) = &metadata.source.rmeta { - files.push(escape_dep_filename(&FileName::Real(path.clone()))); + if let Some((path, _)) = source.rmeta { + files.push(escape_dep_filename(&FileName::Real(path))); } } } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 50a2187c9374..956df7828440 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -1,6 +1,6 @@ //! Validates all used crates and extern libraries and loads their metadata -use crate::cstore::{self, CStore, CrateSource, MetadataBlob}; +use crate::cstore::{self, CStore, MetadataBlob}; use crate::locator::{self, CratePaths}; use crate::schema::{CrateRoot, CrateDep}; use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell}; @@ -14,7 +14,7 @@ use rustc::session::{Session, CrateDisambiguator}; use rustc::session::config::{Sanitizer, self}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc::session::search_paths::PathKind; -use rustc::middle::cstore::{ExternCrate, ExternCrateSource}; +use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource}; use rustc::util::common::record_time; use rustc::util::nodemap::FxHashSet; use rustc::hir::map::Definitions; @@ -33,7 +33,7 @@ use syntax_pos::{Span, DUMMY_SP}; use log::{debug, info, log_enabled}; use proc_macro::bridge::client::ProcMacro; -pub struct Library { +crate struct Library { pub dylib: Option<(PathBuf, PathKind)>, pub rlib: Option<(PathBuf, PathKind)>, pub rmeta: Option<(PathBuf, PathKind)>, @@ -41,7 +41,7 @@ pub struct Library { } pub struct CrateLoader<'a> { - pub sess: &'a Session, + sess: &'a Session, cstore: &'a CStore, local_crate_name: Symbol, } @@ -268,13 +268,12 @@ impl<'a> CrateLoader<'a> { source_map_import_info: RwLock::new(vec![]), alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index), dep_kind: Lock::new(dep_kind), - source: cstore::CrateSource { + source: CrateSource { dylib, rlib, rmeta, }, private_dep, - span, raw_proc_macros, dep_node_index: AtomicCell::new(DepNodeIndex::INVALID), }; diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 98a08e501f14..a9fa210b53c5 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -5,19 +5,15 @@ use crate::schema; use rustc::dep_graph::DepNodeIndex; use rustc::hir::def_id::{CrateNum, DefIndex}; use rustc::hir::map::definitions::DefPathTable; -use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader}; +use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate, MetadataLoader}; use rustc::mir::interpret::AllocDecodingState; use rustc_index::vec::IndexVec; use rustc::util::nodemap::{FxHashMap, NodeMap}; - -use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell}; +use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell}; use syntax::ast; use syntax::ext::base::SyntaxExtension; use syntax_pos; - -pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference}; -pub use rustc::middle::cstore::NativeLibraryKind::*; -pub use rustc::middle::cstore::{CrateSource, LibSource, ForeignModule}; +use proc_macro::bridge::client::ProcMacro; pub use crate::cstore_impl::{provide, provide_extern}; @@ -25,17 +21,13 @@ pub use crate::cstore_impl::{provide, provide_extern}; // local crate numbers (as generated during this session). Each external // crate may refer to types in other external crates, and each has their // own crate numbers. -pub type CrateNumMap = IndexVec; +crate type CrateNumMap = IndexVec; -pub use rustc_data_structures::sync::MetadataRef; -use syntax_pos::Span; -use proc_macro::bridge::client::ProcMacro; - -pub struct MetadataBlob(pub MetadataRef); +crate struct MetadataBlob(pub MetadataRef); /// Holds information about a syntax_pos::SourceFile imported from another crate. /// See `imported_source_files()` for more information. -pub struct ImportedSourceFile { +crate struct ImportedSourceFile { /// This SourceFile's byte-offset within the source_map of its original crate pub original_start_pos: syntax_pos::BytePos, /// The end of this SourceFile within the source_map of its original crate @@ -48,56 +40,54 @@ pub struct CrateMetadata { /// Information about the extern crate that caused this crate to /// be loaded. If this is `None`, then the crate was injected /// (e.g., by the allocator) - pub extern_crate: Lock>, + crate extern_crate: Lock>, - pub blob: MetadataBlob, - pub cnum_map: CrateNumMap, - pub cnum: CrateNum, - pub dependencies: Lock>, - pub source_map_import_info: RwLock>, + crate blob: MetadataBlob, + crate cnum_map: CrateNumMap, + crate cnum: CrateNum, + crate dependencies: Lock>, + crate source_map_import_info: RwLock>, /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. - pub alloc_decoding_state: AllocDecodingState, + crate alloc_decoding_state: AllocDecodingState, // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this // lifetime is only used behind `Lazy`, and therefore acts like an // universal (`for<'tcx>`), that is paired up with whichever `TyCtxt` // is being used to decode those values. - pub root: schema::CrateRoot<'static>, + crate root: schema::CrateRoot<'static>, /// For each definition in this crate, we encode a key. When the /// crate is loaded, we read all the keys and put them in this /// hashmap, which gives the reverse mapping. This allows us to /// quickly retrace a `DefPath`, which is needed for incremental /// compilation support. - pub def_path_table: Lrc, + crate def_path_table: Lrc, - pub trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>, + crate trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>, - pub dep_kind: Lock, - pub source: CrateSource, + crate dep_kind: Lock, + crate source: CrateSource, /// Whether or not this crate should be consider a private dependency /// for purposes of the 'exported_private_dependencies' lint - pub private_dep: bool, + crate private_dep: bool, - pub span: Span, - - pub raw_proc_macros: Option<&'static [ProcMacro]>, + crate raw_proc_macros: Option<&'static [ProcMacro]>, /// The `DepNodeIndex` of the `DepNode` representing this upstream crate. /// It is initialized on the first access in `get_crate_dep_node_index()`. /// Do not access the value directly, as it might not have been initialized /// yet. /// The field must always be initialized to `DepNodeIndex::INVALID`. - pub(super) dep_node_index: AtomicCell, + crate dep_node_index: AtomicCell, } pub struct CStore { metas: RwLock>>>, /// Map from NodeId's of local extern crate statements to crate numbers extern_mod_crate_map: Lock>, - pub metadata_loader: Box, + crate metadata_loader: Box, } pub enum LoadedMacro { @@ -118,25 +108,25 @@ impl CStore { } } - pub(super) fn alloc_new_crate_num(&self) -> CrateNum { + crate fn alloc_new_crate_num(&self) -> CrateNum { let mut metas = self.metas.borrow_mut(); let cnum = CrateNum::new(metas.len()); metas.push(None); cnum } - pub(super) fn get_crate_data(&self, cnum: CrateNum) -> Lrc { + crate fn get_crate_data(&self, cnum: CrateNum) -> Lrc { self.metas.borrow()[cnum].clone() .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum)) } - pub(super) fn set_crate_data(&self, cnum: CrateNum, data: Lrc) { + crate fn set_crate_data(&self, cnum: CrateNum, data: Lrc) { let mut metas = self.metas.borrow_mut(); assert!(metas[cnum].is_none(), "Overwriting crate metadata entry"); metas[cnum] = Some(data); } - pub(super) fn iter_crate_data(&self, mut i: I) + crate fn iter_crate_data(&self, mut i: I) where I: FnMut(CrateNum, &Lrc) { for (k, v) in self.metas.borrow().iter_enumerated() { @@ -146,16 +136,14 @@ impl CStore { } } - pub(super) fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec { + crate fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec { let mut ordering = Vec::new(); self.push_dependencies_in_postorder(&mut ordering, krate); ordering.reverse(); ordering } - pub(super) fn push_dependencies_in_postorder(&self, - ordering: &mut Vec, - krate: CrateNum) { + crate fn push_dependencies_in_postorder(&self, ordering: &mut Vec, krate: CrateNum) { if ordering.contains(&krate) { return; } @@ -170,7 +158,7 @@ impl CStore { ordering.push(krate); } - pub(super) fn do_postorder_cnums_untracked(&self) -> Vec { + crate fn do_postorder_cnums_untracked(&self) -> Vec { let mut ordering = Vec::new(); for (num, v) in self.metas.borrow().iter_enumerated() { if let &Some(_) = v { @@ -180,11 +168,11 @@ impl CStore { return ordering } - pub(super) fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) { + crate fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) { self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum); } - pub(super) fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { + crate fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { self.extern_mod_crate_map.borrow().get(&emod_id).cloned() } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 642a7632b3df..21ed22f61f17 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -6,8 +6,7 @@ use crate::foreign_modules; use crate::schema; use rustc::ty::query::QueryConfig; -use rustc::middle::cstore::{CrateStore, DepKind, - EncodedMetadata, NativeLibraryKind}; +use rustc::middle::cstore::{CrateSource, CrateStore, DepKind, EncodedMetadata, NativeLibraryKind}; use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; use rustc::middle::dependency_format::Linkage; @@ -414,12 +413,6 @@ impl cstore::CStore { } } - pub fn dep_kind_untracked(&self, cnum: CrateNum) -> DepKind { - let data = self.get_crate_data(cnum); - let r = *data.dep_kind.lock(); - r - } - pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { self.get_crate_data(cnum).root.edition } @@ -428,14 +421,6 @@ impl cstore::CStore { self.get_crate_data(def.krate).get_struct_field_names(def.index, sess) } - pub fn ctor_kind_untracked(&self, def: DefId) -> def::CtorKind { - self.get_crate_data(def.krate).get_ctor_kind(def.index) - } - - pub fn item_attrs_untracked(&self, def: DefId, sess: &Session) -> Lrc<[ast::Attribute]> { - self.get_crate_data(def.krate).get_item_attrs(def.index, sess) - } - pub fn item_children_untracked( &self, def_id: DefId, @@ -493,6 +478,10 @@ impl cstore::CStore { pub fn associated_item_cloned_untracked(&self, def: DefId) -> ty::AssocItem { self.get_crate_data(def.krate).get_associated_item(def.index) } + + pub fn crate_source_untracked(&self, cnum: CrateNum) -> CrateSource { + self.get_crate_data(cnum).source.clone() + } } impl CrateStore for cstore::CStore { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 132ef7d42413..6969d608d76d 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1,13 +1,13 @@ // Decoding metadata from a single crate's metadata -use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; +use crate::cstore::{self, CrateMetadata, MetadataBlob}; use crate::schema::*; use rustc_index::vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir; -use rustc::middle::cstore::LinkagePreference; +use rustc::middle::cstore::{LinkagePreference, NativeLibrary, ForeignModule}; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -38,7 +38,7 @@ use log::debug; use proc_macro::bridge::client::ProcMacro; use syntax::ext::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; -pub struct DecodeContext<'a, 'tcx> { +crate struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, cdata: Option<&'a CrateMetadata>, sess: Option<&'tcx Session>, @@ -54,7 +54,7 @@ pub struct DecodeContext<'a, 'tcx> { } /// Abstract over the various ways one can create metadata decoders. -pub trait Metadata<'a, 'tcx>: Copy { +crate trait Metadata<'a, 'tcx>: Copy { fn raw_bytes(self) -> &'a [u8]; fn cdata(self) -> Option<&'a CrateMetadata> { None } fn sess(self) -> Option<&'tcx Session> { None } @@ -130,7 +130,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) { } impl<'a, 'tcx, T: Decodable> Lazy { - pub fn decode>(self, meta: M) -> T { + crate fn decode>(self, meta: M) -> T { let mut dcx = meta.decoder(self.position); dcx.lazy_state = LazyState::NodeStart(self.position); T::decode(&mut dcx).unwrap() @@ -138,7 +138,7 @@ impl<'a, 'tcx, T: Decodable> Lazy { } impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { - pub fn decode>( + crate fn decode>( self, meta: M, ) -> impl ExactSizeIterator + Captures<'a> + Captures<'tcx> + 'x { @@ -149,11 +149,11 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { } impl<'a, 'tcx> DecodeContext<'a, 'tcx> { - pub fn tcx(&self) -> TyCtxt<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { self.tcx.expect("missing TyCtxt in DecodeContext") } - pub fn cdata(&self) -> &'a CrateMetadata { + fn cdata(&self) -> &'a CrateMetadata { self.cdata.expect("missing CrateMetadata in DecodeContext") } @@ -379,15 +379,15 @@ for DecodeContext<'a, 'tcx> { implement_ty_decoder!( DecodeContext<'a, 'tcx> ); impl<'tcx> MetadataBlob { - pub fn is_compatible(&self) -> bool { + crate fn is_compatible(&self) -> bool { self.raw_bytes().starts_with(METADATA_HEADER) } - pub fn get_rustc_version(&self) -> String { + crate fn get_rustc_version(&self) -> String { Lazy::::from_position(METADATA_HEADER.len() + 4).decode(self) } - pub fn get_root(&self) -> CrateRoot<'tcx> { + crate fn get_root(&self) -> CrateRoot<'tcx> { let slice = self.raw_bytes(); let offset = METADATA_HEADER.len(); let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | @@ -396,7 +396,7 @@ impl<'tcx> MetadataBlob { Lazy::>::from_position(pos).decode(self) } - pub fn list_crate_metadata(&self, + crate fn list_crate_metadata(&self, out: &mut dyn io::Write) -> io::Result<()> { write!(out, "=External Dependencies=\n")?; let root = self.get_root(); @@ -449,7 +449,7 @@ impl<'tcx> EntryKind<'tcx> { } impl<'a, 'tcx> CrateMetadata { - pub fn is_proc_macro_crate(&self) -> bool { + crate fn is_proc_macro_crate(&self) -> bool { self.root.proc_macro_decls_static.is_some() } @@ -499,7 +499,7 @@ impl<'a, 'tcx> CrateMetadata { &self.raw_proc_macros.unwrap()[pos] } - pub fn item_name(&self, item_index: DefIndex) -> Symbol { + crate fn item_name(&self, item_index: DefIndex) -> Symbol { if !self.is_proc_macro(item_index) { self.def_key(item_index) .disambiguated_data @@ -512,7 +512,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn def_kind(&self, index: DefIndex) -> Option { + crate fn def_kind(&self, index: DefIndex) -> Option { if !self.is_proc_macro(index) { self.entry(index).kind.def_kind() } else { @@ -522,7 +522,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span { + crate fn get_span(&self, index: DefIndex, sess: &Session) -> Span { self.entry(index).span.decode((self, sess)) } @@ -556,7 +556,7 @@ impl<'a, 'tcx> CrateMetadata { ) } - pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { + crate fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { match self.entry(item_id).kind { EntryKind::Trait(data) => { let data = data.decode((self, sess)); @@ -622,7 +622,7 @@ impl<'a, 'tcx> CrateMetadata { ) } - pub fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef { + crate fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef { let item = self.entry(item_id); let did = self.local_def_id(item_id); @@ -647,7 +647,7 @@ impl<'a, 'tcx> CrateMetadata { tcx.alloc_adt_def(did, kind, variants, repr) } - pub fn get_predicates( + crate fn get_predicates( &self, item_id: DefIndex, tcx: TyCtxt<'tcx>, @@ -655,7 +655,7 @@ impl<'a, 'tcx> CrateMetadata { self.entry(item_id).predicates.unwrap().decode((self, tcx)) } - pub fn get_predicates_defined_on( + crate fn get_predicates_defined_on( &self, item_id: DefIndex, tcx: TyCtxt<'tcx>, @@ -663,7 +663,7 @@ impl<'a, 'tcx> CrateMetadata { self.entry(item_id).predicates_defined_on.unwrap().decode((self, tcx)) } - pub fn get_super_predicates( + crate fn get_super_predicates( &self, item_id: DefIndex, tcx: TyCtxt<'tcx>, @@ -677,30 +677,27 @@ impl<'a, 'tcx> CrateMetadata { super_predicates.decode((self, tcx)) } - pub fn get_generics(&self, - item_id: DefIndex, - sess: &Session) - -> ty::Generics { + crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics { self.entry(item_id).generics.unwrap().decode((self, sess)) } - pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { + crate fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { self.entry(id).ty.unwrap().decode((self, tcx)) } - pub fn get_stability(&self, id: DefIndex) -> Option { + crate fn get_stability(&self, id: DefIndex) -> Option { match self.is_proc_macro(id) { true => self.root.proc_macro_stability.clone(), false => self.entry(id).stability.map(|stab| stab.decode(self)), } } - pub fn get_deprecation(&self, id: DefIndex) -> Option { + crate fn get_deprecation(&self, id: DefIndex) -> Option { self.entry_unless_proc_macro(id) .and_then(|entry| entry.deprecation.map(|depr| depr.decode(self))) } - pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { + crate fn get_visibility(&self, id: DefIndex) -> ty::Visibility { match self.is_proc_macro(id) { true => ty::Visibility::Public, false => self.entry(id).visibility.decode(self), @@ -714,30 +711,31 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_parent_impl(&self, id: DefIndex) -> Option { + crate fn get_parent_impl(&self, id: DefIndex) -> Option { self.get_impl_data(id).parent_impl } - pub fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity { + crate fn get_impl_polarity(&self, id: DefIndex) -> ty::ImplPolarity { self.get_impl_data(id).polarity } - pub fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness { + crate fn get_impl_defaultness(&self, id: DefIndex) -> hir::Defaultness { self.get_impl_data(id).defaultness } - pub fn get_coerce_unsized_info(&self, - id: DefIndex) - -> Option { + crate fn get_coerce_unsized_info( + &self, + id: DefIndex, + ) -> Option { self.get_impl_data(id).coerce_unsized_info } - pub fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option> { + crate fn get_impl_trait(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Option> { self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx))) } /// Iterates over all the stability attributes in the given crate. - pub fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(ast::Name, Option)] { + crate fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(ast::Name, Option)] { // FIXME: For a proc macro crate, not sure whether we should return the "host" // features or an empty Vec. Both don't cause ICEs. tcx.arena.alloc_from_iter(self.root @@ -746,7 +744,7 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over the language items in the given crate. - pub fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { + crate fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { if self.is_proc_macro_crate() { // Proc macro crates do not export any lang-items to the target. &[] @@ -759,7 +757,7 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over the diagnostic items in the given crate. - pub fn get_diagnostic_items( + crate fn get_diagnostic_items( &self, tcx: TyCtxt<'tcx>, ) -> &'tcx FxHashMap { @@ -776,7 +774,7 @@ impl<'a, 'tcx> CrateMetadata { } /// Iterates over each child of the given item. - pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) + crate fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Session) where F: FnMut(def::Export) { if let Some(proc_macros_ids) = self.root.proc_macro_data.map(|d| d.decode(self)) { @@ -911,12 +909,12 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn is_item_mir_available(&self, id: DefIndex) -> bool { + crate fn is_item_mir_available(&self, id: DefIndex) -> bool { !self.is_proc_macro(id) && self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() } - pub fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { + crate fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { self.entry_unless_proc_macro(id) .and_then(|entry| entry.mir.map(|mir| mir.decode((self, tcx)))) .unwrap_or_else(|| { @@ -924,7 +922,7 @@ impl<'a, 'tcx> CrateMetadata { }) } - pub fn get_promoted_mir( + crate fn get_promoted_mir( &self, tcx: TyCtxt<'tcx>, id: DefIndex, @@ -936,7 +934,7 @@ impl<'a, 'tcx> CrateMetadata { }) } - pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { + crate fn mir_const_qualif(&self, id: DefIndex) -> u8 { match self.entry(id).kind { EntryKind::Const(qualif, _) | EntryKind::AssocConst(AssocContainer::ImplDefault, qualif, _) | @@ -947,7 +945,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem { + crate fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem { let item = self.entry(id); let def_key = self.def_key(id); let parent = self.local_def_id(def_key.parent.unwrap()); @@ -981,11 +979,11 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_item_variances(&self, id: DefIndex) -> Vec { + crate fn get_item_variances(&self, id: DefIndex) -> Vec { self.entry(id).variances.decode(self).collect() } - pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { + crate fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { match self.entry(node_id).kind { EntryKind::Struct(data, _) | EntryKind::Union(data, _) | @@ -994,7 +992,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { + crate fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { match self.entry(node_id).kind { EntryKind::Struct(data, _) => { data.decode(self).ctor.map(|index| self.local_def_id(index)) @@ -1006,8 +1004,7 @@ impl<'a, 'tcx> CrateMetadata { } } - - pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> { + crate fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Attribute]> { // The attributes for a tuple struct/variant are attached to the definition, not the ctor; // we assume that someone passing in a tuple struct ctor is actually wanting to // look at the definition @@ -1022,7 +1019,11 @@ impl<'a, 'tcx> CrateMetadata { Lrc::from(self.get_attributes(&item, sess)) } - pub fn get_struct_field_names(&self, id: DefIndex, sess: &Session) -> Vec> { + crate fn get_struct_field_names( + &self, + id: DefIndex, + sess: &Session, + ) -> Vec> { self.entry(id) .children .decode(self) @@ -1049,7 +1050,7 @@ impl<'a, 'tcx> CrateMetadata { None } - pub fn get_inherent_implementations_for_type( + crate fn get_inherent_implementations_for_type( &self, tcx: TyCtxt<'tcx>, id: DefIndex, @@ -1060,7 +1061,7 @@ impl<'a, 'tcx> CrateMetadata { .map(|index| self.local_def_id(index))) } - pub fn get_implementations_for_trait( + crate fn get_implementations_for_trait( &self, tcx: TyCtxt<'tcx>, filter: Option, @@ -1091,7 +1092,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_trait_of_item(&self, id: DefIndex) -> Option { + crate fn get_trait_of_item(&self, id: DefIndex) -> Option { let def_key = self.def_key(id); match def_key.disambiguated_data.data { DefPathData::TypeNs(..) | DefPathData::ValueNs(..) => (), @@ -1108,7 +1109,7 @@ impl<'a, 'tcx> CrateMetadata { } - pub fn get_native_libraries(&self, sess: &Session) -> Vec { + crate fn get_native_libraries(&self, sess: &Session) -> Vec { if self.is_proc_macro_crate() { // Proc macro crates do not have any *target* native libraries. vec![] @@ -1117,7 +1118,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] { + crate fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] { if self.is_proc_macro_crate() { // Proc macro crates do not have any *target* foreign modules. &[] @@ -1126,7 +1127,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_dylib_dependency_formats( + crate fn get_dylib_dependency_formats( &self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(CrateNum, LinkagePreference)] { @@ -1140,7 +1141,7 @@ impl<'a, 'tcx> CrateMetadata { })) } - pub fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] { + crate fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] { if self.is_proc_macro_crate() { // Proc macro crates do not depend on any target weak lang-items. &[] @@ -1151,7 +1152,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_fn_param_names(&self, id: DefIndex) -> Vec { + crate fn get_fn_param_names(&self, id: DefIndex) -> Vec { let param_names = match self.entry(id).kind { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names, @@ -1161,7 +1162,7 @@ impl<'a, 'tcx> CrateMetadata { param_names.decode(self).collect() } - pub fn exported_symbols( + crate fn exported_symbols( &self, tcx: TyCtxt<'tcx>, ) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> { @@ -1174,7 +1175,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_rendered_const(&self, id: DefIndex) -> String { + crate fn get_rendered_const(&self, id: DefIndex) -> String { match self.entry(id).kind { EntryKind::Const(_, data) | EntryKind::AssocConst(_, _, data) => data.decode(self).0, @@ -1182,7 +1183,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn get_macro(&self, id: DefIndex) -> MacroDef { + crate fn get_macro(&self, id: DefIndex) -> MacroDef { let entry = self.entry(id); match entry.kind { EntryKind::MacroDef(macro_def) => macro_def.decode(self), @@ -1200,7 +1201,7 @@ impl<'a, 'tcx> CrateMetadata { constness == hir::Constness::Const } - pub fn asyncness(&self, id: DefIndex) -> hir::IsAsync { + crate fn asyncness(&self, id: DefIndex) -> hir::IsAsync { match self.entry(id).kind { EntryKind::Fn(data) => data.decode(self).asyncness, EntryKind::Method(data) => data.decode(self).fn_data.asyncness, @@ -1209,7 +1210,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn is_foreign_item(&self, id: DefIndex) -> bool { + crate fn is_foreign_item(&self, id: DefIndex) -> bool { match self.entry(id).kind { EntryKind::ForeignImmStatic | EntryKind::ForeignMutStatic | @@ -1228,7 +1229,7 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { + crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { let sig = match self.entry(id).kind { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).sig, @@ -1242,7 +1243,7 @@ impl<'a, 'tcx> CrateMetadata { } #[inline] - pub fn def_key(&self, index: DefIndex) -> DefKey { + crate fn def_key(&self, index: DefIndex) -> DefKey { let mut key = self.def_path_table.def_key(index); if self.is_proc_macro(index) { let name = self.raw_proc_macro(index).name(); @@ -1252,13 +1253,13 @@ impl<'a, 'tcx> CrateMetadata { } // Returns the path leading to the thing with this `id`. - pub fn def_path(&self, id: DefIndex) -> DefPath { + crate fn def_path(&self, id: DefIndex) -> DefPath { debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); DefPath::make(self.cnum, id, |parent| self.def_key(parent)) } #[inline] - pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { + crate fn def_path_hash(&self, index: DefIndex) -> DefPathHash { self.def_path_table.def_path_hash(index) } @@ -1287,9 +1288,10 @@ impl<'a, 'tcx> CrateMetadata { /// /// Proc macro crates don't currently export spans, so this function does not have /// to work for them. - pub fn imported_source_files(&'a self, - local_source_map: &source_map::SourceMap) - -> ReadGuard<'a, Vec> { + fn imported_source_files( + &'a self, + local_source_map: &source_map::SourceMap, + ) -> ReadGuard<'a, Vec> { { let source_files = self.source_map_import_info.borrow(); if !source_files.is_empty() { diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 9a30623b33d6..7f76a9730e19 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -60,7 +60,7 @@ use rustc::ty::TyCtxt; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::PanicStrategy; -pub fn calculate(tcx: TyCtxt<'_>) -> Dependencies { +crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies { tcx.sess.crate_types.borrow().iter().map(|&ty| { let linkage = calculate_type(tcx, ty); verify_ok(tcx, &linkage); diff --git a/src/librustc_metadata/dynamic_lib.rs b/src/librustc_metadata/dynamic_lib.rs index 4c279361ff5e..3871eb89f7b4 100644 --- a/src/librustc_metadata/dynamic_lib.rs +++ b/src/librustc_metadata/dynamic_lib.rs @@ -32,30 +32,6 @@ impl DynamicLibrary { } } - /// Loads a dynamic library into the global namespace (RTLD_GLOBAL on Unix) - /// and do it now (don't use RTLD_LAZY on Unix). - pub fn open_global_now(filename: &Path) -> Result { - let maybe_library = dl::open_global_now(filename.as_os_str()); - match maybe_library { - Err(err) => Err(err), - Ok(handle) => Ok(DynamicLibrary { handle }) - } - } - - /// Returns the environment variable for this process's dynamic library - /// search path - pub fn envvar() -> &'static str { - if cfg!(windows) { - "PATH" - } else if cfg!(target_os = "macos") { - "DYLD_LIBRARY_PATH" - } else if cfg!(target_os = "haiku") { - "LIBRARY_PATH" - } else { - "LD_LIBRARY_PATH" - } - } - /// Accesses the value at the symbol of the dynamic library. pub unsafe fn symbol(&self, symbol: &str) -> Result<*mut T, String> { // This function should have a lifetime constraint of 'a on @@ -83,7 +59,7 @@ mod dl { use std::ptr; use std::str; - pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { + pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { check_for_errors_in(|| { unsafe { match filename { @@ -94,13 +70,6 @@ mod dl { }) } - pub fn open_global_now(filename: &OsStr) -> Result<*mut u8, String> { - check_for_errors_in(|| unsafe { - let s = CString::new(filename.as_bytes()).unwrap(); - libc::dlopen(s.as_ptr(), libc::RTLD_GLOBAL | libc::RTLD_NOW) as *mut u8 - }) - } - unsafe fn open_external(filename: &OsStr) -> *mut u8 { let s = CString::new(filename.as_bytes()).unwrap(); libc::dlopen(s.as_ptr(), libc::RTLD_LAZY) as *mut u8 @@ -110,8 +79,8 @@ mod dl { libc::dlopen(ptr::null(), libc::RTLD_LAZY) as *mut u8 } - pub fn check_for_errors_in(f: F) -> Result where - F: FnOnce() -> T, + fn check_for_errors_in(f: F) -> Result + where F: FnOnce() -> T, { use std::sync::{Mutex, Once}; static INIT: Once = Once::new(); @@ -139,14 +108,15 @@ mod dl { } } - pub unsafe fn symbol(handle: *mut u8, - symbol: *const libc::c_char) - -> Result<*mut u8, String> { + pub(super) unsafe fn symbol( + handle: *mut u8, + symbol: *const libc::c_char, + ) -> Result<*mut u8, String> { check_for_errors_in(|| { libc::dlsym(handle as *mut libc::c_void, symbol) as *mut u8 }) } - pub unsafe fn close(handle: *mut u8) { + pub(super) unsafe fn close(handle: *mut u8) { libc::dlclose(handle as *mut libc::c_void); () } } @@ -178,11 +148,7 @@ mod dl { fn FreeLibrary(handle: HMODULE) -> BOOL; } - pub fn open_global_now(filename: &OsStr) -> Result<*mut u8, String> { - open(Some(filename)) - } - - pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { + pub(super) fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { // disable "dll load failed" error dialog. let prev_error_mode = unsafe { // SEM_FAILCRITICALERRORS 0x01 @@ -225,14 +191,15 @@ mod dl { result } - pub unsafe fn symbol(handle: *mut u8, - symbol: *const c_char) - -> Result<*mut u8, String> { + pub(super) unsafe fn symbol( + handle: *mut u8, + symbol: *const c_char, + ) -> Result<*mut u8, String> { let ptr = GetProcAddress(handle as HMODULE, symbol) as *mut u8; ptr_result(ptr) } - pub unsafe fn close(handle: *mut u8) { + pub(super) unsafe fn close(handle: *mut u8) { FreeLibrary(handle as HMODULE); } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index bbfbba2e0d8f..3e8aa27ee2d8 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -42,9 +42,9 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit::{Visitor, NestedVisitorMap}; use rustc::hir::intravisit; -pub struct EncodeContext<'tcx> { +struct EncodeContext<'tcx> { opaque: opaque::Encoder, - pub tcx: TyCtxt<'tcx>, + tcx: TyCtxt<'tcx>, entries_index: Index<'tcx>, @@ -313,11 +313,12 @@ impl<'tcx> EncodeContext<'tcx> { /// the `Entry` (which may point to other encoded information) /// and will then record the `Lazy` for use in the index. // FIXME(eddyb) remove this. - pub fn record(&mut self, - id: DefId, - op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>, - data: DATA) - { + fn record( + &mut self, + id: DefId, + op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>, + data: DATA, + ) { assert!(id.is_local()); let entry = op(self, data); @@ -1920,7 +1921,7 @@ impl<'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'tcx> { // will allow us to slice the metadata to the precise length that we just // generated regardless of trailing bytes that end up in it. -pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { +crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut encoder = opaque::Encoder::new(vec![]); encoder.emit_raw_bytes(METADATA_HEADER); @@ -1962,7 +1963,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { EncodedMetadata { raw_data: result } } -pub fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { +fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { let ty = tcx.type_of(did); match ty.kind { ty::Adt(ref def, _) => return def.repr, diff --git a/src/librustc_metadata/foreign_modules.rs b/src/librustc_metadata/foreign_modules.rs index 8a4f6e6f17a5..fa1402584eda 100644 --- a/src/librustc_metadata/foreign_modules.rs +++ b/src/librustc_metadata/foreign_modules.rs @@ -3,7 +3,7 @@ use rustc::hir; use rustc::middle::cstore::ForeignModule; use rustc::ty::TyCtxt; -pub fn collect(tcx: TyCtxt<'_>) -> Vec { +crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, modules: Vec::new(), diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 6f248f22cf25..037f9d356308 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -7,7 +7,7 @@ use std::u32; use log::debug; /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. -pub trait FixedSizeEncoding { +trait FixedSizeEncoding { const BYTE_LEN: usize; // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead, @@ -75,25 +75,25 @@ impl FixedSizeEncoding for u32 { /// `u32::MAX`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. -pub struct Index<'tcx> { +crate struct Index<'tcx> { positions: Vec, _marker: PhantomData<&'tcx ()>, } impl Index<'tcx> { - pub fn new(max_index: usize) -> Self { + crate fn new(max_index: usize) -> Self { Index { positions: vec![0xff; max_index * 4], _marker: PhantomData, } } - pub fn record(&mut self, def_id: DefId, entry: Lazy>) { + crate fn record(&mut self, def_id: DefId, entry: Lazy>) { assert!(def_id.is_local()); self.record_index(def_id.index, entry); } - pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { + fn record_index(&mut self, item: DefIndex, entry: Lazy>) { assert!(entry.position < (u32::MAX as usize)); let position = entry.position as u32; let array_index = item.index(); @@ -108,7 +108,7 @@ impl Index<'tcx> { position.write_to_bytes_at(positions, array_index) } - pub fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { + crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); // First we write the length of the lower range ... @@ -123,7 +123,7 @@ impl Lazy<[Index<'tcx>]> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] - pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { + crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { let bytes = &bytes[self.position..]; debug!("Index::lookup: index={:?} len={:?}", def_index, diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index 527d4421fca6..4291f3a4ae34 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -4,7 +4,7 @@ use rustc::ty::TyCtxt; use rustc_target::spec::abi::Abi; use syntax::symbol::sym; -pub fn collect(tcx: TyCtxt<'_>) -> Vec { +crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { args: Vec::new(), }; diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 8df236c41cfb..e89d9015d54b 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -212,12 +212,13 @@ //! no means all of the necessary details. Take a look at the rest of //! metadata::locator or metadata::creader for all the juicy details! -use crate::cstore::{MetadataRef, MetadataBlob}; +use crate::cstore::{MetadataBlob, CStore}; use crate::creader::Library; use crate::schema::{METADATA_HEADER, rustc_version}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; +use rustc_data_structures::sync::MetadataRef; use rustc::middle::cstore::MetadataLoader; use rustc::session::{config, Session}; use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; @@ -245,13 +246,13 @@ use rustc_data_structures::owning_ref::OwningRef; use log::{debug, info, warn}; #[derive(Clone)] -pub struct CrateMismatch { +crate struct CrateMismatch { path: PathBuf, got: String, } #[derive(Clone)] -pub struct Context<'a> { +crate struct Context<'a> { pub sess: &'a Session, pub span: Span, pub crate_name: Symbol, @@ -272,7 +273,7 @@ pub struct Context<'a> { pub metadata_loader: &'a dyn MetadataLoader, } -pub struct CratePaths { +crate struct CratePaths { pub ident: String, pub dylib: Option, pub rlib: Option, @@ -303,7 +304,7 @@ impl CratePaths { } impl<'a> Context<'a> { - pub fn reset(&mut self) { + crate fn reset(&mut self) { self.rejected_via_hash.clear(); self.rejected_via_triple.clear(); self.rejected_via_kind.clear(); @@ -311,7 +312,7 @@ impl<'a> Context<'a> { self.rejected_via_filename.clear(); } - pub fn maybe_load_library_crate(&mut self) -> Option { + crate fn maybe_load_library_crate(&mut self) -> Option { let mut seen_paths = FxHashSet::default(); match self.extra_filename { Some(s) => self.find_library_crate(s, &mut seen_paths) @@ -320,7 +321,7 @@ impl<'a> Context<'a> { } } - pub fn report_errs(self) -> ! { + crate fn report_errs(self) -> ! { let add = match self.root { None => String::new(), Some(r) => format!(" which `{}` depends on", r.ident), @@ -931,7 +932,7 @@ fn get_metadata_section_imp(target: &Target, /// A diagnostic function for dumping crate metadata to an output stream. pub fn list_file_metadata(target: &Target, path: &Path, - loader: &dyn MetadataLoader, + cstore: &CStore, out: &mut dyn io::Write) -> io::Result<()> { let filename = path.file_name().unwrap().to_str().unwrap(); @@ -942,7 +943,7 @@ pub fn list_file_metadata(target: &Target, } else { CrateFlavor::Dylib }; - match get_metadata_section(target, flavor, path, loader) { + match get_metadata_section(target, flavor, path, &*cstore.metadata_loader) { Ok(metadata) => metadata.list_crate_metadata(out), Err(msg) => write!(out, "{}\n", msg), } diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 24ed8fcd8dd0..9e4c2685f116 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -11,7 +11,7 @@ use syntax::feature_gate::{self, GateIssue}; use syntax::symbol::{kw, sym, Symbol}; use syntax::{span_err, struct_span_err}; -pub fn collect(tcx: TyCtxt<'_>) -> Vec { +crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { tcx, libs: Vec::new(), @@ -21,7 +21,7 @@ pub fn collect(tcx: TyCtxt<'_>) -> Vec { return collector.libs; } -pub fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { +crate fn relevant_lib(sess: &Session, lib: &NativeLibrary) -> bool { match lib.cfg { Some(ref cfg) => attr::cfg_matches(cfg, &sess.parse_sess, None), None => true, diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 4fe9c466cb6d..d3539e714012 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -21,7 +21,7 @@ use syntax_pos::{self, Span}; use std::marker::PhantomData; -pub fn rustc_version() -> String { +crate fn rustc_version() -> String { format!("rustc {}", option_env!("CFG_VERSION").unwrap_or("unknown version")) } @@ -29,7 +29,7 @@ pub fn rustc_version() -> String { /// Metadata encoding version. /// N.B., increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `rustc_version()`. -pub const METADATA_VERSION: u8 = 4; +const METADATA_VERSION: u8 = 4; /// Metadata header which includes `METADATA_VERSION`. /// To get older versions of rustc to ignore this metadata, @@ -39,12 +39,12 @@ pub const METADATA_VERSION: u8 = 4; /// This header is followed by the position of the `CrateRoot`, /// which is encoded as a 32-bit big-endian unsigned integer, /// and further followed by the rustc version string. -pub const METADATA_HEADER: &[u8; 12] = +crate const METADATA_HEADER: &[u8; 12] = &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION]; /// Additional metadata for a `Lazy` where `T` may not be `Sized`, /// e.g. for `Lazy<[T]>`, this is the length (count of `T` values). -pub trait LazyMeta { +crate trait LazyMeta { type Meta: Copy + 'static; /// Returns the minimum encoded size. @@ -98,7 +98,7 @@ impl LazyMeta for [T] { #[must_use] // FIXME(#59875) the `Meta` parameter only exists to dodge // invariance wrt `T` (coming from the `meta: T::Meta` field). -pub struct Lazy::Meta> +crate struct Lazy::Meta> where T: ?Sized + LazyMeta, Meta: 'static + Copy, { @@ -108,7 +108,7 @@ pub struct Lazy::Meta> } impl Lazy { - pub fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy { + crate fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy { Lazy { position, meta, @@ -118,13 +118,13 @@ impl Lazy { } impl Lazy { - pub fn from_position(position: usize) -> Lazy { + crate fn from_position(position: usize) -> Lazy { Lazy::from_position_and_meta(position, ()) } } impl Lazy<[T]> { - pub fn empty() -> Lazy<[T]> { + crate fn empty() -> Lazy<[T]> { Lazy::from_position_and_meta(0, 0) } } @@ -141,7 +141,7 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy /// Encoding / decoding state for `Lazy`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum LazyState { +crate enum LazyState { /// Outside of a metadata node. NoNode, @@ -156,7 +156,7 @@ pub enum LazyState { } #[derive(RustcEncodable, RustcDecodable)] -pub struct CrateRoot<'tcx> { +crate struct CrateRoot<'tcx> { pub name: Symbol, pub triple: TargetTriple, pub extra_filename: String, @@ -202,7 +202,7 @@ pub struct CrateRoot<'tcx> { } #[derive(RustcEncodable, RustcDecodable)] -pub struct CrateDep { +crate struct CrateDep { pub name: ast::Name, pub hash: Svh, pub kind: DepKind, @@ -210,13 +210,13 @@ pub struct CrateDep { } #[derive(RustcEncodable, RustcDecodable)] -pub struct TraitImpls { +crate struct TraitImpls { pub trait_id: (u32, DefIndex), pub impls: Lazy<[DefIndex]>, } #[derive(RustcEncodable, RustcDecodable)] -pub struct Entry<'tcx> { +crate struct Entry<'tcx> { pub kind: EntryKind<'tcx>, pub visibility: Lazy, pub span: Lazy, @@ -237,7 +237,7 @@ pub struct Entry<'tcx> { } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -pub enum EntryKind<'tcx> { +crate enum EntryKind<'tcx> { Const(ConstQualif, Lazy), ImmStatic, MutStatic, @@ -272,28 +272,28 @@ pub enum EntryKind<'tcx> { /// Additional data for EntryKind::Const and EntryKind::AssocConst #[derive(Clone, Copy, RustcEncodable, RustcDecodable)] -pub struct ConstQualif { +crate struct ConstQualif { pub mir: u8, } /// Contains a constant which has been rendered to a String. /// Used by rustdoc. #[derive(RustcEncodable, RustcDecodable)] -pub struct RenderedConst(pub String); +crate struct RenderedConst(pub String); #[derive(RustcEncodable, RustcDecodable)] -pub struct ModData { +crate struct ModData { pub reexports: Lazy<[def::Export]>, } #[derive(RustcEncodable, RustcDecodable)] -pub struct MacroDef { +crate struct MacroDef { pub body: String, pub legacy: bool, } #[derive(RustcEncodable, RustcDecodable)] -pub struct FnData<'tcx> { +crate struct FnData<'tcx> { pub asyncness: hir::IsAsync, pub constness: hir::Constness, pub param_names: Lazy<[ast::Name]>, @@ -301,7 +301,7 @@ pub struct FnData<'tcx> { } #[derive(RustcEncodable, RustcDecodable)] -pub struct VariantData<'tcx> { +crate struct VariantData<'tcx> { pub ctor_kind: CtorKind, pub discr: ty::VariantDiscr, /// If this is unit or tuple-variant/struct, then this is the index of the ctor id. @@ -312,7 +312,7 @@ pub struct VariantData<'tcx> { } #[derive(RustcEncodable, RustcDecodable)] -pub struct TraitData<'tcx> { +crate struct TraitData<'tcx> { pub unsafety: hir::Unsafety, pub paren_sugar: bool, pub has_auto_impl: bool, @@ -321,12 +321,12 @@ pub struct TraitData<'tcx> { } #[derive(RustcEncodable, RustcDecodable)] -pub struct TraitAliasData<'tcx> { +crate struct TraitAliasData<'tcx> { pub super_predicates: Lazy>, } #[derive(RustcEncodable, RustcDecodable)] -pub struct ImplData<'tcx> { +crate struct ImplData<'tcx> { pub polarity: ty::ImplPolarity, pub defaultness: hir::Defaultness, pub parent_impl: Option, @@ -341,7 +341,7 @@ pub struct ImplData<'tcx> { /// is a trait or an impl and whether, in a trait, it has /// a default, or an in impl, whether it's marked "default". #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -pub enum AssocContainer { +crate enum AssocContainer { TraitRequired, TraitWithDefault, ImplDefault, @@ -349,7 +349,7 @@ pub enum AssocContainer { } impl AssocContainer { - pub fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer { + crate fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer { match *self { AssocContainer::TraitRequired | AssocContainer::TraitWithDefault => ty::TraitContainer(def_id), @@ -359,7 +359,7 @@ impl AssocContainer { } } - pub fn defaultness(&self) -> hir::Defaultness { + crate fn defaultness(&self) -> hir::Defaultness { match *self { AssocContainer::TraitRequired => hir::Defaultness::Default { has_value: false, @@ -376,22 +376,22 @@ impl AssocContainer { } #[derive(RustcEncodable, RustcDecodable)] -pub struct MethodData<'tcx> { +crate struct MethodData<'tcx> { pub fn_data: FnData<'tcx>, pub container: AssocContainer, pub has_self: bool, } #[derive(RustcEncodable, RustcDecodable)] -pub struct ClosureData<'tcx> { +crate struct ClosureData<'tcx> { pub sig: Lazy>, } #[derive(RustcEncodable, RustcDecodable)] -pub struct GeneratorData<'tcx> { +crate struct GeneratorData<'tcx> { pub layout: mir::GeneratorLayout<'tcx>, } // Tags used for encoding Spans: -pub const TAG_VALID_SPAN: u8 = 0; -pub const TAG_INVALID_SPAN: u8 = 1; +crate const TAG_VALID_SPAN: u8 = 0; +crate const TAG_INVALID_SPAN: u8 = 1; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 2b8965aa5d41..e2c666e0f8fb 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -104,8 +104,7 @@ impl<'a> Resolver<'a> { return self.module_map[&def_id] } - let macros_only = self.cstore.dep_kind_untracked(def_id.krate).macros_only(); - if let Some(&module) = self.extern_module_map.get(&(def_id, macros_only)) { + if let Some(&module) = self.extern_module_map.get(&def_id) { return module; } @@ -121,7 +120,7 @@ impl<'a> Resolver<'a> { let module = self.arenas.alloc_module(ModuleData::new( parent, kind, def_id, ExpnId::root(), DUMMY_SP )); - self.extern_module_map.insert((def_id, macros_only), module); + self.extern_module_map.insert(def_id, module); module } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e3c272e12fe5..542afe70745d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -878,7 +878,7 @@ pub struct Resolver<'a> { /// language items. empty_module: Module<'a>, module_map: FxHashMap>, - extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>, + extern_module_map: FxHashMap>, binding_parent_modules: FxHashMap>, Module<'a>>, /// Maps glob imports to the names of items actually imported. From b476f2fa4e97cc5050469f199582f2a32da4a589 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 6 Oct 2019 16:42:14 +0300 Subject: [PATCH 363/545] rustc_metadata: Use `CrateSource` where appropriate --- src/librustc/middle/cstore.rs | 6 +++ src/librustc_metadata/creader.rs | 34 +++++----------- src/librustc_metadata/locator.rs | 70 ++++++++++++-------------------- 3 files changed, 43 insertions(+), 67 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 065959ed09fd..1706d3120fb6 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -32,6 +32,12 @@ pub struct CrateSource { pub rmeta: Option<(PathBuf, PathKind)>, } +impl CrateSource { + pub fn paths(&self) -> impl Iterator { + self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0) + } +} + #[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, HashStable)] pub enum DepKind { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 956df7828440..438d42cf7528 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -34,9 +34,7 @@ use log::{debug, info, log_enabled}; use proc_macro::bridge::client::ProcMacro; crate struct Library { - pub dylib: Option<(PathBuf, PathKind)>, - pub rlib: Option<(PathBuf, PathKind)>, - pub rmeta: Option<(PathBuf, PathKind)>, + pub source: CrateSource, pub metadata: MetadataBlob, } @@ -197,10 +195,10 @@ impl<'a> CrateLoader<'a> { dep_kind: DepKind, name: Symbol ) -> (CrateNum, Lrc) { - let _prof_timer = - self.sess.prof.generic_activity("metadata_register_crate"); + let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); - let crate_root = lib.metadata.get_root(); + let Library { source, metadata } = lib; + let crate_root = metadata.get_root(); self.verify_no_symbol_conflicts(span, &crate_root); let private_dep = self.sess.opts.externs.get(&name.as_str()) @@ -218,28 +216,22 @@ impl<'a> CrateLoader<'a> { let root = if let Some(root) = root { root } else { - crate_paths = CratePaths { - ident: crate_root.name.to_string(), - dylib: lib.dylib.clone().map(|p| p.0), - rlib: lib.rlib.clone().map(|p| p.0), - rmeta: lib.rmeta.clone().map(|p| p.0), - }; + crate_paths = CratePaths { name: crate_root.name, source: source.clone() }; &crate_paths }; - let Library { dylib, rlib, rmeta, metadata } = lib; let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind); let dependencies: Vec = cnum_map.iter().cloned().collect(); let raw_proc_macros = crate_root.proc_macro_data.map(|_| { let temp_root; - let (dlsym_dylib, dlsym_root) = match &host_lib { + let (dlsym_source, dlsym_root) = match &host_lib { Some(host_lib) => - (&host_lib.dylib, { temp_root = host_lib.metadata.get_root(); &temp_root }), - None => (&dylib, &crate_root), + (&host_lib.source, { temp_root = host_lib.metadata.get_root(); &temp_root }), + None => (&source, &crate_root), }; - let dlsym_dylib = dlsym_dylib.as_ref().expect("no dylib for a proc-macro crate"); + let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator, span) }); @@ -268,11 +260,7 @@ impl<'a> CrateLoader<'a> { source_map_import_info: RwLock::new(vec![]), alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index), dep_kind: Lock::new(dep_kind), - source: CrateSource { - dylib, - rlib, - rmeta, - }, + source, private_dep, raw_proc_macros, dep_node_index: AtomicCell::new(DepNodeIndex::INVALID), @@ -558,7 +546,7 @@ impl<'a> CrateLoader<'a> { (data.source.dylib.clone(), PMDSource::Registered(data)) } LoadResult::Loaded(library) => { - let dylib = library.dylib.clone(); + let dylib = library.source.dylib.clone(); let metadata = PMDSource::Owned(library); (dylib, metadata) } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index e89d9015d54b..05676dad3340 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -219,7 +219,7 @@ use crate::schema::{METADATA_HEADER, rustc_version}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; -use rustc::middle::cstore::MetadataLoader; +use rustc::middle::cstore::{CrateSource, MetadataLoader}; use rustc::session::{config, Session}; use rustc::session::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; use rustc::session::search_paths::PathKind; @@ -274,10 +274,8 @@ crate struct Context<'a> { } crate struct CratePaths { - pub ident: String, - pub dylib: Option, - pub rlib: Option, - pub rmeta: Option, + pub name: Symbol, + pub source: CrateSource, } #[derive(Copy, Clone, PartialEq)] @@ -297,12 +295,6 @@ impl fmt::Display for CrateFlavor { } } -impl CratePaths { - fn paths(&self) -> Vec { - self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).cloned().collect() - } -} - impl<'a> Context<'a> { crate fn reset(&mut self) { self.rejected_via_hash.clear(); @@ -324,7 +316,7 @@ impl<'a> Context<'a> { crate fn report_errs(self) -> ! { let add = match self.root { None => String::new(), - Some(r) => format!(" which `{}` depends on", r.ident), + Some(r) => format!(" which `{}` depends on", r.name), }; let mut msg = "the following crate versions were found:".to_string(); let mut err = if !self.rejected_via_hash.is_empty() { @@ -342,8 +334,8 @@ impl<'a> Context<'a> { match self.root { None => {} Some(r) => { - for path in r.paths().iter() { - msg.push_str(&format!("\ncrate `{}`: {}", r.ident, path.display())); + for path in r.source.paths() { + msg.push_str(&format!("\ncrate `{}`: {}", r.name, path.display())); } } } @@ -535,18 +527,8 @@ impl<'a> Context<'a> { // search is being performed for. let mut libraries = FxHashMap::default(); for (_hash, (rlibs, rmetas, dylibs)) in candidates { - let mut slot = None; - let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot); - let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot); - let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot); - if let Some((h, m)) = slot { - libraries.insert(h, - Library { - dylib, - rlib, - rmeta, - metadata: m, - }); + if let Some((svh, lib)) = self.extract_lib(rlibs, rmetas, dylibs) { + libraries.insert(svh, lib); } } @@ -564,7 +546,7 @@ impl<'a> Context<'a> { self.crate_name); let candidates = libraries.iter().filter_map(|(_, lib)| { let crate_name = &lib.metadata.get_root().name.as_str(); - match &(&lib.dylib, &lib.rlib) { + match &(&lib.source.dylib, &lib.source.rlib) { &(&Some((ref pd, _)), &Some((ref pr, _))) => { Some(format!("\ncrate `{}`: {}\n{:>padding$}", crate_name, @@ -585,6 +567,21 @@ impl<'a> Context<'a> { } } + fn extract_lib( + &mut self, + rlibs: FxHashMap, + rmetas: FxHashMap, + dylibs: FxHashMap, + ) -> Option<(Svh, Library)> { + let mut slot = None; + let source = CrateSource { + rlib: self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot), + rmeta: self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot), + dylib: self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot), + }; + slot.map(|(svh, metadata)| (svh, Library { source, metadata })) + } + // Attempts to extract *one* library from the set `m`. If the set has no // elements, `None` is returned. If the set has more than one element, then // the errors and notes are emitted about the set of libraries. @@ -829,23 +826,8 @@ impl<'a> Context<'a> { } }; - // Extract the rlib/dylib pair. - let mut slot = None; - let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot); - let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot); - let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot); - - if rlib.is_none() && rmeta.is_none() && dylib.is_none() { - return None; - } - slot.map(|(_, metadata)| - Library { - dylib, - rlib, - rmeta, - metadata, - } - ) + // Extract the dylib/rlib/rmeta triple. + self.extract_lib(rlibs, rmetas, dylibs).map(|(_, lib)| lib) } } From 2805553dd8dcb2bd7388cf8a53bed82e876ab5d1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 6 Oct 2019 22:25:57 +0300 Subject: [PATCH 364/545] rustc_metadata: Improve documentation of `CrateMetadata` --- src/librustc_metadata/cstore.rs | 61 +++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index a9fa210b53c5..08e824d45761 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -37,50 +37,61 @@ crate struct ImportedSourceFile { } pub struct CrateMetadata { - /// Information about the extern crate that caused this crate to - /// be loaded. If this is `None`, then the crate was injected - /// (e.g., by the allocator) - crate extern_crate: Lock>, - + /// The primary crate data - binary metadata blob. crate blob: MetadataBlob, - crate cnum_map: CrateNumMap, - crate cnum: CrateNum, - crate dependencies: Lock>, - crate source_map_import_info: RwLock>, - /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. - crate alloc_decoding_state: AllocDecodingState, + // --- Some data pre-decoded from the metadata blob, usually for performance --- - // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this - // lifetime is only used behind `Lazy`, and therefore acts like an - // universal (`for<'tcx>`), that is paired up with whichever `TyCtxt` - // is being used to decode those values. + /// Properties of the whole crate. + /// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this + /// lifetime is only used behind `Lazy`, and therefore acts like an + /// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt` + /// is being used to decode those values. crate root: schema::CrateRoot<'static>, - /// For each definition in this crate, we encode a key. When the /// crate is loaded, we read all the keys and put them in this /// hashmap, which gives the reverse mapping. This allows us to /// quickly retrace a `DefPath`, which is needed for incremental /// compilation support. crate def_path_table: Lrc, - + /// Trait impl data. + /// FIXME: Used only from queries and can use query cache, + /// so pre-decoding can probably be avoided. crate trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>, + /// Proc macro descriptions for this crate, if it's a proc macro crate. + crate raw_proc_macros: Option<&'static [ProcMacro]>, + /// Source maps for code from the crate. + crate source_map_import_info: RwLock>, + /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. + crate alloc_decoding_state: AllocDecodingState, + /// The `DepNodeIndex` of the `DepNode` representing this upstream crate. + /// It is initialized on the first access in `get_crate_dep_node_index()`. + /// Do not access the value directly, as it might not have been initialized yet. + /// The field must always be initialized to `DepNodeIndex::INVALID`. + crate dep_node_index: AtomicCell, + // --- Other significant crate properties --- + + /// ID of this crate, from the current compilation session's point of view. + crate cnum: CrateNum, + /// Maps crate IDs as they are were seen from this crate's compilation sessions into + /// IDs as they are seen from the current compilation session. + crate cnum_map: CrateNumMap, + /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime. + crate dependencies: Lock>, + /// How to link (or not link) this crate to the currently compiled crate. crate dep_kind: Lock, + /// Filesystem location of this crate. crate source: CrateSource, - /// Whether or not this crate should be consider a private dependency /// for purposes of the 'exported_private_dependencies' lint crate private_dep: bool, - crate raw_proc_macros: Option<&'static [ProcMacro]>, + // --- Data used only for improving diagnostics --- - /// The `DepNodeIndex` of the `DepNode` representing this upstream crate. - /// It is initialized on the first access in `get_crate_dep_node_index()`. - /// Do not access the value directly, as it might not have been initialized - /// yet. - /// The field must always be initialized to `DepNodeIndex::INVALID`. - crate dep_node_index: AtomicCell, + /// Information about the `extern crate` item or path that caused this crate to be loaded. + /// If this is `None`, then the crate was injected (e.g., by the allocator). + crate extern_crate: Lock>, } pub struct CStore { From e843d867e62a06330e63b419ccd50c178dae40aa Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 13 Oct 2019 23:47:26 +0300 Subject: [PATCH 365/545] rustc_metadata: Crate loader is immutable --- src/librustc_interface/passes.rs | 6 ++--- src/librustc_metadata/creader.rs | 44 ++++++++++++-------------------- src/librustc_resolve/lib.rs | 4 +-- 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 309cf8e255be..5f046847fd1e 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -130,7 +130,7 @@ pub fn configure_and_expand( let crate_name = crate_name.to_string(); let (result, resolver) = BoxedResolver::new(static move || { let sess = &*sess; - let mut crate_loader = CrateLoader::new(sess, &*cstore, &crate_name); + let crate_loader = CrateLoader::new(sess, &*cstore, &crate_name); let resolver_arenas = Resolver::arenas(); let res = configure_and_expand_inner( sess, @@ -138,7 +138,7 @@ pub fn configure_and_expand( krate, &crate_name, &resolver_arenas, - &mut crate_loader, + &crate_loader, plugin_info, ); let mut resolver = match res { @@ -319,7 +319,7 @@ fn configure_and_expand_inner<'a>( mut krate: ast::Crate, crate_name: &str, resolver_arenas: &'a ResolverArenas<'a>, - crate_loader: &'a mut CrateLoader<'a>, + crate_loader: &'a CrateLoader<'a>, plugin_info: PluginInfo, ) -> Result<(ast::Crate, Resolver<'a>)> { time(sess, "pre-AST-expansion lint checks", || { diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 438d42cf7528..aabcc9f1502e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -187,7 +187,7 @@ impl<'a> CrateLoader<'a> { } fn register_crate( - &mut self, + &self, host_lib: Option, root: Option<&CratePaths>, span: Span, @@ -272,7 +272,7 @@ impl<'a> CrateLoader<'a> { } fn load_proc_macro<'b>( - &mut self, + &self, locate_ctxt: &mut locator::Context<'b>, path_kind: PathKind, ) -> Option<(LoadResult, Option)> @@ -327,7 +327,7 @@ impl<'a> CrateLoader<'a> { } fn resolve_crate<'b>( - &'b mut self, + &'b self, name: Symbol, span: Span, dep_kind: DepKind, @@ -337,7 +337,7 @@ impl<'a> CrateLoader<'a> { } fn maybe_resolve_crate<'b>( - &'b mut self, + &'b self, name: Symbol, span: Span, mut dep_kind: DepKind, @@ -397,7 +397,7 @@ impl<'a> CrateLoader<'a> { } } - fn load(&mut self, locate_ctxt: &mut locator::Context<'_>) -> Option { + fn load(&self, locate_ctxt: &mut locator::Context<'_>) -> Option { let library = locate_ctxt.maybe_load_library_crate()?; // In the case that we're loading a crate, but not matching @@ -424,7 +424,7 @@ impl<'a> CrateLoader<'a> { } } - fn update_extern_crate(&mut self, + fn update_extern_crate(&self, cnum: CrateNum, mut extern_crate: ExternCrate, visited: &mut FxHashSet<(CrateNum, bool)>) @@ -466,7 +466,7 @@ impl<'a> CrateLoader<'a> { } // Go through the crate metadata and load any crates that it references - fn resolve_crate_deps(&mut self, + fn resolve_crate_deps(&self, root: &CratePaths, crate_root: &CrateRoot<'_>, metadata: &MetadataBlob, @@ -496,7 +496,7 @@ impl<'a> CrateLoader<'a> { })).collect() } - fn read_extension_crate(&mut self, name: Symbol, span: Span) -> ExtensionCrate { + fn read_extension_crate(&self, name: Symbol, span: Span) -> ExtensionCrate { info!("read extension crate `{}`", name); let target_triple = self.sess.opts.target_triple.clone(); let host_triple = TargetTriple::from_triple(config::host_triple()); @@ -592,7 +592,7 @@ impl<'a> CrateLoader<'a> { /// Look for a plugin registrar. Returns library path, crate /// SVH and DefIndex of the registrar function. - pub fn find_plugin_registrar(&mut self, + pub fn find_plugin_registrar(&self, span: Span, name: Symbol) -> Option<(PathBuf, CrateDisambiguator)> { @@ -625,7 +625,7 @@ impl<'a> CrateLoader<'a> { } } - fn inject_panic_runtime(&mut self, krate: &ast::Crate) { + fn inject_panic_runtime(&self, krate: &ast::Crate) { // If we're only compiling an rlib, then there's no need to select a // panic runtime, so we just skip this section entirely. let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| { @@ -706,7 +706,7 @@ impl<'a> CrateLoader<'a> { &|data| data.root.needs_panic_runtime); } - fn inject_sanitizer_runtime(&mut self) { + fn inject_sanitizer_runtime(&self) { if let Some(ref sanitizer) = self.sess.opts.debugging_opts.sanitizer { // Sanitizers can only be used on some tested platforms with // executables linked to `std` @@ -804,7 +804,7 @@ impl<'a> CrateLoader<'a> { } } - fn inject_profiler_runtime(&mut self) { + fn inject_profiler_runtime(&self) { if self.sess.opts.debugging_opts.profile || self.sess.opts.cg.profile_generate.enabled() { @@ -821,7 +821,7 @@ impl<'a> CrateLoader<'a> { } } - fn inject_allocator_crate(&mut self, krate: &ast::Crate) { + fn inject_allocator_crate(&self, krate: &ast::Crate) { let has_global_allocator = match &*global_allocator_spans(krate) { [span1, span2, ..] => { self.sess.struct_span_err(*span2, "cannot define multiple global allocators") @@ -960,7 +960,7 @@ impl<'a> CrateLoader<'a> { } impl<'a> CrateLoader<'a> { - pub fn postprocess(&mut self, krate: &ast::Crate) { + pub fn postprocess(&self, krate: &ast::Crate) { self.inject_sanitizer_runtime(); self.inject_profiler_runtime(); self.inject_allocator_crate(krate); @@ -971,9 +971,7 @@ impl<'a> CrateLoader<'a> { } } - pub fn process_extern_crate( - &mut self, item: &ast::Item, definitions: &Definitions, - ) -> CrateNum { + pub fn process_extern_crate(&self, item: &ast::Item, definitions: &Definitions) -> CrateNum { match item.kind { ast::ItemKind::ExternCrate(orig_name) => { debug!("resolving extern crate stmt. ident: {} orig_name: {:?}", @@ -1013,11 +1011,7 @@ impl<'a> CrateLoader<'a> { } } - pub fn process_path_extern( - &mut self, - name: Symbol, - span: Span, - ) -> CrateNum { + pub fn process_path_extern(&self, name: Symbol, span: Span) -> CrateNum { let cnum = self.resolve_crate(name, span, DepKind::Explicit, None).0; self.update_extern_crate( @@ -1035,11 +1029,7 @@ impl<'a> CrateLoader<'a> { cnum } - pub fn maybe_process_path_extern( - &mut self, - name: Symbol, - span: Span, - ) -> Option { + pub fn maybe_process_path_extern(&self, name: Symbol, span: Span) -> Option { let cnum = self.maybe_resolve_crate(name, span, DepKind::Explicit, None).ok()?.0; self.update_extern_crate( diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 542afe70745d..e716a22e226c 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -900,7 +900,7 @@ pub struct Resolver<'a> { arenas: &'a ResolverArenas<'a>, dummy_binding: &'a NameBinding<'a>, - crate_loader: &'a mut CrateLoader<'a>, + crate_loader: &'a CrateLoader<'a>, macro_names: FxHashSet, builtin_macros: FxHashMap, macro_use_prelude: FxHashMap>, @@ -1070,7 +1070,7 @@ impl<'a> Resolver<'a> { cstore: &'a CStore, krate: &Crate, crate_name: &str, - crate_loader: &'a mut CrateLoader<'a>, + crate_loader: &'a CrateLoader<'a>, arenas: &'a ResolverArenas<'a>) -> Resolver<'a> { let root_def_id = DefId::local(CRATE_DEF_INDEX); From f5baad2b5eae0dbe8c59768d51c2681a2cf7c9f1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 14 Oct 2019 01:08:13 +0300 Subject: [PATCH 366/545] rustc_metadata: Remove resolutions for extern crate items from `CStore` Use a more traditional scheme with providing them as a resolver output --- src/librustc/middle/cstore.rs | 1 - src/librustc/ty/context.rs | 8 ++++++-- src/librustc/ty/mod.rs | 3 ++- src/librustc_interface/passes.rs | 2 ++ src/librustc_metadata/creader.rs | 1 - src/librustc_metadata/cstore.rs | 13 +------------ src/librustc_metadata/cstore_impl.rs | 5 ----- src/librustc_resolve/build_reduced_graph.rs | 1 + src/librustc_resolve/lib.rs | 5 ++++- 9 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 1706d3120fb6..2170a288c922 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -214,7 +214,6 @@ pub trait CrateStore { fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool; fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator; fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; - fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option; fn item_generics_cloned_untracked(&self, def: DefId, sess: &Session) -> ty::Generics; fn postorder_cnums_untracked(&self) -> Vec; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index cd52f8fa92c5..256194cfb00e 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -43,7 +43,7 @@ use crate::ty::subst::{UserSubsts, GenericArgKind}; use crate::ty::{BoundVar, BindingMode}; use crate::ty::CanonicalPolyFnSig; use crate::util::common::ErrorReported; -use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet}; +use crate::util::nodemap::{DefIdMap, DefIdSet, ItemLocalMap, ItemLocalSet, NodeMap}; use crate::util::nodemap::{FxHashMap, FxHashSet}; use crate::util::profiling::SelfProfilerRef; @@ -1051,6 +1051,9 @@ pub struct GlobalCtxt<'tcx> { /// Common consts, pre-interned for your convenience. pub consts: CommonConsts<'tcx>, + /// Resolutions of `extern crate` items produced by resolver. + extern_crate_map: NodeMap, + /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. trait_map: FxHashMap TyCtxt<'tcx> { types: common_types, lifetimes: common_lifetimes, consts: common_consts, + extern_crate_map: resolutions.extern_crate_map, trait_map, export_map: resolutions.export_map.into_iter().map(|(k, v)| { let exports: Vec<_> = v.into_iter().map(|e| { @@ -2951,7 +2955,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { }; providers.extern_mod_stmt_cnum = |tcx, id| { let id = tcx.hir().as_local_node_id(id).unwrap(); - tcx.cstore.extern_mod_stmt_cnum_untracked(id) + tcx.extern_crate_map.get(&id).cloned() }; providers.all_crate_nums = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 3692caada577..00b5fa23047e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -28,7 +28,7 @@ use crate::ty::subst::{Subst, InternalSubsts, SubstsRef}; use crate::ty::util::{IntTypeExt, Discr}; use crate::ty::walk::TypeWalker; use crate::util::captures::Captures; -use crate::util::nodemap::{NodeSet, DefIdMap, FxHashMap}; +use crate::util::nodemap::{NodeMap, NodeSet, DefIdMap, FxHashMap}; use arena::SyncDroplessArena; use crate::session::DataTypeKind; @@ -121,6 +121,7 @@ mod sty; #[derive(Clone)] pub struct Resolutions { + pub extern_crate_map: NodeMap, pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 5f046847fd1e..56c7d6adb19c 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -169,6 +169,7 @@ impl ExpansionResult { ExpansionResult { defs: Steal::new(resolver.definitions), resolutions: Steal::new(Resolutions { + extern_crate_map: resolver.extern_crate_map, export_map: resolver.export_map, trait_map: resolver.trait_map, glob_map: resolver.glob_map, @@ -187,6 +188,7 @@ impl ExpansionResult { ExpansionResult { defs: Steal::new(resolver.definitions.clone()), resolutions: Steal::new(Resolutions { + extern_crate_map: resolver.extern_crate_map.clone(), export_map: resolver.export_map.clone(), trait_map: resolver.trait_map.clone(), glob_map: resolver.glob_map.clone(), diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index aabcc9f1502e..9850121d2ce5 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -1004,7 +1004,6 @@ impl<'a> CrateLoader<'a> { }, &mut FxHashSet::default(), ); - self.cstore.add_extern_mod_stmt_cnum(item.id, cnum); cnum } _ => bug!(), diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 08e824d45761..a5a458e49a38 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -8,7 +8,7 @@ use rustc::hir::map::definitions::DefPathTable; use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate, MetadataLoader}; use rustc::mir::interpret::AllocDecodingState; use rustc_index::vec::IndexVec; -use rustc::util::nodemap::{FxHashMap, NodeMap}; +use rustc::util::nodemap::FxHashMap; use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell}; use syntax::ast; use syntax::ext::base::SyntaxExtension; @@ -96,8 +96,6 @@ pub struct CrateMetadata { pub struct CStore { metas: RwLock>>>, - /// Map from NodeId's of local extern crate statements to crate numbers - extern_mod_crate_map: Lock>, crate metadata_loader: Box, } @@ -114,7 +112,6 @@ impl CStore { // corresponding `CrateNum`. This first entry will always remain // `None`. metas: RwLock::new(IndexVec::from_elem_n(None, 1)), - extern_mod_crate_map: Default::default(), metadata_loader, } } @@ -178,12 +175,4 @@ impl CStore { } return ordering } - - crate fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) { - self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum); - } - - crate fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { - self.extern_mod_crate_map.borrow().get(&emod_id).cloned() - } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 21ed22f61f17..fd011265da7c 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -538,11 +538,6 @@ impl CrateStore for cstore::CStore { result } - fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option - { - self.do_extern_mod_stmt_cnum(emod_id) - } - fn postorder_cnums_untracked(&self) -> Vec { self.do_postorder_cnums_untracked() } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e2c666e0f8fb..1f86aafbddff 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -617,6 +617,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let crate_id = self.r.crate_loader.process_extern_crate( item, &self.r.definitions ); + self.r.extern_crate_map.insert(item.id, crate_id); self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) }; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e716a22e226c..5f77bcfeb7ff 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -26,7 +26,7 @@ use rustc::session::Session; use rustc::lint; use rustc::hir::def::{self, DefKind, PartialRes, CtorKind, CtorOf, NonMacroAttrKind, ExportMap}; use rustc::hir::def::Namespace::*; -use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, DefId}; +use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId}; use rustc::hir::{TraitMap, GlobMap}; use rustc::ty::{self, DefIdTree}; use rustc::util::nodemap::{NodeMap, NodeSet, FxHashMap, FxHashSet, DefIdMap}; @@ -855,6 +855,8 @@ pub struct Resolver<'a> { /// Resolutions for labels (node IDs of their corresponding blocks or loops). label_res_map: NodeMap, + /// `CrateNum` resolutions of `extern crate` items. + pub extern_crate_map: NodeMap, pub export_map: ExportMap, pub trait_map: TraitMap, @@ -1155,6 +1157,7 @@ impl<'a> Resolver<'a> { partial_res_map: Default::default(), import_res_map: Default::default(), label_res_map: Default::default(), + extern_crate_map: Default::default(), export_map: FxHashMap::default(), trait_map: Default::default(), empty_module, From 29fb07d2451035cce7fbe99bc854cb3d71b5f1a1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 14 Oct 2019 16:47:12 +0200 Subject: [PATCH 367/545] syntax: add recovery for intersection patterns `p1 @ p2` --- src/libsyntax/parse/parser/pat.rs | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 48f9e3016103..c0e577bd58b1 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -367,6 +367,7 @@ impl<'a> Parser<'a> { let pat = self.mk_pat(lo.to(self.prev_span), pat); let pat = self.maybe_recover_from_bad_qpath(pat, true)?; + let pat = self.recover_intersection_pat(pat)?; if !allow_range_pat { self.ban_pat_range_if_ambiguous(&pat)? @@ -375,6 +376,65 @@ impl<'a> Parser<'a> { Ok(pat) } + /// Try to recover the more general form `intersect ::= $pat_lhs @ $pat_rhs`. + /// + /// Allowed binding patterns generated by `binding ::= ref? mut? $ident @ $pat_rhs` + /// should already have been parsed by now at this point, + /// if the next token is `@` then we can try to parse the more general form. + /// + /// Consult `parse_pat_ident` for the `binding` grammar. + /// + /// The notion of intersection patterns are found in + /// e.g. [F#][and] where they are called AND-patterns. + /// + /// [and]: https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching + fn recover_intersection_pat(&mut self, lhs: P) -> PResult<'a, P> { + if self.token.kind != token::At { + // Next token is not `@` so it's not going to be an intersection pattern. + return Ok(lhs); + } + + // At this point we attempt to parse `@ $pat_rhs` and emit an error. + self.bump(); // `@` + let mut rhs = self.parse_pat(None)?; + let sp = lhs.span.to(rhs.span); + + if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind { + // The user inverted the order, so help them fix that. + let mut applicability = Applicability::MachineApplicable; + lhs.walk(&mut |p| match p.kind { + // `check_match` is unhappy if the subpattern has a binding anywhere. + PatKind::Ident(..) => { + applicability = Applicability::MaybeIncorrect; + false // Short-circuit. + }, + _ => true, + }); + + let lhs_span = lhs.span; + // Move the LHS into the RHS as a subpattern. + // The RHS is now the full pattern. + *sub = Some(lhs); + + self.struct_span_err(sp, "pattern on wrong side of `@`") + .span_label(lhs_span, "pattern on the left, should be to the right") + .span_label(rhs.span, "binding on the right, should be to the left") + .span_suggestion(sp, "switch the order", pprust::pat_to_string(&rhs), applicability) + .emit(); + + rhs.span = sp; + return Ok(rhs); + } + + // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`. + let mut err = self.struct_span_err(sp, "left-hand side of `@` must be a binding pattern"); + err.span_label(lhs.span, "interpreted as a pattern, not a binding") + .span_label(rhs.span, "also a pattern") + .note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`"); + // FIXME(Centril): Introduce `PatKind::Err` and use that instead. + Err(err) + } + /// Ban a range pattern if it has an ambiguous interpretation. fn ban_pat_range_if_ambiguous(&self, pat: &Pat) -> PResult<'a, ()> { match pat.kind { From a77a8aaa2e55c0591ee766f3ff2142a67439d243 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 14 Oct 2019 16:57:18 +0200 Subject: [PATCH 368/545] syntax: add test for intersection pattern parser recovery --- src/test/ui/parser/intersection-patterns.rs | 40 +++++++++++++++++++ .../ui/parser/intersection-patterns.stderr | 33 +++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/test/ui/parser/intersection-patterns.rs create mode 100644 src/test/ui/parser/intersection-patterns.stderr diff --git a/src/test/ui/parser/intersection-patterns.rs b/src/test/ui/parser/intersection-patterns.rs new file mode 100644 index 000000000000..1dda21519e39 --- /dev/null +++ b/src/test/ui/parser/intersection-patterns.rs @@ -0,0 +1,40 @@ +// This tests the parser recovery in `recover_intersection_pat` +// and serves as a regression test for the diagnostics issue #65400. +// +// The general idea is that for `$pat_lhs @ $pat_rhs` where +// `$pat_lhs` is not generated by `ref? mut? $ident` we want +// to suggest either switching the order or note that intersection +// patterns are not allowed. + +fn main() { + let s: Option = None; + + match s { + Some(x) @ y => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be to the right + //~| binding on the right, should be to the left + //~| HELP switch the order + //~| SUGGESTION y@Some(x) + _ => {} + } + + match s { + Some(x) @ Some(y) => {} + //~^ ERROR left-hand side of `@` must be a binding pattern + //~| interpreted as a pattern, not a binding + //~| also a pattern + //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x` + _ => {} + } + + match 2 { + 1 ..= 5 @ e => {} + //~^ ERROR pattern on wrong side of `@` + //~| pattern on the left, should be to the right + //~| binding on the right, should be to the left + //~| HELP switch the order + //~| SUGGESTION e@1 ..=5 + _ => {} + } +} diff --git a/src/test/ui/parser/intersection-patterns.stderr b/src/test/ui/parser/intersection-patterns.stderr new file mode 100644 index 000000000000..03781f8fdee3 --- /dev/null +++ b/src/test/ui/parser/intersection-patterns.stderr @@ -0,0 +1,33 @@ +error: pattern on wrong side of `@` + --> $DIR/intersection-patterns.rs:13:9 + | +LL | Some(x) @ y => {} + | -------^^^- + | | | + | | binding on the right, should be to the left + | pattern on the left, should be to the right + | help: switch the order: `y@Some(x)` + +error: left-hand side of `@` must be a binding pattern + --> $DIR/intersection-patterns.rs:23:9 + | +LL | Some(x) @ Some(y) => {} + | -------^^^------- + | | | + | | also a pattern + | interpreted as a pattern, not a binding + | + = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x` + +error: pattern on wrong side of `@` + --> $DIR/intersection-patterns.rs:32:9 + | +LL | 1 ..= 5 @ e => {} + | -------^^^- + | | | + | | binding on the right, should be to the left + | pattern on the left, should be to the right + | help: switch the order: `e@1 ..=5` + +error: aborting due to 3 previous errors + From 72ad8f716bc2591fba72d7107a9938952214f485 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 14 Oct 2019 17:25:50 +0200 Subject: [PATCH 369/545] syntax: use `PatKind::Wild` as our `::Err` equivalent. --- src/libsyntax/parse/parser/pat.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index c0e577bd58b1..55c534e56ceb 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -421,18 +421,18 @@ impl<'a> Parser<'a> { .span_label(rhs.span, "binding on the right, should be to the left") .span_suggestion(sp, "switch the order", pprust::pat_to_string(&rhs), applicability) .emit(); - - rhs.span = sp; - return Ok(rhs); + } else { + // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`. + rhs.kind = PatKind::Wild; + self.struct_span_err(sp, "left-hand side of `@` must be a binding pattern") + .span_label(lhs.span, "interpreted as a pattern, not a binding") + .span_label(rhs.span, "also a pattern") + .note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`") + .emit(); } - // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`. - let mut err = self.struct_span_err(sp, "left-hand side of `@` must be a binding pattern"); - err.span_label(lhs.span, "interpreted as a pattern, not a binding") - .span_label(rhs.span, "also a pattern") - .note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`"); - // FIXME(Centril): Introduce `PatKind::Err` and use that instead. - Err(err) + rhs.span = sp; + Ok(rhs) } /// Ban a range pattern if it has an ambiguous interpretation. From 4977e319a442bc928031729b4534e6a416965a45 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Oct 2019 17:59:45 +0200 Subject: [PATCH 370/545] update miri --- Cargo.lock | 4 ++-- src/tools/miri | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 844320fff3f1..6d40b1989279 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -556,9 +556,9 @@ dependencies = [ [[package]] name = "compiletest_rs" -version = "0.3.23" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb783fe7afb90ec3d3e49ccaf9196d29ab63c6ed61d4b0695839daa580ae3a3d" +checksum = "676a74b493d50ac33cacd83fd536597e6b52c0b46b9856f7b9c809d82fef4ac0" dependencies = [ "diff", "filetime", diff --git a/src/tools/miri b/src/tools/miri index 07ac10277ea5..2adc39f27b7f 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 07ac10277ea5ad42efbb914da5844e0ab08efbf4 +Subproject commit 2adc39f27b7fd2d06b3d1d470827928766731a1d From 3a9f8deb1d568baeb2cac503cf8667e3170fb2f8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 14 Oct 2019 18:02:49 +0200 Subject: [PATCH 371/545] recover_intersection_pat: adjust wording --- src/libsyntax/parse/parser/pat.rs | 6 +++--- src/test/ui/parser/intersection-patterns.rs | 10 +++++----- src/test/ui/parser/intersection-patterns.stderr | 10 +++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index 55c534e56ceb..e288346a3292 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -417,14 +417,14 @@ impl<'a> Parser<'a> { *sub = Some(lhs); self.struct_span_err(sp, "pattern on wrong side of `@`") - .span_label(lhs_span, "pattern on the left, should be to the right") - .span_label(rhs.span, "binding on the right, should be to the left") + .span_label(lhs_span, "pattern on the left, should be on the right") + .span_label(rhs.span, "binding on the right, should be on the left") .span_suggestion(sp, "switch the order", pprust::pat_to_string(&rhs), applicability) .emit(); } else { // The special case above doesn't apply so we may have e.g. `A(x) @ B(y)`. rhs.kind = PatKind::Wild; - self.struct_span_err(sp, "left-hand side of `@` must be a binding pattern") + self.struct_span_err(sp, "left-hand side of `@` must be a binding") .span_label(lhs.span, "interpreted as a pattern, not a binding") .span_label(rhs.span, "also a pattern") .note("bindings are `x`, `mut x`, `ref x`, and `ref mut x`") diff --git a/src/test/ui/parser/intersection-patterns.rs b/src/test/ui/parser/intersection-patterns.rs index 1dda21519e39..3b0dfd1ee99b 100644 --- a/src/test/ui/parser/intersection-patterns.rs +++ b/src/test/ui/parser/intersection-patterns.rs @@ -12,8 +12,8 @@ fn main() { match s { Some(x) @ y => {} //~^ ERROR pattern on wrong side of `@` - //~| pattern on the left, should be to the right - //~| binding on the right, should be to the left + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left //~| HELP switch the order //~| SUGGESTION y@Some(x) _ => {} @@ -21,7 +21,7 @@ fn main() { match s { Some(x) @ Some(y) => {} - //~^ ERROR left-hand side of `@` must be a binding pattern + //~^ ERROR left-hand side of `@` must be a binding //~| interpreted as a pattern, not a binding //~| also a pattern //~| NOTE bindings are `x`, `mut x`, `ref x`, and `ref mut x` @@ -31,8 +31,8 @@ fn main() { match 2 { 1 ..= 5 @ e => {} //~^ ERROR pattern on wrong side of `@` - //~| pattern on the left, should be to the right - //~| binding on the right, should be to the left + //~| pattern on the left, should be on the right + //~| binding on the right, should be on the left //~| HELP switch the order //~| SUGGESTION e@1 ..=5 _ => {} diff --git a/src/test/ui/parser/intersection-patterns.stderr b/src/test/ui/parser/intersection-patterns.stderr index 03781f8fdee3..39fc9b9475d9 100644 --- a/src/test/ui/parser/intersection-patterns.stderr +++ b/src/test/ui/parser/intersection-patterns.stderr @@ -4,11 +4,11 @@ error: pattern on wrong side of `@` LL | Some(x) @ y => {} | -------^^^- | | | - | | binding on the right, should be to the left - | pattern on the left, should be to the right + | | binding on the right, should be on the left + | pattern on the left, should be on the right | help: switch the order: `y@Some(x)` -error: left-hand side of `@` must be a binding pattern +error: left-hand side of `@` must be a binding --> $DIR/intersection-patterns.rs:23:9 | LL | Some(x) @ Some(y) => {} @@ -25,8 +25,8 @@ error: pattern on wrong side of `@` LL | 1 ..= 5 @ e => {} | -------^^^- | | | - | | binding on the right, should be to the left - | pattern on the left, should be to the right + | | binding on the right, should be on the left + | pattern on the left, should be on the right | help: switch the order: `e@1 ..=5` error: aborting due to 3 previous errors From 16266a54058a71c943d064054bfe3a1b5704a444 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 14 Oct 2019 18:12:04 +0200 Subject: [PATCH 372/545] pprust: `p1@p2` -> `p1 @ p2` --- src/libsyntax/print/pprust.rs | 3 ++- src/test/ui/parser/intersection-patterns.rs | 4 ++-- src/test/ui/parser/intersection-patterns.stderr | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 7d4ffe493d70..68dd90b54ab6 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -2381,7 +2381,8 @@ impl<'a> State<'a> { } self.print_ident(ident); if let Some(ref p) = *sub { - self.s.word("@"); + self.s.space(); + self.s.word_space("@"); self.print_pat(p); } } diff --git a/src/test/ui/parser/intersection-patterns.rs b/src/test/ui/parser/intersection-patterns.rs index 3b0dfd1ee99b..adb607cf6b97 100644 --- a/src/test/ui/parser/intersection-patterns.rs +++ b/src/test/ui/parser/intersection-patterns.rs @@ -15,7 +15,7 @@ fn main() { //~| pattern on the left, should be on the right //~| binding on the right, should be on the left //~| HELP switch the order - //~| SUGGESTION y@Some(x) + //~| SUGGESTION y @ Some(x) _ => {} } @@ -34,7 +34,7 @@ fn main() { //~| pattern on the left, should be on the right //~| binding on the right, should be on the left //~| HELP switch the order - //~| SUGGESTION e@1 ..=5 + //~| SUGGESTION e @ 1 ..=5 _ => {} } } diff --git a/src/test/ui/parser/intersection-patterns.stderr b/src/test/ui/parser/intersection-patterns.stderr index 39fc9b9475d9..f5bfee5bbd61 100644 --- a/src/test/ui/parser/intersection-patterns.stderr +++ b/src/test/ui/parser/intersection-patterns.stderr @@ -6,7 +6,7 @@ LL | Some(x) @ y => {} | | | | | binding on the right, should be on the left | pattern on the left, should be on the right - | help: switch the order: `y@Some(x)` + | help: switch the order: `y @ Some(x)` error: left-hand side of `@` must be a binding --> $DIR/intersection-patterns.rs:23:9 @@ -27,7 +27,7 @@ LL | 1 ..= 5 @ e => {} | | | | | binding on the right, should be on the left | pattern on the left, should be on the right - | help: switch the order: `e@1 ..=5` + | help: switch the order: `e @ 1 ..=5` error: aborting due to 3 previous errors From eb68bbb2b0a8fa78c81fc2a224133d480431fcfc Mon Sep 17 00:00:00 2001 From: ben Date: Sun, 13 Oct 2019 17:52:09 +1300 Subject: [PATCH 373/545] Include const generic arguments in metadata. --- src/librustc_metadata/encoder.rs | 32 ++++--------------- .../auxiliary/const_generic_lib.rs | 9 ++++++ .../const-argument-cross-crate-mismatch.rs | 10 ++++++ ...const-argument-cross-crate-mismatch.stderr | 21 ++++++++++++ .../const-argument-cross-crate.rs | 12 +++++++ 5 files changed, 58 insertions(+), 26 deletions(-) create mode 100644 src/test/ui/const-generics/auxiliary/const_generic_lib.rs create mode 100644 src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs create mode 100644 src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr create mode 100644 src/test/ui/const-generics/const-argument-cross-crate.rs diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index bbfbba2e0d8f..7069cc56bcf4 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -5,7 +5,7 @@ use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; use rustc::hir::def::CtorKind; use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, LOCAL_CRATE}; -use rustc::hir::GenericParamKind; +use rustc::hir::{GenericParamKind, AnonConst}; use rustc::hir::map::definitions::DefPathTable; use rustc_data_structures::fingerprint::Fingerprint; use rustc_index::vec::IndexVec; @@ -1711,6 +1711,11 @@ impl Visitor<'tcx> for EncodeContext<'tcx> { intravisit::walk_expr(self, ex); self.encode_info_for_expr(ex); } + fn visit_anon_const(&mut self, c: &'tcx AnonConst) { + intravisit::walk_anon_const(self, c); + let def_id = self.tcx.hir().local_def_id(c.hir_id); + self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); + } fn visit_item(&mut self, item: &'tcx hir::Item) { intravisit::walk_item(self, item); let def_id = self.tcx.hir().local_def_id(item.hir_id); @@ -1728,25 +1733,10 @@ impl Visitor<'tcx> for EncodeContext<'tcx> { EncodeContext::encode_info_for_foreign_item, (def_id, ni)); } - fn visit_variant(&mut self, - v: &'tcx hir::Variant, - g: &'tcx hir::Generics, - id: hir::HirId) { - intravisit::walk_variant(self, v, g, id); - - if let Some(ref discr) = v.disr_expr { - let def_id = self.tcx.hir().local_def_id(discr.hir_id); - self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); - } - } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { intravisit::walk_generics(self, generics); self.encode_info_for_generics(generics); } - fn visit_ty(&mut self, ty: &'tcx hir::Ty) { - intravisit::walk_ty(self, ty); - self.encode_info_for_ty(ty); - } fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def); @@ -1784,16 +1774,6 @@ impl EncodeContext<'tcx> { } } - fn encode_info_for_ty(&mut self, ty: &hir::Ty) { - match ty.kind { - hir::TyKind::Array(_, ref length) => { - let def_id = self.tcx.hir().local_def_id(length.hir_id); - self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); - } - _ => {} - } - } - fn encode_info_for_expr(&mut self, expr: &hir::Expr) { match expr.kind { hir::ExprKind::Closure(..) => { diff --git a/src/test/ui/const-generics/auxiliary/const_generic_lib.rs b/src/test/ui/const-generics/auxiliary/const_generic_lib.rs new file mode 100644 index 000000000000..901fb5dd054e --- /dev/null +++ b/src/test/ui/const-generics/auxiliary/const_generic_lib.rs @@ -0,0 +1,9 @@ +#![feature(const_generics)] + +pub struct Struct(pub [u8; N]); + +pub type Alias = Struct<2>; + +pub fn function(value: Struct<3>) -> u8 { + value.0[0] +} diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs new file mode 100644 index 000000000000..d863d097d5ca --- /dev/null +++ b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.rs @@ -0,0 +1,10 @@ +// aux-build:const_generic_lib.rs + +extern crate const_generic_lib; + +fn main() { + let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); + //~^ ERROR mismatched types + let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); + //~^ ERROR mismatched types +} diff --git a/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr new file mode 100644 index 000000000000..b7fd29ce7067 --- /dev/null +++ b/src/test/ui/const-generics/const-argument-cross-crate-mismatch.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/const-argument-cross-crate-mismatch.rs:6:41 + | +LL | let _ = const_generic_lib::function(const_generic_lib::Struct([0u8, 1u8])); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `3usize`, found `2usize` + | + = note: expected type `const_generic_lib::Struct<3usize>` + found type `const_generic_lib::Struct<_: usize>` + +error[E0308]: mismatched types + --> $DIR/const-argument-cross-crate-mismatch.rs:8:39 + | +LL | let _: const_generic_lib::Alias = const_generic_lib::Struct([0u8, 1u8, 2u8]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `2usize`, found `3usize` + | + = note: expected type `const_generic_lib::Struct<2usize>` + found type `const_generic_lib::Struct<_: usize>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/const-generics/const-argument-cross-crate.rs b/src/test/ui/const-generics/const-argument-cross-crate.rs new file mode 100644 index 000000000000..98cf39a7ee11 --- /dev/null +++ b/src/test/ui/const-generics/const-argument-cross-crate.rs @@ -0,0 +1,12 @@ +// run-pass +// aux-build:const_generic_lib.rs + +extern crate const_generic_lib; + +struct Container(const_generic_lib::Alias); + +fn main() { + let res = const_generic_lib::function(const_generic_lib::Struct([14u8, 1u8, 2u8])); + assert_eq!(res, 14u8); + let _ = Container(const_generic_lib::Struct([0u8, 1u8])); +} From 34bcfcabcc0cb7ef77a2fa1c8ea95b7b56b99a03 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 14 Oct 2019 21:35:49 +0300 Subject: [PATCH 374/545] Remove an outdated test output file --- .../feature-gate-exhaustive-patterns.nll.stderr | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr deleted file mode 100644 index d77fbc1e8239..000000000000 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.nll.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/feature-gate-exhaustive-patterns.rs:7:9 - | -LL | let Ok(_x) = foo(); - | ^^^^^^ pattern `Err(_)` not covered - | - = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant - = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html -help: you might want to use `if let` to ignore the variant that isn't matched - | -LL | if let Ok(_x) = foo() { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0005`. From 068a8d163cdbab740c62bb7cc802c62e2c4b90b2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 14 Oct 2019 15:12:23 -0300 Subject: [PATCH 375/545] Minor comment tweaks --- src/librustc_data_structures/sync.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 3277b85c2814..432fa3c527f6 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -1,6 +1,6 @@ //! This module defines types which are thread safe if cfg!(parallel_compiler) is true. //! -//! `Lrc` is an alias of either Rc or Arc. +//! `Lrc` is an alias of `Arc` if cfg!(parallel_compiler) is true, `Rc` otherwise. //! //! `Lock` is a mutex. //! It internally uses `parking_lot::Mutex` if cfg!(parallel_compiler) is true, @@ -12,7 +12,7 @@ //! //! `MTLock` is a mutex which disappears if cfg!(parallel_compiler) is false. //! -//! `MTRef` is a immutable reference if cfg!(parallel_compiler), and an mutable reference otherwise. +//! `MTRef` is an immutable reference if cfg!(parallel_compiler), and a mutable reference otherwise. //! //! `rustc_erase_owner!` erases a OwningRef owner into Erased or Erased + Send + Sync //! depending on the value of cfg!(parallel_compiler). From 83560225adf05461e181f5dde303ae8a93a95aba Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 14 Oct 2019 15:15:02 -0300 Subject: [PATCH 376/545] Move serial_scope and serial_join to parallel_compiler = false --- src/librustc_data_structures/sync.rs | 46 ++++++++++++++-------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 432fa3c527f6..1d81aa0b3867 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -23,29 +23,6 @@ use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use crate::owning_ref::{Erased, OwningRef}; -pub fn serial_join(oper_a: A, oper_b: B) -> (RA, RB) - where A: FnOnce() -> RA, - B: FnOnce() -> RB -{ - (oper_a(), oper_b()) -} - -pub struct SerialScope; - -impl SerialScope { - pub fn spawn(&self, f: F) - where F: FnOnce(&SerialScope) - { - f(self) - } -} - -pub fn serial_scope(f: F) -> R - where F: FnOnce(&SerialScope) -> R -{ - f(&SerialScope) -} - pub use std::sync::atomic::Ordering::SeqCst; pub use std::sync::atomic::Ordering; @@ -64,6 +41,29 @@ cfg_if! { } } + pub fn serial_join(oper_a: A, oper_b: B) -> (RA, RB) + where A: FnOnce() -> RA, + B: FnOnce() -> RB + { + (oper_a(), oper_b()) + } + + pub struct SerialScope; + + impl SerialScope { + pub fn spawn(&self, f: F) + where F: FnOnce(&SerialScope) + { + f(self) + } + } + + pub fn serial_scope(f: F) -> R + where F: FnOnce(&SerialScope) -> R + { + f(&SerialScope) + } + use std::ops::Add; use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe}; From b9bc431bd22e8e53398281d1c800fd78fe91e613 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 14 Oct 2019 17:49:47 -0300 Subject: [PATCH 377/545] Rename serial_join and serial_scope to join and scope --- src/librustc_data_structures/sync.rs | 47 +++++++++++++--------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 1d81aa0b3867..9622c290039d 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -41,29 +41,6 @@ cfg_if! { } } - pub fn serial_join(oper_a: A, oper_b: B) -> (RA, RB) - where A: FnOnce() -> RA, - B: FnOnce() -> RB - { - (oper_a(), oper_b()) - } - - pub struct SerialScope; - - impl SerialScope { - pub fn spawn(&self, f: F) - where F: FnOnce(&SerialScope) - { - f(self) - } - } - - pub fn serial_scope(f: F) -> R - where F: FnOnce(&SerialScope) -> R - { - f(&SerialScope) - } - use std::ops::Add; use std::panic::{resume_unwind, catch_unwind, AssertUnwindSafe}; @@ -176,8 +153,28 @@ cfg_if! { pub type AtomicU32 = Atomic; pub type AtomicU64 = Atomic; - pub use self::serial_join as join; - pub use self::serial_scope as scope; + pub fn join(oper_a: A, oper_b: B) -> (RA, RB) + where A: FnOnce() -> RA, + B: FnOnce() -> RB + { + (oper_a(), oper_b()) + } + + pub struct SerialScope; + + impl SerialScope { + pub fn spawn(&self, f: F) + where F: FnOnce(&SerialScope) + { + f(self) + } + } + + pub fn scope(f: F) -> R + where F: FnOnce(&SerialScope) -> R + { + f(&SerialScope) + } #[macro_export] macro_rules! parallel { From 6dd718ca7937fc1a769d65b06396cf64f45f94ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 14 Oct 2019 14:30:59 -0700 Subject: [PATCH 378/545] Use heuristics for capitalization warning in suggestions --- src/librustc_errors/emitter.rs | 27 ++++++++++++++----- src/librustc_errors/lib.rs | 6 ++--- .../extern-prelude-from-opaque-fail.stderr | 2 +- .../lint/lint-group-nonstandard-style.stderr | 2 +- ...lint-lowercase-static-const-pattern.stderr | 4 +-- .../ui/lint/lint-non-camel-case-types.stderr | 4 +-- .../lint/lint-non-snake-case-functions.stderr | 2 +- .../ui/lint/lint-non-uppercase-statics.stderr | 2 +- .../ui/lint/lint-uppercase-variables.stderr | 2 +- src/test/ui/resolve/issue-39226.stderr | 2 +- .../inaccessible-test-modules.stderr | 4 +-- .../ui/traits/trait-impl-for-module.stderr | 2 +- src/test/ui/utf8_idents.stderr | 2 +- 13 files changed, 37 insertions(+), 24 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 040844537680..d02201d5321c 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -13,7 +13,7 @@ use syntax_pos::{SourceFile, Span, MultiSpan}; use crate::{ Level, CodeSuggestion, Diagnostic, SubDiagnostic, - SuggestionStyle, SourceMapperDyn, DiagnosticId, + SuggestionStyle, SourceMapper, SourceMapperDyn, DiagnosticId, }; use crate::Level::Error; use crate::snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; @@ -239,11 +239,11 @@ pub trait Emitter { format!( "help: {}{}: `{}`", sugg.msg, - if self.source_map().as_ref().map(|sm| substitution.to_lowercase() == sm - .span_to_snippet(sugg.substitutions[0].parts[0].span) - .unwrap() - .to_lowercase()).unwrap_or(false) - { + if self.source_map().map(|sm| is_case_difference( + &**sm, + substitution, + sugg.substitutions[0].parts[0].span, + )).unwrap_or(false) { " (notice the capitalization)" } else { "" @@ -2058,3 +2058,18 @@ impl<'a> Drop for WritableDst<'a> { } } } + +/// Whether the original and suggested code are visually similar enough to warrant extra wording. +pub fn is_case_difference(sm: &dyn SourceMapper, suggested: &str, sp: Span) -> bool { + // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode. + let found = sm.span_to_snippet(sp).unwrap(); + let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z']; + // There are ASCII chars that are confusable (above) and differ in capitalization: + let confusable = found.chars().zip(suggested.chars()).any(|(f, s)| { + (ascii_confusables.contains(&f) || ascii_confusables.contains(&s)) && f != s + }); + confusable && found.to_lowercase() == suggested.to_lowercase() + // FIXME: We sometimes suggest the same thing we already have, which is a + // bug, but be defensive against that here. + && found != suggested +} diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index babaeb7e532a..63df052a2250 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -13,7 +13,7 @@ pub use emitter::ColorConfig; use Level::*; -use emitter::{Emitter, EmitterWriter}; +use emitter::{Emitter, EmitterWriter, is_case_difference}; use registry::Registry; use rustc_data_structures::sync::{self, Lrc, Lock}; @@ -239,8 +239,7 @@ impl CodeSuggestion { prev_hi = cm.lookup_char_pos(part.span.hi()); prev_line = fm.get_line(prev_hi.line - 1); } - let only_capitalization = buf.clone().to_lowercase() - == cm.span_to_snippet(bounding_span).unwrap().to_lowercase(); + let only_capitalization = is_case_difference(cm, &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); @@ -250,7 +249,6 @@ impl CodeSuggestion { buf.pop(); } (buf, substitution.parts, only_capitalization) - }).collect() } } diff --git a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr index 1f5e46c133dd..65133eb1e187 100644 --- a/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/src/test/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -5,7 +5,7 @@ LL | use my_core; | ^^^^^^^ | | | no `my_core` in the root - | help: a similar name exists in the module (notice the capitalization): `my_core` + | help: a similar name exists in the module: `my_core` error[E0432]: unresolved import `my_core` --> $DIR/extern-prelude-from-opaque-fail.rs:7:13 diff --git a/src/test/ui/lint/lint-group-nonstandard-style.stderr b/src/test/ui/lint/lint-group-nonstandard-style.stderr index 1ecd0f38826a..1cc973d32c2d 100644 --- a/src/test/ui/lint/lint-group-nonstandard-style.stderr +++ b/src/test/ui/lint/lint-group-nonstandard-style.stderr @@ -41,7 +41,7 @@ error: static variable `bad` should have an upper case name --> $DIR/lint-group-nonstandard-style.rs:14:16 | LL | static bad: isize = 1; - | ^^^ help: convert the identifier to upper case (notice the capitalization): `BAD` + | ^^^ help: convert the identifier to upper case: `BAD` | note: lint level defined here --> $DIR/lint-group-nonstandard-style.rs:10:14 diff --git a/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr b/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr index 5cac1c3d0535..40e5a736a8e5 100644 --- a/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr +++ b/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr @@ -2,7 +2,7 @@ error: constant in pattern `a` should have an upper case name --> $DIR/lint-lowercase-static-const-pattern.rs:11:13 | LL | (0, a) => 0, - | ^ help: convert the identifier to upper case (notice the capitalization): `A` + | ^ help: convert the identifier to upper case: `A` | note: lint level defined here --> $DIR/lint-lowercase-static-const-pattern.rs:4:9 @@ -14,7 +14,7 @@ error: constant in pattern `aha` should have an upper case name --> $DIR/lint-lowercase-static-const-pattern.rs:26:13 | LL | (0, aha) => 0, - | ^^^ help: convert the identifier to upper case (notice the capitalization): `AHA` + | ^^^ help: convert the identifier to upper case: `AHA` error: constant in pattern `not_okay` should have an upper case name --> $DIR/lint-lowercase-static-const-pattern.rs:40:13 diff --git a/src/test/ui/lint/lint-non-camel-case-types.stderr b/src/test/ui/lint/lint-non-camel-case-types.stderr index 02f7db045e5c..177f8c8fe9b6 100644 --- a/src/test/ui/lint/lint-non-camel-case-types.stderr +++ b/src/test/ui/lint/lint-non-camel-case-types.stderr @@ -38,7 +38,7 @@ error: variant `bar` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:22:5 | LL | bar - | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Bar` + | ^^^ help: convert the identifier to upper camel case: `Bar` error: trait `foo6` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:25:7 @@ -50,7 +50,7 @@ error: type parameter `ty` should have an upper camel case name --> $DIR/lint-non-camel-case-types.rs:29:6 | LL | fn f(_: ty) {} - | ^^ help: convert the identifier to upper camel case (notice the capitalization): `Ty` + | ^^ help: convert the identifier to upper camel case: `Ty` error: aborting due to 8 previous errors diff --git a/src/test/ui/lint/lint-non-snake-case-functions.stderr b/src/test/ui/lint/lint-non-snake-case-functions.stderr index 2e7b53b05d16..244522acf1f8 100644 --- a/src/test/ui/lint/lint-non-snake-case-functions.stderr +++ b/src/test/ui/lint/lint-non-snake-case-functions.stderr @@ -26,7 +26,7 @@ error: method `render_HTML` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:17:8 | LL | fn render_HTML() {} - | ^^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `render_html` + | ^^^^^^^^^^^ help: convert the identifier to snake case: `render_html` error: trait method `ABC` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:22:8 diff --git a/src/test/ui/lint/lint-non-uppercase-statics.stderr b/src/test/ui/lint/lint-non-uppercase-statics.stderr index a03bdf52a0a6..ceb83d08f277 100644 --- a/src/test/ui/lint/lint-non-uppercase-statics.stderr +++ b/src/test/ui/lint/lint-non-uppercase-statics.stderr @@ -14,7 +14,7 @@ error: static variable `bar` should have an upper case name --> $DIR/lint-non-uppercase-statics.rs:6:12 | LL | static mut bar: isize = 1; - | ^^^ help: convert the identifier to upper case (notice the capitalization): `BAR` + | ^^^ help: convert the identifier to upper case: `BAR` error: aborting due to 2 previous errors diff --git a/src/test/ui/lint/lint-uppercase-variables.stderr b/src/test/ui/lint/lint-uppercase-variables.stderr index cc2be3d0bd9d..f614d5d71f88 100644 --- a/src/test/ui/lint/lint-uppercase-variables.stderr +++ b/src/test/ui/lint/lint-uppercase-variables.stderr @@ -39,7 +39,7 @@ error: variable `Test` should have a snake case name --> $DIR/lint-uppercase-variables.rs:18:9 | LL | let Test: usize = 0; - | ^^^^ help: convert the identifier to snake case (notice the capitalization): `test` + | ^^^^ help: convert the identifier to snake case: `test` error: variable `Foo` should have a snake case name --> $DIR/lint-uppercase-variables.rs:22:9 diff --git a/src/test/ui/resolve/issue-39226.stderr b/src/test/ui/resolve/issue-39226.stderr index ad596c25551a..d9a28e63dce8 100644 --- a/src/test/ui/resolve/issue-39226.stderr +++ b/src/test/ui/resolve/issue-39226.stderr @@ -8,7 +8,7 @@ LL | handle: Handle | ^^^^^^ | | | did you mean `Handle { /* fields */ }`? - | help: a local variable with a similar name exists (notice the capitalization): `handle` + | help: a local variable with a similar name exists: `handle` error: aborting due to previous error diff --git a/src/test/ui/test-attrs/inaccessible-test-modules.stderr b/src/test/ui/test-attrs/inaccessible-test-modules.stderr index 0b94619f689a..a94ea1e79bc5 100644 --- a/src/test/ui/test-attrs/inaccessible-test-modules.stderr +++ b/src/test/ui/test-attrs/inaccessible-test-modules.stderr @@ -5,7 +5,7 @@ LL | use main as x; | ----^^^^^ | | | no `main` in the root - | help: a similar name exists in the module (notice the capitalization): `main` + | help: a similar name exists in the module: `main` error[E0432]: unresolved import `test` --> $DIR/inaccessible-test-modules.rs:6:5 @@ -14,7 +14,7 @@ LL | use test as y; | ----^^^^^ | | | no `test` in the root - | help: a similar name exists in the module (notice the capitalization): `test` + | help: a similar name exists in the module: `test` error: aborting due to 2 previous errors diff --git a/src/test/ui/traits/trait-impl-for-module.stderr b/src/test/ui/traits/trait-impl-for-module.stderr index 8b81192aa470..4a06cd777d49 100644 --- a/src/test/ui/traits/trait-impl-for-module.stderr +++ b/src/test/ui/traits/trait-impl-for-module.stderr @@ -2,7 +2,7 @@ error[E0573]: expected type, found module `a` --> $DIR/trait-impl-for-module.rs:7:12 | LL | impl A for a { - | ^ help: a trait with a similar name exists (notice the capitalization): `A` + | ^ help: a trait with a similar name exists: `A` error: aborting due to previous error diff --git a/src/test/ui/utf8_idents.stderr b/src/test/ui/utf8_idents.stderr index 869bed61ea0f..56de63da4f97 100644 --- a/src/test/ui/utf8_idents.stderr +++ b/src/test/ui/utf8_idents.stderr @@ -38,7 +38,7 @@ warning: type parameter `γ` should have an upper camel case name --> $DIR/utf8_idents.rs:3:5 | LL | γ - | ^ help: convert the identifier to upper camel case (notice the capitalization): `Γ` + | ^ help: convert the identifier to upper camel case: `Γ` | = note: `#[warn(non_camel_case_types)]` on by default From b6a5740117a66b59a00a40bbfbce6e4f378825de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 13 Jun 2019 22:42:24 +0200 Subject: [PATCH 379/545] Use more fine grained locks for the dep graph --- src/librustc/dep_graph/graph.rs | 132 +++++++++++++++++--------------- 1 file changed, 72 insertions(+), 60 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 25cbf8c88deb..5d2d30f8debb 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -3,7 +3,8 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::vec::{Idx, IndexVec}; use smallvec::SmallVec; -use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, Ordering}; +use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, AtomicU64, Ordering}; +use std::sync::atomic::Ordering::SeqCst; use std::env; use std::hash::Hash; use std::collections::hash_map::Entry; @@ -53,7 +54,7 @@ struct DepGraphData { /// tracking. The `current` field is the dependency graph of only the /// current compilation session: We don't merge the previous dep-graph into /// current one anymore. - current: Lock, + current: CurrentDepGraph, /// The dep-graph from the previous compilation session. It contains all /// nodes and edges as well as all fingerprints of nodes that have them. @@ -95,7 +96,7 @@ impl DepGraph { data: Some(Lrc::new(DepGraphData { previous_work_products: prev_work_products, dep_node_debug: Default::default(), - current: Lock::new(CurrentDepGraph::new(prev_graph_node_count)), + current: CurrentDepGraph::new(prev_graph_node_count), emitting_diagnostics: Default::default(), emitting_diagnostics_cond_var: Condvar::new(), previous: prev_graph, @@ -117,13 +118,12 @@ impl DepGraph { } pub fn query(&self) -> DepGraphQuery { - let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); - let nodes: Vec<_> = current_dep_graph.data.iter().map(|n| n.node).collect(); + let data = self.data.as_ref().unwrap().current.data.lock(); + let nodes: Vec<_> = data.iter().map(|n| n.node).collect(); let mut edges = Vec::new(); - for (from, edge_targets) in current_dep_graph.data.iter() - .map(|d| (d.node, &d.edges)) { + for (from, edge_targets) in data.iter().map(|d| (d.node, &d.edges)) { for &edge_target in edge_targets.iter() { - let to = current_dep_graph.data[edge_target].node; + let to = data[edge_target].node; edges.push((from, to)); } } @@ -202,7 +202,7 @@ impl DepGraph { read_set: Default::default(), }), |data, key, fingerprint, task| { - data.borrow_mut().complete_task(key, task.unwrap(), fingerprint) + data.complete_task(key, task.unwrap(), fingerprint) }, hash_result) } @@ -223,7 +223,7 @@ impl DepGraph { self.with_task_impl(key, cx, input, true, identity_fn, |_| None, |data, key, fingerprint, _| { - data.borrow_mut().alloc_node(key, SmallVec::new(), fingerprint) + data.alloc_node(key, SmallVec::new(), fingerprint) }, hash_result::) } @@ -236,7 +236,7 @@ impl DepGraph { no_tcx: bool, task: fn(C, A) -> R, create_task: fn(DepNode) -> Option, - finish_task_and_alloc_depnode: fn(&Lock, + finish_task_and_alloc_depnode: fn(&CurrentDepGraph, DepNode, Fingerprint, Option) -> DepNodeIndex, @@ -350,7 +350,6 @@ impl DepGraph { (r, task_deps.into_inner()) }); let dep_node_index = data.current - .borrow_mut() .complete_anon_task(dep_kind, task_deps); (result, dep_node_index) } else { @@ -374,8 +373,7 @@ impl DepGraph { self.with_task_impl(key, cx, arg, false, task, |_| None, |data, key, fingerprint, _| { - let mut current = data.borrow_mut(); - current.alloc_node(key, smallvec![], fingerprint) + data.alloc_node(key, smallvec![], fingerprint) }, hash_result) } @@ -383,9 +381,9 @@ impl DepGraph { #[inline] pub fn read(&self, v: DepNode) { if let Some(ref data) = self.data { - let current = data.current.borrow_mut(); - if let Some(&dep_node_index) = current.node_to_node_index.get(&v) { - std::mem::drop(current); + let map = data.current.node_to_node_index.lock(); + if let Some(dep_node_index) = map.get(&v).copied() { + std::mem::drop(map); data.read_index(dep_node_index); } else { bug!("DepKind {:?} should be pre-allocated but isn't.", v.kind) @@ -406,8 +404,8 @@ impl DepGraph { .as_ref() .unwrap() .current - .borrow_mut() .node_to_node_index + .lock() .get(dep_node) .cloned() .unwrap() @@ -416,7 +414,7 @@ impl DepGraph { #[inline] pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { if let Some(ref data) = self.data { - data.current.borrow_mut().node_to_node_index.contains_key(dep_node) + data.current.node_to_node_index.lock().contains_key(dep_node) } else { false } @@ -424,8 +422,8 @@ impl DepGraph { #[inline] pub fn fingerprint_of(&self, dep_node_index: DepNodeIndex) -> Fingerprint { - let current = self.data.as_ref().expect("dep graph enabled").current.borrow_mut(); - current.data[dep_node_index].fingerprint + let data = self.data.as_ref().expect("dep graph enabled").current.data.lock(); + data[dep_node_index].fingerprint } pub fn prev_fingerprint_of(&self, dep_node: &DepNode) -> Option { @@ -479,32 +477,29 @@ impl DepGraph { pub fn edge_deduplication_data(&self) -> Option<(u64, u64)> { if cfg!(debug_assertions) { - let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); + let current_dep_graph = &self.data.as_ref().unwrap().current; - Some((current_dep_graph.total_read_count, - current_dep_graph.total_duplicate_read_count)) + Some((current_dep_graph.total_read_count.load(SeqCst), + current_dep_graph.total_duplicate_read_count.load(SeqCst))) } else { None } } pub fn serialize(&self) -> SerializedDepGraph { - let current_dep_graph = self.data.as_ref().unwrap().current.borrow(); + let data = self.data.as_ref().unwrap().current.data.lock(); let fingerprints: IndexVec = - current_dep_graph.data.iter().map(|d| d.fingerprint).collect(); + data.iter().map(|d| d.fingerprint).collect(); let nodes: IndexVec = - current_dep_graph.data.iter().map(|d| d.node).collect(); + data.iter().map(|d| d.node).collect(); - let total_edge_count: usize = current_dep_graph.data.iter() - .map(|d| d.edges.len()) - .sum(); + let total_edge_count: usize = data.iter().map(|d| d.edges.len()).sum(); let mut edge_list_indices = IndexVec::with_capacity(nodes.len()); let mut edge_list_data = Vec::with_capacity(total_edge_count); - for (current_dep_node_index, edges) in current_dep_graph.data.iter_enumerated() - .map(|(i, d)| (i, &d.edges)) { + for (current_dep_node_index, edges) in data.iter_enumerated().map(|(i, d)| (i, &d.edges)) { let start = edge_list_data.len() as u32; // This should really just be a memcpy :/ edge_list_data.extend(edges.iter().map(|i| SerializedDepNodeIndex::new(i.index()))); @@ -600,7 +595,7 @@ impl DepGraph { #[cfg(not(parallel_compiler))] { - debug_assert!(!data.current.borrow().node_to_node_index.contains_key(dep_node)); + debug_assert!(!data.current.node_to_node_index.lock().contains_key(dep_node)); debug_assert!(data.colors.get(prev_dep_node_index).is_none()); } @@ -733,15 +728,13 @@ impl DepGraph { // There may be multiple threads trying to mark the same dep node green concurrently let dep_node_index = { - let mut current = data.current.borrow_mut(); - // Copy the fingerprint from the previous graph, // so we don't have to recompute it let fingerprint = data.previous.fingerprint_by_index(prev_dep_node_index); // We allocating an entry for the node in the current dependency graph and // adding all the appropriate edges imported from the previous graph - current.intern_node(*dep_node, current_deps, fingerprint) + data.current.intern_node(*dep_node, current_deps, fingerprint) }; // ... emitting any stored diagnostic ... @@ -917,9 +910,27 @@ struct DepNodeData { fingerprint: Fingerprint, } +/// `CurrentDepGraph` stores the dependency graph for the current session. +/// It will be populated as we run queries or tasks. +/// +/// The nodes in it are identified by an index (`DepNodeIndex`). +/// The data for each node is stored in its `DepNodeData`, found in the `data` field. +/// +/// We never remove nodes from the graph: they are only added. +/// +/// This struct uses two locks internally. The `data` and `node_to_node_index` fields are +/// locked separately. Operations that take a `DepNodeIndex` typically just access +/// the data field. +/// +/// The only operation that must manipulate both locks is adding new nodes, in which case +/// we first acquire the `node_to_node_index` lock and then, once a new node is to be inserted, +/// acquire the lock on `data.` pub(super) struct CurrentDepGraph { - data: IndexVec, - node_to_node_index: FxHashMap, + data: Lock>, + node_to_node_index: Lock>, + + /// Used to trap when a specific edge is added to the graph. + /// This is used for debug purposes and is only active with `debug_assertions`. #[allow(dead_code)] forbidden_edge: Option, @@ -936,8 +947,10 @@ pub(super) struct CurrentDepGraph { /// the `DepGraph` is created. anon_id_seed: Fingerprint, - total_read_count: u64, - total_duplicate_read_count: u64, + /// These are simple counters that are for profiling and + /// debugging and only active with `debug_assertions`. + total_read_count: AtomicU64, + total_duplicate_read_count: AtomicU64, } impl CurrentDepGraph { @@ -971,20 +984,20 @@ impl CurrentDepGraph { let new_node_count_estimate = (prev_graph_node_count * 102) / 100 + 200; CurrentDepGraph { - data: IndexVec::with_capacity(new_node_count_estimate), - node_to_node_index: FxHashMap::with_capacity_and_hasher( + data: Lock::new(IndexVec::with_capacity(new_node_count_estimate)), + node_to_node_index: Lock::new(FxHashMap::with_capacity_and_hasher( new_node_count_estimate, Default::default(), - ), + )), anon_id_seed: stable_hasher.finish(), forbidden_edge, - total_read_count: 0, - total_duplicate_read_count: 0, + total_read_count: AtomicU64::new(0), + total_duplicate_read_count: AtomicU64::new(0), } } fn complete_task( - &mut self, + &self, node: DepNode, task_deps: TaskDeps, fingerprint: Fingerprint @@ -992,7 +1005,7 @@ impl CurrentDepGraph { self.alloc_node(node, task_deps.reads, fingerprint) } - fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex { + fn complete_anon_task(&self, kind: DepKind, task_deps: TaskDeps) -> DepNodeIndex { debug_assert!(!kind.is_eval_always()); let mut hasher = StableHasher::new(); @@ -1017,28 +1030,27 @@ impl CurrentDepGraph { } fn alloc_node( - &mut self, + &self, dep_node: DepNode, edges: SmallVec<[DepNodeIndex; 8]>, fingerprint: Fingerprint ) -> DepNodeIndex { - debug_assert!(!self.node_to_node_index.contains_key(&dep_node)); + debug_assert!(!self.node_to_node_index.lock().contains_key(&dep_node)); self.intern_node(dep_node, edges, fingerprint) } fn intern_node( - &mut self, + &self, dep_node: DepNode, edges: SmallVec<[DepNodeIndex; 8]>, fingerprint: Fingerprint ) -> DepNodeIndex { - debug_assert_eq!(self.node_to_node_index.len(), self.data.len()); - - match self.node_to_node_index.entry(dep_node) { + match self.node_to_node_index.lock().entry(dep_node) { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { - let dep_node_index = DepNodeIndex::new(self.data.len()); - self.data.push(DepNodeData { + let mut data = self.data.lock(); + let dep_node_index = DepNodeIndex::new(data.len()); + data.push(DepNodeData { node: dep_node, edges, fingerprint @@ -1057,7 +1069,7 @@ impl DepGraphData { if let Some(task_deps) = icx.task_deps { let mut task_deps = task_deps.lock(); if cfg!(debug_assertions) { - self.current.lock().total_read_count += 1; + self.current.total_read_count.fetch_add(1, SeqCst); } if task_deps.read_set.insert(source) { task_deps.reads.push(source); @@ -1065,9 +1077,9 @@ impl DepGraphData { #[cfg(debug_assertions)] { if let Some(target) = task_deps.node { - let graph = self.current.lock(); - if let Some(ref forbidden_edge) = graph.forbidden_edge { - let source = graph.data[source].node; + let data = self.current.data.lock(); + if let Some(ref forbidden_edge) = self.current.forbidden_edge { + let source = data[source].node; if forbidden_edge.test(&source, &target) { bug!("forbidden edge {:?} -> {:?} created", source, @@ -1077,7 +1089,7 @@ impl DepGraphData { } } } else if cfg!(debug_assertions) { - self.current.lock().total_duplicate_read_count += 1; + self.current.total_duplicate_read_count.fetch_add(1, SeqCst); } } }) From 8bf6d353772aacc15c78919e3d2f2db0528484b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 14 Oct 2019 14:48:45 -0700 Subject: [PATCH 380/545] Tweak heuristics for less noise --- src/librustc_errors/emitter.rs | 6 +++--- src/test/ui/consts/const-eval/const_fn_ptr.stderr | 2 +- src/test/ui/enable-unstable-lib-feature.stderr | 2 +- src/test/ui/lint/lint-lowercase-static-const-pattern.stderr | 2 +- src/test/ui/lint/lint-non-snake-case-functions.stderr | 4 ++-- src/test/ui/lint/lint-non-uppercase-associated-const.stderr | 2 +- src/test/ui/lint/not_found.stderr | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index d02201d5321c..84400091100e 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -2064,9 +2064,9 @@ pub fn is_case_difference(sm: &dyn SourceMapper, suggested: &str, sp: Span) -> b // FIXME: this should probably be extended to also account for `FO0` → `FOO` and unicode. let found = sm.span_to_snippet(sp).unwrap(); let ascii_confusables = &['c', 'f', 'i', 'k', 'o', 's', 'u', 'v', 'w', 'x', 'y', 'z']; - // There are ASCII chars that are confusable (above) and differ in capitalization: - let confusable = found.chars().zip(suggested.chars()).any(|(f, s)| { - (ascii_confusables.contains(&f) || ascii_confusables.contains(&s)) && f != s + // All the chars that differ in capitalization are confusable (above): + let confusable = found.chars().zip(suggested.chars()).filter(|(f, s)| f != s).all(|(f, s)| { + (ascii_confusables.contains(&f) || ascii_confusables.contains(&s)) }); confusable && found.to_lowercase() == suggested.to_lowercase() // FIXME: We sometimes suggest the same thing we already have, which is a diff --git a/src/test/ui/consts/const-eval/const_fn_ptr.stderr b/src/test/ui/consts/const-eval/const_fn_ptr.stderr index 9a5871905a05..2fbb19322442 100644 --- a/src/test/ui/consts/const-eval/const_fn_ptr.stderr +++ b/src/test/ui/consts/const-eval/const_fn_ptr.stderr @@ -20,7 +20,7 @@ warning: constant `X_const` should have an upper case name --> $DIR/const_fn_ptr.rs:9:7 | LL | const X_const: fn(usize) -> usize = double_const; - | ^^^^^^^ help: convert the identifier to upper case (notice the capitalization): `X_CONST` + | ^^^^^^^ help: convert the identifier to upper case: `X_CONST` | = note: `#[warn(non_upper_case_globals)]` on by default diff --git a/src/test/ui/enable-unstable-lib-feature.stderr b/src/test/ui/enable-unstable-lib-feature.stderr index d89f804f15bd..d5b8c0efaad3 100644 --- a/src/test/ui/enable-unstable-lib-feature.stderr +++ b/src/test/ui/enable-unstable-lib-feature.stderr @@ -2,7 +2,7 @@ error: function `BOGUS` should have a snake case name --> $DIR/enable-unstable-lib-feature.rs:11:8 | LL | pub fn BOGUS() { } - | ^^^^^ help: convert the identifier to snake case (notice the capitalization): `bogus` + | ^^^^^ help: convert the identifier to snake case: `bogus` | note: lint level defined here --> $DIR/enable-unstable-lib-feature.rs:6:9 diff --git a/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr b/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr index 40e5a736a8e5..d95510ccd2d2 100644 --- a/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr +++ b/src/test/ui/lint/lint-lowercase-static-const-pattern.stderr @@ -20,7 +20,7 @@ error: constant in pattern `not_okay` should have an upper case name --> $DIR/lint-lowercase-static-const-pattern.rs:40:13 | LL | (0, not_okay) => 0, - | ^^^^^^^^ help: convert the identifier to upper case (notice the capitalization): `NOT_OKAY` + | ^^^^^^^^ help: convert the identifier to upper case: `NOT_OKAY` error: aborting due to 3 previous errors diff --git a/src/test/ui/lint/lint-non-snake-case-functions.stderr b/src/test/ui/lint/lint-non-snake-case-functions.stderr index 244522acf1f8..c5eca89debb8 100644 --- a/src/test/ui/lint/lint-non-snake-case-functions.stderr +++ b/src/test/ui/lint/lint-non-snake-case-functions.stderr @@ -2,7 +2,7 @@ error: method `Foo_Method` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:7:8 | LL | fn Foo_Method() {} - | ^^^^^^^^^^ help: convert the identifier to snake case (notice the capitalization): `foo_method` + | ^^^^^^^^^^ help: convert the identifier to snake case: `foo_method` | note: lint level defined here --> $DIR/lint-non-snake-case-functions.rs:1:9 @@ -32,7 +32,7 @@ error: trait method `ABC` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:22:8 | LL | fn ABC(); - | ^^^ help: convert the identifier to snake case (notice the capitalization): `abc` + | ^^^ help: convert the identifier to snake case: `abc` error: trait method `a_b_C` should have a snake case name --> $DIR/lint-non-snake-case-functions.rs:25:8 diff --git a/src/test/ui/lint/lint-non-uppercase-associated-const.stderr b/src/test/ui/lint/lint-non-uppercase-associated-const.stderr index 233048ee1ddb..2185d5a0ab48 100644 --- a/src/test/ui/lint/lint-non-uppercase-associated-const.stderr +++ b/src/test/ui/lint/lint-non-uppercase-associated-const.stderr @@ -2,7 +2,7 @@ error: associated constant `not_upper` should have an upper case name --> $DIR/lint-non-uppercase-associated-const.rs:7:11 | LL | const not_upper: bool = true; - | ^^^^^^^^^ help: convert the identifier to upper case (notice the capitalization): `NOT_UPPER` + | ^^^^^^^^^ help: convert the identifier to upper case: `NOT_UPPER` | note: lint level defined here --> $DIR/lint-non-uppercase-associated-const.rs:1:9 diff --git a/src/test/ui/lint/not_found.stderr b/src/test/ui/lint/not_found.stderr index 8614e9f11733..5016d9b97d69 100644 --- a/src/test/ui/lint/not_found.stderr +++ b/src/test/ui/lint/not_found.stderr @@ -10,7 +10,7 @@ warning: unknown lint: `DEAD_CODE` --> $DIR/not_found.rs:8:8 | LL | #[warn(DEAD_CODE)] - | ^^^^^^^^^ help: did you mean (notice the capitalization): `dead_code` + | ^^^^^^^^^ help: did you mean: `dead_code` warning: unknown lint: `Warnings` --> $DIR/not_found.rs:10:8 From fe09bb518d9dfb270a6f3562b50b96272524b42c Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 10 Oct 2019 16:38:05 -0700 Subject: [PATCH 381/545] Add expanded type cache to OpaqueTypeExpander --- src/librustc/ty/util.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index d0e95a18c59f..35bd42fd7443 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -697,6 +697,9 @@ impl<'tcx> TyCtxt<'tcx> { // that type, and when we finish expanding that type we remove the // its DefId. seen_opaque_tys: FxHashSet, + // Cache of all expansions we've seen so far. This is a critical + // optimization for some large types produced by async fn trees. + expanded_cache: FxHashMap<(DefId, SubstsRef<'tcx>), Ty<'tcx>>, primary_def_id: DefId, found_recursion: bool, tcx: TyCtxt<'tcx>, @@ -713,9 +716,16 @@ impl<'tcx> TyCtxt<'tcx> { } let substs = substs.fold_with(self); if self.seen_opaque_tys.insert(def_id) { - let generic_ty = self.tcx.type_of(def_id); - let concrete_ty = generic_ty.subst(self.tcx, substs); - let expanded_ty = self.fold_ty(concrete_ty); + let expanded_ty = match self.expanded_cache.get(&(def_id, substs)) { + Some(expanded_ty) => expanded_ty, + None => { + let generic_ty = self.tcx.type_of(def_id); + let concrete_ty = generic_ty.subst(self.tcx, substs); + let expanded_ty = self.fold_ty(concrete_ty); + self.expanded_cache.insert((def_id, substs), expanded_ty); + expanded_ty + } + }; self.seen_opaque_tys.remove(&def_id); Some(expanded_ty) } else { @@ -743,6 +753,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut visitor = OpaqueTypeExpander { seen_opaque_tys: FxHashSet::default(), + expanded_cache: FxHashMap::default(), primary_def_id: def_id, found_recursion: false, tcx: self, From 802554f4274f6514cd2f8f618cae567adf18128f Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 10 Oct 2019 16:38:53 -0700 Subject: [PATCH 382/545] Only expand types that contain projections --- src/librustc/ty/util.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 35bd42fd7443..6a94ca6b8c75 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -745,8 +745,10 @@ 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 { + } else if t.has_projections() { t.super_fold_with(self) + } else { + t } } } From 57d33b155f31ca8c9d17371416d085c66ab4e61c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 5 Sep 2019 15:52:47 +1000 Subject: [PATCH 383/545] Remove custom `PartialEq` impls for `LocalInternedString`. This is on-trend with the recent changes simplifying `LocalInternedString` and reducing its use. --- src/libsyntax/feature_gate/check.rs | 2 +- src/libsyntax/parse/literal.rs | 2 +- src/libsyntax_pos/symbol.rs | 24 ------------------------ 3 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 9e40b1a26ac1..5f79050c5b8c 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -769,7 +769,7 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } if let Some(allowed) = allow_features.as_ref() { - if allowed.iter().find(|f| *f == name.as_str()).is_none() { + if allowed.iter().find(|&f| f == &name.as_str() as &str).is_none() { span_err!(span_handler, mi.span(), E0725, "the feature `{}` is not in the list of allowed features", name); diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index fcd5b2782fd6..95588d84f387 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -204,7 +204,7 @@ impl LitKind { let (kind, symbol, suffix) = match *self { LitKind::Str(symbol, ast::StrStyle::Cooked) => { // Don't re-intern unless the escaped string is different. - let s = &symbol.as_str(); + let s: &str = &symbol.as_str(); let escaped = s.escape_default().to_string(); let symbol = if escaped == *s { symbol } else { Symbol::intern(&escaped) }; (token::Str, symbol, None) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 2b005c3fc421..c57a933721f8 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1201,30 +1201,6 @@ impl> std::cmp::PartialEq for LocalInternedS } } -impl std::cmp::PartialEq for str { - fn eq(&self, other: &LocalInternedString) -> bool { - self == other.string - } -} - -impl<'a> std::cmp::PartialEq for &'a str { - fn eq(&self, other: &LocalInternedString) -> bool { - *self == other.string - } -} - -impl std::cmp::PartialEq for String { - fn eq(&self, other: &LocalInternedString) -> bool { - self == other.string - } -} - -impl<'a> std::cmp::PartialEq for &'a String { - fn eq(&self, other: &LocalInternedString) -> bool { - *self == other.string - } -} - impl !Send for LocalInternedString {} impl !Sync for LocalInternedString {} From 6c75e8156143da23a5cc0a3ec5facc8fe5a6e61e Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 15 Oct 2019 08:12:55 +0200 Subject: [PATCH 384/545] Refactor: Rename `db` locals to `diag` https://github.com/rust-lang/rust/pull/64272 replaced `DiagnosticBuilder` with `Diagnostic` in some places. This commit just renames the DB variable from `db` to `diag` where it wasn't renamed. --- src/librustc_codegen_ssa/back/write.rs | 10 +++---- .../annotate_snippet_emitter_writer.rs | 14 ++++----- src/librustc_errors/emitter.rs | 26 ++++++++-------- src/libsyntax/json.rs | 30 +++++++++---------- 4 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index ef3b115890f8..5339134a2a84 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -1667,13 +1667,13 @@ impl SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic(&mut self, db: &rustc_errors::Diagnostic) { + fn emit_diagnostic(&mut self, diag: &rustc_errors::Diagnostic) { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - msg: db.message(), - code: db.code.clone(), - lvl: db.level, + msg: diag.message(), + code: diag.code.clone(), + lvl: diag.level, }))); - for child in &db.children { + for child in &diag.children { drop(self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { msg: child.message(), code: None, diff --git a/src/librustc_errors/annotate_snippet_emitter_writer.rs b/src/librustc_errors/annotate_snippet_emitter_writer.rs index 16a1a28cd3a8..491bc2aa6a2e 100644 --- a/src/librustc_errors/annotate_snippet_emitter_writer.rs +++ b/src/librustc_errors/annotate_snippet_emitter_writer.rs @@ -31,19 +31,19 @@ pub struct AnnotateSnippetEmitterWriter { impl Emitter for AnnotateSnippetEmitterWriter { /// The entry point for the diagnostics generation - fn emit_diagnostic(&mut self, db: &Diagnostic) { - let mut children = db.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&db); + fn emit_diagnostic(&mut self, diag: &Diagnostic) { + let mut children = diag.children.clone(); + let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); self.fix_multispans_in_std_macros(&self.source_map, &mut primary_span, &mut children, - &db.level, + &diag.level, self.external_macro_backtrace); - self.emit_messages_default(&db.level, - db.message(), - &db.code, + self.emit_messages_default(&diag.level, + diag.message(), + &diag.code, &primary_span, &children, &suggestions); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 84400091100e..1e486786f686 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -180,7 +180,7 @@ const ANONYMIZED_LINE_NUM: &str = "LL"; /// Emitter trait for emitting errors. pub trait Emitter { /// Emit a structured diagnostic. - fn emit_diagnostic(&mut self, db: &Diagnostic); + fn emit_diagnostic(&mut self, diag: &Diagnostic); /// Emit a notification that an artifact has been output. /// This is currently only supported for the JSON format, @@ -206,10 +206,10 @@ pub trait Emitter { /// we return the original `primary_span` and the original suggestions. fn primary_span_formatted<'a>( &mut self, - db: &'a Diagnostic, + diag: &'a Diagnostic, ) -> (MultiSpan, &'a [CodeSuggestion]) { - let mut primary_span = db.span.clone(); - if let Some((sugg, rest)) = db.suggestions.split_first() { + let mut primary_span = diag.span.clone(); + if let Some((sugg, rest)) = diag.suggestions.split_first() { if rest.is_empty() && // ^ if there is only one suggestion // don't display multi-suggestions as labels @@ -260,10 +260,10 @@ pub trait Emitter { // to be consistent. We could try to figure out if we can // make one (or the first one) inline, but that would give // undue importance to a semi-random suggestion - (primary_span, &db.suggestions) + (primary_span, &diag.suggestions) } } else { - (primary_span, &db.suggestions) + (primary_span, &diag.suggestions) } } @@ -401,19 +401,19 @@ impl Emitter for EmitterWriter { self.sm.as_ref() } - fn emit_diagnostic(&mut self, db: &Diagnostic) { - let mut children = db.children.clone(); - let (mut primary_span, suggestions) = self.primary_span_formatted(&db); + fn emit_diagnostic(&mut self, diag: &Diagnostic) { + let mut children = diag.children.clone(); + let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); self.fix_multispans_in_std_macros(&self.sm, &mut primary_span, &mut children, - &db.level, + &diag.level, self.external_macro_backtrace); - self.emit_messages_default(&db.level, - &db.styled_message(), - &db.code, + self.emit_messages_default(&diag.level, + &diag.styled_message(), + &diag.code, &primary_span, &children, &suggestions); diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 4cf987417b8e..e3296788d9fa 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -89,8 +89,8 @@ impl JsonEmitter { } impl Emitter for JsonEmitter { - fn emit_diagnostic(&mut self, db: &errors::Diagnostic) { - let data = Diagnostic::from_errors_diagnostic(db, self); + fn emit_diagnostic(&mut self, diag: &errors::Diagnostic) { + let data = Diagnostic::from_errors_diagnostic(diag, self); let result = if self.pretty { writeln!(&mut self.dst, "{}", as_pretty_json(&data)) } else { @@ -209,10 +209,10 @@ struct ArtifactNotification<'a> { } impl Diagnostic { - fn from_errors_diagnostic(db: &errors::Diagnostic, + fn from_errors_diagnostic(diag: &errors::Diagnostic, je: &JsonEmitter) -> Diagnostic { - let sugg = db.suggestions.iter().map(|sugg| { + let sugg = diag.suggestions.iter().map(|sugg| { Diagnostic { message: sugg.msg.clone(), code: None, @@ -241,30 +241,30 @@ impl Diagnostic { let output = buf.clone(); je.json_rendered.new_emitter( Box::new(buf), Some(je.sm.clone()), false, None, je.external_macro_backtrace - ).ui_testing(je.ui_testing).emit_diagnostic(db); + ).ui_testing(je.ui_testing).emit_diagnostic(diag); let output = Arc::try_unwrap(output.0).unwrap().into_inner().unwrap(); let output = String::from_utf8(output).unwrap(); Diagnostic { - message: db.message(), - code: DiagnosticCode::map_opt_string(db.code.clone(), je), - level: db.level.to_str(), - spans: DiagnosticSpan::from_multispan(&db.span, je), - children: db.children.iter().map(|c| { + message: diag.message(), + code: DiagnosticCode::map_opt_string(diag.code.clone(), je), + level: diag.level.to_str(), + spans: DiagnosticSpan::from_multispan(&diag.span, je), + children: diag.children.iter().map(|c| { Diagnostic::from_sub_diagnostic(c, je) }).chain(sugg).collect(), rendered: Some(output), } } - fn from_sub_diagnostic(db: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic { + fn from_sub_diagnostic(diag: &SubDiagnostic, je: &JsonEmitter) -> Diagnostic { Diagnostic { - message: db.message(), + message: diag.message(), code: None, - level: db.level.to_str(), - spans: db.render_span.as_ref() + level: diag.level.to_str(), + spans: diag.render_span.as_ref() .map(|sp| DiagnosticSpan::from_multispan(sp, je)) - .unwrap_or_else(|| DiagnosticSpan::from_multispan(&db.span, je)), + .unwrap_or_else(|| DiagnosticSpan::from_multispan(&diag.span, je)), children: vec![], rendered: None, } From b39e188dda7a690f560c8beb0ae0b34982b993d8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 31 Aug 2019 15:22:53 +0300 Subject: [PATCH 385/545] Stabilize proc macros generating `macro_rules` items --- src/librustc/lib.rs | 2 +- src/libsyntax/ext/expand.rs | 49 ++----------------- src/libsyntax_pos/lib.rs | 2 +- src/test/ui/macros/same-sequence-span.rs | 1 - src/test/ui/macros/same-sequence-span.stderr | 8 +-- .../ui/proc-macro/auxiliary/more-gates.rs | 35 ------------- src/test/ui/proc-macro/more-gates.rs | 22 --------- src/test/ui/proc-macro/more-gates.stderr | 48 ------------------ 8 files changed, 10 insertions(+), 157 deletions(-) delete mode 100644 src/test/ui/proc-macro/auxiliary/more-gates.rs delete mode 100644 src/test/ui/proc-macro/more-gates.rs delete mode 100644 src/test/ui/proc-macro/more-gates.stderr diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 197ca191a5d0..8943fc342c02 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -56,7 +56,7 @@ #![feature(test)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] -#![feature(proc_macro_hygiene)] +#![cfg_attr(bootstrap, feature(proc_macro_hygiene))] #![feature(log_syntax)] #![feature(associated_type_bounds)] #![feature(rustc_attrs)] diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 9fcd918cef17..2559e8747627 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -10,14 +10,14 @@ use crate::ext::mbe::macro_rules::annotate_err_with_kind; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; use crate::mut_visit::*; -use crate::parse::{DirectoryOwnership, PResult, ParseSess}; +use crate::parse::{DirectoryOwnership, PResult}; use crate::parse::token; use crate::parse::parser::Parser; use crate::print::pprust; use crate::ptr::P; use crate::symbol::{sym, Symbol}; use crate::tokenstream::{TokenStream, TokenTree}; -use crate::visit::{self, Visitor}; +use crate::visit::Visitor; use crate::util::map_in_place::MapInPlace; use errors::{Applicability, FatalError}; @@ -577,10 +577,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::Bang(expander) => { self.gate_proc_macro_expansion_kind(span, fragment_kind); let tok_result = expander.expand(self.cx, span, mac.stream()); - let result = - self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span); - self.gate_proc_macro_expansion(span, &result); - result + self.parse_ast_fragment(tok_result, fragment_kind, &mac.path, span) } SyntaxExtensionKind::LegacyBang(expander) => { let prev = self.cx.current_expansion.prior_type_ascription; @@ -624,10 +621,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { })), DUMMY_SP).into(); let input = self.extract_proc_macro_attr_input(attr.item.tokens, span); let tok_result = expander.expand(self.cx, span, input, item_tok); - let res = - self.parse_ast_fragment(tok_result, fragment_kind, &attr.item.path, span); - self.gate_proc_macro_expansion(span, &res); - res + self.parse_ast_fragment(tok_result, fragment_kind, &attr.item.path, span) } SyntaxExtensionKind::LegacyAttr(expander) => { match attr.parse_meta(self.cx.parse_sess) { @@ -718,41 +712,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ); } - fn gate_proc_macro_expansion(&self, span: Span, fragment: &AstFragment) { - if self.cx.ecfg.proc_macro_hygiene() { - return - } - - fragment.visit_with(&mut DisallowMacros { - span, - parse_sess: self.cx.parse_sess, - }); - - struct DisallowMacros<'a> { - span: Span, - parse_sess: &'a ParseSess, - } - - impl<'ast, 'a> Visitor<'ast> for DisallowMacros<'a> { - fn visit_item(&mut self, i: &'ast ast::Item) { - if let ast::ItemKind::MacroDef(_) = i.kind { - emit_feature_err( - self.parse_sess, - sym::proc_macro_hygiene, - self.span, - GateIssue::Language, - "procedural macros cannot expand to macro definitions", - ); - } - visit::walk_item(self, i); - } - - fn visit_mac(&mut self, _mac: &'ast ast::Mac) { - // ... - } - } - } - fn gate_proc_macro_expansion_kind(&self, span: Span, kind: AstFragmentKind) { let kind = match kind { AstFragmentKind::Expr | diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 30ee9b90515e..7f7c5cb2e454 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -12,7 +12,7 @@ #![feature(non_exhaustive)] #![feature(optin_builtin_traits)] #![feature(rustc_attrs)] -#![feature(proc_macro_hygiene)] +#![cfg_attr(bootstrap, feature(proc_macro_hygiene))] #![feature(specialization)] #![feature(step_trait)] diff --git a/src/test/ui/macros/same-sequence-span.rs b/src/test/ui/macros/same-sequence-span.rs index a4f70b6b68d1..e0bb4d98525b 100644 --- a/src/test/ui/macros/same-sequence-span.rs +++ b/src/test/ui/macros/same-sequence-span.rs @@ -4,7 +4,6 @@ // left-hand side of a macro definition behave as if they had unique spans, and in particular that // they don't crash the compiler. -#![feature(proc_macro_hygiene)] #![allow(unused_macros)] extern crate proc_macro_sequence; diff --git a/src/test/ui/macros/same-sequence-span.stderr b/src/test/ui/macros/same-sequence-span.stderr index 0eef4a2a678b..896f579765f9 100644 --- a/src/test/ui/macros/same-sequence-span.stderr +++ b/src/test/ui/macros/same-sequence-span.stderr @@ -1,5 +1,5 @@ error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments - --> $DIR/same-sequence-span.rs:15:18 + --> $DIR/same-sequence-span.rs:14:18 | LL | (1 $x:expr $($y:tt,)* | ^^^^^ not allowed after `expr` fragments @@ -7,7 +7,7 @@ LL | (1 $x:expr $($y:tt,)* = note: allowed there are: `=>`, `,` or `;` error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments - --> $DIR/same-sequence-span.rs:16:18 + --> $DIR/same-sequence-span.rs:15:18 | LL | $(= $z:tt)* | ^ not allowed after `expr` fragments @@ -15,7 +15,7 @@ LL | $(= $z:tt)* = note: allowed there are: `=>`, `,` or `;` error: `$x:expr` may be followed by `$y:tt`, which is not allowed for `expr` fragments - --> $DIR/same-sequence-span.rs:20:1 + --> $DIR/same-sequence-span.rs:19:1 | LL | proc_macro_sequence::make_foo!(); | ^-------------------------------- @@ -30,7 +30,7 @@ LL | | fn main() {} = note: allowed there are: `=>`, `,` or `;` error: `$x:expr` may be followed by `=`, which is not allowed for `expr` fragments - --> $DIR/same-sequence-span.rs:20:1 + --> $DIR/same-sequence-span.rs:19:1 | LL | proc_macro_sequence::make_foo!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/proc-macro/auxiliary/more-gates.rs b/src/test/ui/proc-macro/auxiliary/more-gates.rs deleted file mode 100644 index 6b609eaee129..000000000000 --- a/src/test/ui/proc-macro/auxiliary/more-gates.rs +++ /dev/null @@ -1,35 +0,0 @@ -// force-host -// no-prefer-dynamic - -#![crate_type = "proc-macro"] - -extern crate proc_macro; - -use proc_macro::*; - -#[proc_macro_attribute] -pub fn attr2mac1(_: TokenStream, _: TokenStream) -> TokenStream { - "macro_rules! foo1 { (a) => (a) }".parse().unwrap() -} - -#[proc_macro_attribute] -pub fn attr2mac2(_: TokenStream, _: TokenStream) -> TokenStream { - "macro foo2(a) { a }".parse().unwrap() -} - -#[proc_macro] -pub fn mac2mac1(_: TokenStream) -> TokenStream { - "macro_rules! foo3 { (a) => (a) }".parse().unwrap() -} - -#[proc_macro] -pub fn mac2mac2(_: TokenStream) -> TokenStream { - "macro foo4(a) { a }".parse().unwrap() -} - -#[proc_macro] -pub fn tricky(_: TokenStream) -> TokenStream { - "fn foo() { - macro_rules! foo { (a) => (a) } - }".parse().unwrap() -} diff --git a/src/test/ui/proc-macro/more-gates.rs b/src/test/ui/proc-macro/more-gates.rs deleted file mode 100644 index b870b438a654..000000000000 --- a/src/test/ui/proc-macro/more-gates.rs +++ /dev/null @@ -1,22 +0,0 @@ -// aux-build:more-gates.rs - -#![feature(decl_macro)] - -extern crate more_gates as foo; - -use foo::*; - -#[attr2mac1] -//~^ ERROR: cannot expand to macro definitions -pub fn a() {} -#[attr2mac2] -//~^ ERROR: cannot expand to macro definitions -pub fn a() {} - -mac2mac1!(); //~ ERROR: cannot expand to macro definitions -mac2mac2!(); //~ ERROR: cannot expand to macro definitions - -tricky!(); -//~^ ERROR: cannot expand to macro definitions - -fn main() {} diff --git a/src/test/ui/proc-macro/more-gates.stderr b/src/test/ui/proc-macro/more-gates.stderr deleted file mode 100644 index ad96f78c77ad..000000000000 --- a/src/test/ui/proc-macro/more-gates.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error[E0658]: procedural macros cannot expand to macro definitions - --> $DIR/more-gates.rs:9:1 - | -LL | #[attr2mac1] - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/54727 - = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable - -error[E0658]: procedural macros cannot expand to macro definitions - --> $DIR/more-gates.rs:12:1 - | -LL | #[attr2mac2] - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/54727 - = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable - -error[E0658]: procedural macros cannot expand to macro definitions - --> $DIR/more-gates.rs:16:1 - | -LL | mac2mac1!(); - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/54727 - = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable - -error[E0658]: procedural macros cannot expand to macro definitions - --> $DIR/more-gates.rs:17:1 - | -LL | mac2mac2!(); - | ^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/54727 - = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable - -error[E0658]: procedural macros cannot expand to macro definitions - --> $DIR/more-gates.rs:19:1 - | -LL | tricky!(); - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/54727 - = help: add `#![feature(proc_macro_hygiene)]` to the crate attributes to enable - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0658`. From d80be3b4ff49583d94dea89b1b9bd06a013f43d6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 22 Sep 2019 16:35:28 +0300 Subject: [PATCH 386/545] Test basic hygiene for `macro_rules` produced by transparent macros --- .../auxiliary/gen-macro-rules-hygiene.rs | 23 +++++++++++++++ .../ui/proc-macro/gen-macro-rules-hygiene.rs | 23 +++++++++++++++ .../proc-macro/gen-macro-rules-hygiene.stderr | 28 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs create mode 100644 src/test/ui/proc-macro/gen-macro-rules-hygiene.rs create mode 100644 src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr diff --git a/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs new file mode 100644 index 000000000000..548fefe76f57 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/gen-macro-rules-hygiene.rs @@ -0,0 +1,23 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn gen_macro_rules(_: TokenStream) -> TokenStream { + " + macro_rules! generated {() => { + struct ItemDef; + let local_def = 0; + + ItemUse; // OK + local_use; // ERROR + break 'label_use; // ERROR + + type DollarCrate = $crate::ItemUse; // OK + }} + ".parse().unwrap() +} diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs b/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs new file mode 100644 index 000000000000..195bda82e9ce --- /dev/null +++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.rs @@ -0,0 +1,23 @@ +// `macro_rules` items produced by transparent macros have correct hygiene in basic cases. +// Local variables and labels are hygienic, items are not hygienic. +// `$crate` refers to the crate that defines `macro_rules` and not the outer transparent macro. + +// aux-build:gen-macro-rules-hygiene.rs + +#[macro_use] +extern crate gen_macro_rules_hygiene; + +struct ItemUse; + +gen_macro_rules!(); +//~^ ERROR use of undeclared label `'label_use` +//~| ERROR cannot find value `local_use` in this scope + +fn main() { + 'label_use: loop { + let local_use = 1; + generated!(); + ItemDef; // OK + local_def; //~ ERROR cannot find value `local_def` in this scope + } +} diff --git a/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr new file mode 100644 index 000000000000..ecebdfa96566 --- /dev/null +++ b/src/test/ui/proc-macro/gen-macro-rules-hygiene.stderr @@ -0,0 +1,28 @@ +error[E0426]: use of undeclared label `'label_use` + --> $DIR/gen-macro-rules-hygiene.rs:12:1 + | +LL | gen_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^^ undeclared label `'label_use` +... +LL | generated!(); + | ------------- in this macro invocation + +error[E0425]: cannot find value `local_use` in this scope + --> $DIR/gen-macro-rules-hygiene.rs:12:1 + | +LL | gen_macro_rules!(); + | ^^^^^^^^^^^^^^^^^^^ not found in this scope +... +LL | generated!(); + | ------------- in this macro invocation + +error[E0425]: cannot find value `local_def` in this scope + --> $DIR/gen-macro-rules-hygiene.rs:21:9 + | +LL | local_def; + | ^^^^^^^^^ not found in this scope + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0425, E0426. +For more information about an error, try `rustc --explain E0425`. From c29fe81ec42a89a5aadd8496855dc7dc43be7668 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 10:27:32 +0200 Subject: [PATCH 387/545] move maybe_report_invalid_custom_discriminants to feature_gate --- src/libsyntax/feature_gate/check.rs | 50 ++++++++++++++++++++++++-- src/libsyntax/parse/diagnostics.rs | 55 ++--------------------------- 2 files changed, 50 insertions(+), 55 deletions(-) diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 6008f8f3005b..2f6d98213e5b 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -5,14 +5,13 @@ use super::builtin_attrs::{AttributeGate, BUILTIN_ATTRIBUTE_MAP}; use crate::ast::{ self, AssocTyConstraint, AssocTyConstraintKind, NodeId, GenericParam, GenericParamKind, - PatKind, RangeEnd, + PatKind, RangeEnd, VariantData, }; use crate::attr::{self, check_builtin_attribute}; use crate::source_map::Spanned; use crate::edition::{ALL_EDITIONS, Edition}; use crate::visit::{self, FnKind, Visitor}; use crate::parse::{token, ParseSess}; -use crate::parse::parser::Parser; use crate::symbol::{Symbol, sym}; use crate::tokenstream::TokenTree; @@ -246,6 +245,51 @@ impl<'a> PostExpansionVisitor<'a> { Abi::System => {} } } + + fn maybe_report_invalid_custom_discriminants(&self, variants: &[ast::Variant]) { + let has_fields = variants.iter().any(|variant| match variant.data { + VariantData::Tuple(..) | VariantData::Struct(..) => true, + VariantData::Unit(..) => false, + }); + + let discriminant_spans = variants.iter().filter(|variant| match variant.data { + VariantData::Tuple(..) | VariantData::Struct(..) => false, + VariantData::Unit(..) => true, + }) + .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) + .collect::>(); + + if !discriminant_spans.is_empty() && has_fields { + let mut err = feature_err( + self.parse_sess, + sym::arbitrary_enum_discriminant, + discriminant_spans.clone(), + crate::feature_gate::GateIssue::Language, + "custom discriminant values are not allowed in enums with tuple or struct variants", + ); + for sp in discriminant_spans { + err.span_label(sp, "disallowed custom discriminant"); + } + for variant in variants.iter() { + match &variant.data { + VariantData::Struct(..) => { + err.span_label( + variant.span, + "struct variant defined here", + ); + } + VariantData::Tuple(..) => { + err.span_label( + variant.span, + "tuple variant defined here", + ); + } + VariantData::Unit(..) => {} + } + } + err.emit(); + } + } } impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { @@ -353,7 +397,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { let has_feature = self.features.arbitrary_enum_discriminant; if !has_feature && !i.span.allows_unstable(sym::arbitrary_enum_discriminant) { - Parser::maybe_report_invalid_custom_discriminants(self.parse_sess, &variants); + self.maybe_report_invalid_custom_discriminants(&variants); } } diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 0bbd67589ddd..943838d9dda7 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -1,9 +1,8 @@ use crate::ast::{ self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, - Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData, + Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, }; -use crate::feature_gate::feature_err; -use crate::parse::{SeqSep, PResult, Parser, ParseSess}; +use crate::parse::{SeqSep, PResult, Parser}; use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType}; use crate::parse::token::{self, TokenKind}; use crate::print::pprust; @@ -715,55 +714,7 @@ impl<'a> Parser<'a> { } } - crate fn maybe_report_invalid_custom_discriminants( - sess: &ParseSess, - variants: &[ast::Variant], - ) { - let has_fields = variants.iter().any(|variant| match variant.data { - VariantData::Tuple(..) | VariantData::Struct(..) => true, - VariantData::Unit(..) => false, - }); - - let discriminant_spans = variants.iter().filter(|variant| match variant.data { - VariantData::Tuple(..) | VariantData::Struct(..) => false, - VariantData::Unit(..) => true, - }) - .filter_map(|variant| variant.disr_expr.as_ref().map(|c| c.value.span)) - .collect::>(); - - if !discriminant_spans.is_empty() && has_fields { - let mut err = feature_err( - sess, - sym::arbitrary_enum_discriminant, - discriminant_spans.clone(), - crate::feature_gate::GateIssue::Language, - "custom discriminant values are not allowed in enums with tuple or struct variants", - ); - for sp in discriminant_spans { - err.span_label(sp, "disallowed custom discriminant"); - } - for variant in variants.iter() { - match &variant.data { - VariantData::Struct(..) => { - err.span_label( - variant.span, - "struct variant defined here", - ); - } - VariantData::Tuple(..) => { - err.span_label( - variant.span, - "tuple variant defined here", - ); - } - VariantData::Unit(..) => {} - } - } - err.emit(); - } - } - - crate fn maybe_recover_from_bad_type_plus( + pub(super) fn maybe_recover_from_bad_type_plus( &mut self, allow_plus: bool, ty: &Ty, From 52d0e86b9a46ab74f76c0bc7b2b9df3d32fcfbc1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 9 Oct 2019 03:23:10 +0200 Subject: [PATCH 388/545] syntax: extract sess.rs for ParseSess --- src/libsyntax/parse/mod.rs | 125 ++-------------------------------- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/parse/sess.rs | 124 +++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 119 deletions(-) create mode 100644 src/libsyntax/parse/sess.rs diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 0df695d37b94..53ba9b20690a 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1,26 +1,19 @@ //! The main parser interface. -use crate::ast::{self, CrateConfig, NodeId}; -use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; -use crate::source_map::{SourceMap, FilePathMapping}; -use crate::feature_gate::UnstableFeatures; +use crate::ast; use crate::parse::parser::{Parser, emit_unclosed_delims}; use crate::parse::token::{Nonterminal, TokenKind}; use crate::tokenstream::{self, TokenStream, TokenTree}; use crate::print::pprust; -use crate::symbol::Symbol; -use errors::{Applicability, FatalError, Level, Handler, ColorConfig, Diagnostic, DiagnosticBuilder}; -use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use errors::{FatalError, Level, Diagnostic, DiagnosticBuilder}; #[cfg(target_arch = "x86_64")] use rustc_data_structures::static_assert_size; -use rustc_data_structures::sync::{Lrc, Lock, Once}; -use syntax_pos::{Span, SourceFile, FileName, MultiSpan}; -use syntax_pos::edition::Edition; -use syntax_pos::hygiene::ExpnId; +use rustc_data_structures::sync::Lrc; +use syntax_pos::{Span, SourceFile, FileName}; use std::borrow::Cow; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::str; use log::info; @@ -33,6 +26,8 @@ pub mod parser; pub mod attr; pub mod lexer; pub mod token; +mod sess; +pub use sess::ParseSess; crate mod classify; crate mod diagnostics; @@ -46,112 +41,6 @@ pub type PResult<'a, T> = Result>; #[cfg(target_arch = "x86_64")] static_assert_size!(PResult<'_, bool>, 16); -/// Collected spans during parsing for places where a certain feature was -/// used and should be feature gated accordingly in `check_crate`. -#[derive(Default)] -pub struct GatedSpans { - /// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`. - pub let_chains: Lock>, - /// Spans collected for gating `async_closure`, e.g. `async || ..`. - pub async_closure: Lock>, - /// Spans collected for gating `yield e?` expressions (`generators` gate). - pub yields: Lock>, - /// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`. - pub or_patterns: Lock>, - /// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`. - pub const_extern_fn: Lock>, -} - -/// Info about a parsing session. -pub struct ParseSess { - pub span_diagnostic: Handler, - pub unstable_features: UnstableFeatures, - pub config: CrateConfig, - pub edition: Edition, - pub missing_fragment_specifiers: Lock>, - /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. - pub raw_identifier_spans: Lock>, - /// Used to determine and report recursive module inclusions. - included_mod_stack: Lock>, - source_map: Lrc, - pub buffered_lints: Lock>, - /// Contains the spans of block expressions that could have been incomplete based on the - /// operation token that followed it, but that the parser cannot identify without further - /// analysis. - pub ambiguous_block_expr_parse: Lock>, - pub injected_crate_name: Once, - pub gated_spans: GatedSpans, -} - -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) - } - - pub fn with_span_handler(handler: Handler, source_map: Lrc) -> Self { - Self { - span_diagnostic: handler, - unstable_features: UnstableFeatures::from_environment(), - config: FxHashSet::default(), - edition: ExpnId::root().expn_data().edition, - missing_fragment_specifiers: Lock::new(FxHashSet::default()), - raw_identifier_spans: Lock::new(Vec::new()), - included_mod_stack: Lock::new(vec![]), - source_map, - buffered_lints: Lock::new(vec![]), - ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), - injected_crate_name: Once::new(), - gated_spans: GatedSpans::default(), - } - } - - #[inline] - pub fn source_map(&self) -> &SourceMap { - &self.source_map - } - - pub fn buffer_lint>(&self, - lint_id: BufferedEarlyLintId, - span: S, - id: NodeId, - msg: &str, - ) { - self.buffered_lints.with_lock(|buffered_lints| { - buffered_lints.push(BufferedEarlyLint{ - span: span.into(), - id, - msg: msg.into(), - lint_id, - }); - }); - } - - /// 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( - &self, - err: &mut DiagnosticBuilder<'_>, - span: Span, - alt_snippet: Option, - ) { - if let Some(snippet) = self.source_map().span_to_snippet(span).ok().or(alt_snippet) { - err.span_suggestion( - span, - "parentheses are required to parse this as an expression", - format!("({})", snippet), - Applicability::MachineApplicable, - ); - } - } -} - #[derive(Clone)] pub struct Directory<'a> { pub path: Cow<'a, Path>, diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 478cfefc2247..2b9734798336 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1366,7 +1366,7 @@ impl<'a> Parser<'a> { ], Applicability::MaybeIncorrect, ).span_suggestion( - self.sess.source_map.next_point(self.prev_span), + self.sess.source_map().next_point(self.prev_span), "add a semicolon", ';'.to_string(), Applicability::MaybeIncorrect, diff --git a/src/libsyntax/parse/sess.rs b/src/libsyntax/parse/sess.rs new file mode 100644 index 000000000000..e49d3954f8e6 --- /dev/null +++ b/src/libsyntax/parse/sess.rs @@ -0,0 +1,124 @@ +//! Contains `ParseSess` which holds state living beyond what one `Parser` might. +//! It also serves as an input to the parser itself. + +use crate::ast::{CrateConfig, NodeId}; +use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; +use crate::source_map::{SourceMap, FilePathMapping}; +use crate::feature_gate::UnstableFeatures; + +use errors::{Applicability, Handler, ColorConfig, DiagnosticBuilder}; +use rustc_data_structures::fx::{FxHashSet, FxHashMap}; +use rustc_data_structures::sync::{Lrc, Lock, Once}; +use syntax_pos::{Symbol, Span, MultiSpan}; +use syntax_pos::edition::Edition; +use syntax_pos::hygiene::ExpnId; + +use std::path::PathBuf; +use std::str; + +/// Collected spans during parsing for places where a certain feature was +/// used and should be feature gated accordingly in `check_crate`. +#[derive(Default)] +crate struct GatedSpans { + /// Spans collected for gating `let_chains`, e.g. `if a && let b = c {}`. + crate let_chains: Lock>, + /// Spans collected for gating `async_closure`, e.g. `async || ..`. + crate async_closure: Lock>, + /// Spans collected for gating `yield e?` expressions (`generators` gate). + crate yields: Lock>, + /// Spans collected for gating `or_patterns`, e.g. `Some(Foo | Bar)`. + crate or_patterns: Lock>, + /// Spans collected for gating `const_extern_fn`, e.g. `const extern fn foo`. + crate const_extern_fn: Lock>, +} + +/// Info about a parsing session. +pub struct ParseSess { + pub span_diagnostic: Handler, + crate unstable_features: UnstableFeatures, + pub config: CrateConfig, + pub edition: Edition, + pub missing_fragment_specifiers: Lock>, + /// Places where raw identifiers were used. This is used for feature-gating raw identifiers. + pub raw_identifier_spans: Lock>, + /// Used to determine and report recursive module inclusions. + pub(super) included_mod_stack: Lock>, + source_map: Lrc, + pub buffered_lints: Lock>, + /// Contains the spans of block expressions that could have been incomplete based on the + /// operation token that followed it, but that the parser cannot identify without further + /// analysis. + pub ambiguous_block_expr_parse: Lock>, + pub injected_crate_name: Once, + crate gated_spans: GatedSpans, +} + +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) + } + + pub fn with_span_handler(handler: Handler, source_map: Lrc) -> Self { + Self { + span_diagnostic: handler, + unstable_features: UnstableFeatures::from_environment(), + config: FxHashSet::default(), + edition: ExpnId::root().expn_data().edition, + missing_fragment_specifiers: Lock::new(FxHashSet::default()), + raw_identifier_spans: Lock::new(Vec::new()), + included_mod_stack: Lock::new(vec![]), + source_map, + buffered_lints: Lock::new(vec![]), + ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), + injected_crate_name: Once::new(), + gated_spans: GatedSpans::default(), + } + } + + #[inline] + pub fn source_map(&self) -> &SourceMap { + &self.source_map + } + + pub fn buffer_lint( + &self, + lint_id: BufferedEarlyLintId, + span: impl Into, + id: NodeId, + msg: &str, + ) { + self.buffered_lints.with_lock(|buffered_lints| { + buffered_lints.push(BufferedEarlyLint{ + span: span.into(), + id, + msg: msg.into(), + lint_id, + }); + }); + } + + /// 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( + &self, + err: &mut DiagnosticBuilder<'_>, + span: Span, + alt_snippet: Option, + ) { + if let Some(snippet) = self.source_map().span_to_snippet(span).ok().or(alt_snippet) { + err.span_suggestion( + span, + "parentheses are required to parse this as an expression", + format!("({})", snippet), + Applicability::MachineApplicable, + ); + } + } +} From 79d02867b89ffabaf6db700e2eb63a3ef2610a97 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 11 Oct 2019 18:40:56 +0200 Subject: [PATCH 389/545] move parse_lit to expr.rs --- src/libsyntax/parse/literal.rs | 167 +--------------------------- src/libsyntax/parse/parser.rs | 8 +- src/libsyntax/parse/parser/expr.rs | 172 ++++++++++++++++++++++++++++- 3 files changed, 170 insertions(+), 177 deletions(-) diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 56a79bfe5d51..fbd409b0de4f 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -1,14 +1,10 @@ //! Code related to parsing literals. use crate::ast::{self, Lit, LitKind}; -use crate::parse::parser::Parser; -use crate::parse::PResult; -use crate::parse::token::{self, Token, TokenKind}; -use crate::print::pprust; +use crate::parse::token::{self, Token}; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{TokenStream, TokenTree}; -use errors::{Applicability, Handler}; use log::debug; use rustc_data_structures::sync::Lrc; use syntax_pos::Span; @@ -28,72 +24,6 @@ crate enum LitError { IntTooLarge, } -impl LitError { - fn report(&self, diag: &Handler, lit: token::Lit, span: Span) { - let token::Lit { kind, suffix, .. } = lit; - match *self { - // `NotLiteral` is not an error by itself, so we don't report - // it and give the parser opportunity to try something else. - LitError::NotLiteral => {} - // `LexerError` *is* an error, but it was already reported - // by lexer, so here we don't report it the second time. - LitError::LexerError => {} - LitError::InvalidSuffix => { - expect_no_suffix( - diag, span, &format!("{} {} literal", kind.article(), kind.descr()), suffix - ); - } - LitError::InvalidIntSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); - if looks_like_width_suffix(&['i', 'u'], &suf) { - // If it looks like a width, try to be helpful. - let msg = format!("invalid width `{}` for integer literal", &suf[1..]); - diag.struct_span_err(span, &msg) - .help("valid widths are 8, 16, 32, 64 and 128") - .emit(); - } else { - let msg = format!("invalid suffix `{}` for integer literal", suf); - diag.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{}`", suf)) - .help("the suffix must be one of the integral types (`u32`, `isize`, etc)") - .emit(); - } - } - LitError::InvalidFloatSuffix => { - let suf = suffix.expect("suffix error with no suffix").as_str(); - if looks_like_width_suffix(&['f'], &suf) { - // If it looks like a width, try to be helpful. - let msg = format!("invalid width `{}` for float literal", &suf[1..]); - diag.struct_span_err(span, &msg) - .help("valid widths are 32 and 64") - .emit(); - } else { - let msg = format!("invalid suffix `{}` for float literal", suf); - diag.struct_span_err(span, &msg) - .span_label(span, format!("invalid suffix `{}`", suf)) - .help("valid suffixes are `f32` and `f64`") - .emit(); - } - } - LitError::NonDecimalFloat(base) => { - let descr = match base { - 16 => "hexadecimal", - 8 => "octal", - 2 => "binary", - _ => unreachable!(), - }; - diag.struct_span_err(span, &format!("{} float literal is not supported", descr)) - .span_label(span, "not supported") - .emit(); - } - LitError::IntTooLarge => { - diag.struct_span_err(span, "integer literal is too large") - .emit(); - } - } - } -} - impl LitKind { /// Converts literal token into a semantic literal. fn from_lit_token(lit: token::Lit) -> Result { @@ -254,7 +184,7 @@ impl LitKind { impl Lit { /// Converts literal token into an AST literal. - fn from_lit_token(token: token::Lit, span: Span) -> Result { + crate fn from_lit_token(token: token::Lit, span: Span) -> Result { Ok(Lit { token, kind: LitKind::from_lit_token(token)?, span }) } @@ -296,99 +226,6 @@ impl Lit { } } -impl<'a> Parser<'a> { - /// Matches `lit = true | false | token_lit`. - crate fn parse_lit(&mut self) -> PResult<'a, Lit> { - let mut recovered = None; - if self.token == token::Dot { - // Attempt to recover `.4` as `0.4`. - recovered = self.look_ahead(1, |next_token| { - if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) - = next_token.kind { - if self.token.span.hi() == next_token.span.lo() { - let s = String::from("0.") + &symbol.as_str(); - let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); - return Some(Token::new(kind, self.token.span.to(next_token.span))); - } - } - None - }); - if let Some(token) = &recovered { - self.bump(); - self.diagnostic() - .struct_span_err(token.span, "float literals must have an integer part") - .span_suggestion( - token.span, - "must have an integer part", - pprust::token_to_string(token), - Applicability::MachineApplicable, - ) - .emit(); - } - } - - let token = recovered.as_ref().unwrap_or(&self.token); - match Lit::from_token(token) { - Ok(lit) => { - self.bump(); - Ok(lit) - } - Err(LitError::NotLiteral) => { - let msg = format!("unexpected token: {}", self.this_token_descr()); - Err(self.span_fatal(token.span, &msg)) - } - Err(err) => { - let (lit, span) = (token.expect_lit(), token.span); - self.bump(); - err.report(&self.sess.span_diagnostic, lit, span); - // Pack possible quotes and prefixes from the original literal into - // the error literal's symbol so they can be pretty-printed faithfully. - let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); - let symbol = Symbol::intern(&suffixless_lit.to_string()); - let lit = token::Lit::new(token::Err, symbol, lit.suffix); - Lit::from_lit_token(lit, span).map_err(|_| unreachable!()) - } - } - } -} - -crate fn expect_no_suffix(diag: &Handler, sp: Span, kind: &str, suffix: Option) { - if let Some(suf) = suffix { - let mut err = if kind == "a tuple index" && - [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) { - // #59553: warn instead of reject out of hand to allow the fix to percolate - // through the ecosystem when people fix their macros - let mut err = diag.struct_span_warn( - sp, - &format!("suffixes on {} are invalid", kind), - ); - err.note(&format!( - "`{}` is *temporarily* accepted on tuple index fields as it was \ - incorrectly accepted on stable for a few releases", - suf, - )); - err.help( - "on proc macros, you'll want to use `syn::Index::from` or \ - `proc_macro::Literal::*_unsuffixed` for code that will desugar \ - to tuple field access", - ); - err.note( - "for more context, see https://github.com/rust-lang/rust/issues/60210", - ); - err - } else { - diag.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) - }; - err.span_label(sp, format!("invalid suffix `{}`", suf)); - err.emit(); - } -} - -// Checks if `s` looks like i32 or u1234 etc. -fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { - s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) -} - fn strip_underscores(symbol: Symbol) -> Symbol { // Do not allocate a new string unless necessary. let s = symbol.as_str(); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2b9734798336..a3ac6d0c81f3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -15,10 +15,10 @@ use crate::ast::{ self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, }; -use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep, literal, token}; +use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep}; use crate::parse::lexer::UnmatchedBrace; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; -use crate::parse::token::{Token, TokenKind, DelimToken}; +use crate::parse::token::{self, Token, TokenKind, DelimToken}; use crate::print::pprust; use crate::ptr::P; use crate::source_map::respan; @@ -637,10 +637,6 @@ impl<'a> Parser<'a> { } } - fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { - literal::expect_no_suffix(&self.sess.span_diagnostic, sp, kind, suffix) - } - /// 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. diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 660bf9b7d65f..dd0fd834fb0c 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1,17 +1,17 @@ -use super::{ - Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode, SemiColonMode, - SeqSep, TokenExpectType, -}; +use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode}; +use super::{SemiColonMode, SeqSep, TokenExpectType}; use super::pat::{GateOr, PARAM_EXPECTED}; +use crate::parse::literal::LitError; + use crate::ast::{ self, DUMMY_NODE_ID, Attribute, AttrStyle, Ident, CaptureBy, BlockCheckMode, Expr, ExprKind, RangeLimits, Label, Movability, IsAsync, Arm, Ty, TyKind, - FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, + FunctionRetTy, Param, FnDecl, BinOpKind, BinOp, UnOp, Mac, AnonConst, Field, Lit, }; use crate::maybe_recover_from_interpolated_ty_qpath; use crate::parse::classify; -use crate::parse::token::{self, Token}; +use crate::parse::token::{self, Token, TokenKind}; use crate::parse::diagnostics::Error; use crate::print::pprust; use crate::ptr::P; @@ -20,6 +20,7 @@ use crate::symbol::{kw, sym}; use crate::util::parser::{AssocOp, Fixity, prec_let_scrutinee_needs_par}; use errors::Applicability; +use syntax_pos::Symbol; use std::mem; use rustc_data_structures::thin_vec::ThinVec; @@ -1072,6 +1073,165 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } + /// Matches `lit = true | false | token_lit`. + crate fn parse_lit(&mut self) -> PResult<'a, Lit> { + let mut recovered = None; + if self.token == token::Dot { + // Attempt to recover `.4` as `0.4`. + recovered = self.look_ahead(1, |next_token| { + if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) + = next_token.kind { + if self.token.span.hi() == next_token.span.lo() { + let s = String::from("0.") + &symbol.as_str(); + let kind = TokenKind::lit(token::Float, Symbol::intern(&s), suffix); + return Some(Token::new(kind, self.token.span.to(next_token.span))); + } + } + None + }); + if let Some(token) = &recovered { + self.bump(); + self.struct_span_err(token.span, "float literals must have an integer part") + .span_suggestion( + token.span, + "must have an integer part", + pprust::token_to_string(token), + Applicability::MachineApplicable, + ) + .emit(); + } + } + + let token = recovered.as_ref().unwrap_or(&self.token); + match Lit::from_token(token) { + Ok(lit) => { + self.bump(); + Ok(lit) + } + Err(LitError::NotLiteral) => { + let msg = format!("unexpected token: {}", self.this_token_descr()); + Err(self.span_fatal(token.span, &msg)) + } + Err(err) => { + let (lit, span) = (token.expect_lit(), token.span); + self.bump(); + self.error_literal_from_token(err, lit, span); + // Pack possible quotes and prefixes from the original literal into + // the error literal's symbol so they can be pretty-printed faithfully. + let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); + let symbol = Symbol::intern(&suffixless_lit.to_string()); + let lit = token::Lit::new(token::Err, symbol, lit.suffix); + Lit::from_lit_token(lit, span).map_err(|_| unreachable!()) + } + } + } + + fn error_literal_from_token(&self, err: LitError, lit: token::Lit, span: Span) { + // Checks if `s` looks like i32 or u1234 etc. + fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { + s.len() > 1 + && s.starts_with(first_chars) + && s[1..].chars().all(|c| c.is_ascii_digit()) + } + + let token::Lit { kind, suffix, .. } = lit; + match err { + // `NotLiteral` is not an error by itself, so we don't report + // it and give the parser opportunity to try something else. + LitError::NotLiteral => {} + // `LexerError` *is* an error, but it was already reported + // by lexer, so here we don't report it the second time. + LitError::LexerError => {} + LitError::InvalidSuffix => { + self.expect_no_suffix( + span, + &format!("{} {} literal", kind.article(), kind.descr()), + suffix, + ); + } + LitError::InvalidIntSuffix => { + let suf = suffix.expect("suffix error with no suffix").as_str(); + if looks_like_width_suffix(&['i', 'u'], &suf) { + // If it looks like a width, try to be helpful. + let msg = format!("invalid width `{}` for integer literal", &suf[1..]); + self.struct_span_err(span, &msg) + .help("valid widths are 8, 16, 32, 64 and 128") + .emit(); + } else { + let msg = format!("invalid suffix `{}` for integer literal", suf); + self.struct_span_err(span, &msg) + .span_label(span, format!("invalid suffix `{}`", suf)) + .help("the suffix must be one of the integral types (`u32`, `isize`, etc)") + .emit(); + } + } + LitError::InvalidFloatSuffix => { + let suf = suffix.expect("suffix error with no suffix").as_str(); + if looks_like_width_suffix(&['f'], &suf) { + // If it looks like a width, try to be helpful. + let msg = format!("invalid width `{}` for float literal", &suf[1..]); + self.struct_span_err(span, &msg) + .help("valid widths are 32 and 64") + .emit(); + } else { + let msg = format!("invalid suffix `{}` for float literal", suf); + self.struct_span_err(span, &msg) + .span_label(span, format!("invalid suffix `{}`", suf)) + .help("valid suffixes are `f32` and `f64`") + .emit(); + } + } + LitError::NonDecimalFloat(base) => { + let descr = match base { + 16 => "hexadecimal", + 8 => "octal", + 2 => "binary", + _ => unreachable!(), + }; + self.struct_span_err(span, &format!("{} float literal is not supported", descr)) + .span_label(span, "not supported") + .emit(); + } + LitError::IntTooLarge => { + self.struct_span_err(span, "integer literal is too large") + .emit(); + } + } + } + + pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option) { + if let Some(suf) = suffix { + let mut err = if kind == "a tuple index" + && [sym::i32, sym::u32, sym::isize, sym::usize].contains(&suf) + { + // #59553: warn instead of reject out of hand to allow the fix to percolate + // through the ecosystem when people fix their macros + let mut err = self.sess.span_diagnostic.struct_span_warn( + sp, + &format!("suffixes on {} are invalid", kind), + ); + err.note(&format!( + "`{}` is *temporarily* accepted on tuple index fields as it was \ + incorrectly accepted on stable for a few releases", + suf, + )); + err.help( + "on proc macros, you'll want to use `syn::Index::from` or \ + `proc_macro::Literal::*_unsuffixed` for code that will desugar \ + to tuple field access", + ); + err.note( + "for more context, see https://github.com/rust-lang/rust/issues/60210", + ); + err + } else { + self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind)) + }; + err.span_label(sp, format!("invalid suffix `{}`", suf)); + err.emit(); + } + } + /// Matches `'-' lit | lit` (cf. `ast_validation::AstValidator::check_expr_within_pat`). crate fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { maybe_whole_expr!(self); From ae156a56d4ae27e2fca8d51aa63d5322b500c91f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 14 Oct 2019 10:08:26 +0200 Subject: [PATCH 390/545] syntax::parse::sess -> syntax::sess --- src/librustc/hir/lowering.rs | 6 +++--- src/librustc/hir/print.rs | 2 +- src/librustc/session/config.rs | 3 ++- src/librustc/session/mod.rs | 4 ++-- src/librustdoc/clean/cfg.rs | 2 +- src/librustdoc/html/highlight.rs | 4 ++-- src/librustdoc/passes/check_code_block_syntax.rs | 3 ++- src/librustdoc/test.rs | 2 +- src/libsyntax/attr/builtin.rs | 2 +- src/libsyntax/attr/mod.rs | 3 ++- src/libsyntax/config.rs | 3 ++- src/libsyntax/ext/base.rs | 9 +++++---- src/libsyntax/ext/expand.rs | 3 ++- src/libsyntax/ext/mbe/macro_check.rs | 2 +- src/libsyntax/ext/mbe/macro_parser.rs | 3 ++- src/libsyntax/ext/mbe/macro_rules.rs | 3 ++- src/libsyntax/ext/mbe/quoted.rs | 2 +- src/libsyntax/ext/proc_macro_server.rs | 3 ++- src/libsyntax/feature_gate/builtin_attrs.rs | 2 +- src/libsyntax/feature_gate/check.rs | 3 ++- src/libsyntax/lib.rs | 1 + src/libsyntax/parse/lexer/mod.rs | 2 +- src/libsyntax/parse/mod.rs | 3 +-- src/libsyntax/parse/parser.rs | 3 ++- src/libsyntax/print/pprust.rs | 3 ++- src/libsyntax/{parse => }/sess.rs | 0 src/libsyntax/tests.rs | 3 ++- src/libsyntax_ext/cmdline_attrs.rs | 3 ++- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- src/libsyntax_ext/proc_macro_harness.rs | 2 +- src/libsyntax_ext/standard_library_imports.rs | 2 +- src/libsyntax_ext/test_harness.rs | 2 +- src/test/ui-fulldeps/ast_stmt_expr_attr.rs | 3 ++- src/test/ui-fulldeps/mod_dir_path_canonicalized.rs | 3 ++- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 4 ++-- 35 files changed, 58 insertions(+), 42 deletions(-) rename src/libsyntax/{parse => }/sess.rs (100%) diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 747848edc7a8..ab5a3c065103 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -67,11 +67,11 @@ use syntax::errors; use syntax::ext::base::SpecialDerives; use syntax::ext::hygiene::ExpnId; use syntax::print::pprust; -use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned}; -use syntax::symbol::{kw, sym, Symbol}; use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::{self, Nonterminal, Token}; -use syntax::parse::ParseSess; +use syntax::sess::ParseSess; +use syntax::source_map::{respan, ExpnData, ExpnKind, DesugaringKind, Spanned}; +use syntax::symbol::{kw, sym, Symbol}; use syntax::visit::{self, Visitor}; use syntax_pos::Span; diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 6cffaa8a494c..b852098d4cef 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -1,10 +1,10 @@ use rustc_target::spec::abi::Abi; use syntax::ast; use syntax::source_map::{SourceMap, Spanned}; -use syntax::parse::ParseSess; use syntax::print::pp::{self, Breaks}; use syntax::print::pp::Breaks::{Consistent, Inconsistent}; use syntax::print::pprust::{self, Comments, PrintState}; +use syntax::sess::ParseSess; use syntax::symbol::kw; use syntax::util::parser::{self, AssocOp, Fixity}; use syntax_pos::{self, BytePos, FileName}; diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 2517141542d5..675e3bbd002b 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -16,8 +16,9 @@ use syntax; use syntax::ast::{self, IntTy, UintTy, MetaItemKind}; use syntax::source_map::{FileName, FilePathMapping}; use syntax::edition::{Edition, EDITION_NAME_LIST, DEFAULT_EDITION}; -use syntax::parse::{ParseSess, new_parser_from_source_str}; +use syntax::parse::new_parser_from_source_str; use syntax::parse::token; +use syntax::sess::ParseSess; use syntax::symbol::{sym, Symbol}; use syntax::feature_gate::UnstableFeatures; use syntax::source_map::SourceMap; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index fa2902e4f0ed..c59df146629f 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -28,7 +28,7 @@ use syntax::ext::allocator::AllocatorKind; use syntax::feature_gate::{self, AttributeType}; use syntax::json::JsonEmitter; use syntax::source_map; -use syntax::parse::{self, ParseSess}; +use syntax::sess::ParseSess; use syntax::symbol::Symbol; use syntax_pos::{MultiSpan, Span}; use crate::util::profiling::{SelfProfiler, SelfProfilerRef}; @@ -1159,7 +1159,7 @@ fn build_session_( ); let target_cfg = config::build_target_config(&sopts, &span_diagnostic); - let parse_sess = parse::ParseSess::with_span_handler( + let parse_sess = ParseSess::with_span_handler( span_diagnostic, source_map, ); diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index da3b52afadff..706f52d03221 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -9,7 +9,7 @@ use std::ops; use syntax::symbol::{Symbol, sym}; use syntax::ast::{MetaItem, MetaItemKind, NestedMetaItem, LitKind}; -use syntax::parse::ParseSess; +use syntax::sess::ParseSess; use syntax::feature_gate::Features; use syntax_pos::Span; diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 5d86ee9721b7..30c9453a643d 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -14,7 +14,7 @@ use std::io::prelude::*; use syntax::source_map::{SourceMap, FilePathMapping}; use syntax::parse::lexer; use syntax::parse::token::{self, Token}; -use syntax::parse; +use syntax::sess::ParseSess; use syntax::symbol::{kw, sym}; use syntax_pos::{Span, FileName}; @@ -33,7 +33,7 @@ pub fn render_with_highlighting( class, tooltip).unwrap(); } - let sess = parse::ParseSess::new(FilePathMapping::empty()); + let sess = ParseSess::new(FilePathMapping::empty()); let fm = sess.source_map().new_source_file( FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned(), diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 32044e48b6f9..10e15ab8881a 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -1,6 +1,7 @@ use errors::Applicability; use syntax::parse::lexer::{StringReader as Lexer}; -use syntax::parse::{ParseSess, token}; +use syntax::parse::token; +use syntax::sess::ParseSess; use syntax::source_map::FilePathMapping; use syntax_pos::{InnerSpan, FileName}; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 05e6f36c9586..0be6340df96e 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -394,7 +394,7 @@ pub fn make_test(s: &str, // Uses libsyntax to parse the doctest and find if there's a main fn and the extern // crate already is included. let (already_has_main, already_has_extern_crate, found_macro) = with_globals(edition, || { - use crate::syntax::{parse::{self, ParseSess}, source_map::FilePathMapping}; + use crate::syntax::{parse, sess::ParseSess, source_map::FilePathMapping}; use errors::emitter::EmitterWriter; use errors::Handler; diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index efc48256e7ce..1fe698c2572c 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -4,8 +4,8 @@ use crate::ast::{self, Attribute, MetaItem, NestedMetaItem}; use crate::early_buffered_lints::BufferedEarlyLintId; use crate::ext::base::ExtCtxt; use crate::feature_gate::{Features, GatedCfg}; -use crate::parse::ParseSess; use crate::print::pprust; +use crate::sess::ParseSess; use errors::{Applicability, Handler}; use syntax_pos::hygiene::Transparency; diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index c2c883fd20e7..d291e502c255 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -16,9 +16,10 @@ use crate::mut_visit::visit_clobber; use crate::source_map::{BytePos, Spanned, DUMMY_SP}; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::parser::Parser; -use crate::parse::{ParseSess, PResult}; +use crate::parse::PResult; use crate::parse::token::{self, Token}; use crate::ptr::P; +use crate::sess::ParseSess; use crate::symbol::{sym, Symbol}; use crate::ThinVec; use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 2923cc86ba02..2099d018b7b3 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -10,8 +10,9 @@ use crate::attr; use crate::ast; use crate::edition::Edition; use crate::mut_visit::*; -use crate::parse::{token, ParseSess}; +use crate::parse::token; use crate::ptr::P; +use crate::sess::ParseSess; use crate::symbol::sym; use crate::util::map_in_place::MapInPlace; diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 583fb3f77018..01be5642d5c4 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -5,9 +5,10 @@ use crate::edition::Edition; use crate::ext::expand::{self, AstFragment, Invocation}; use crate::ext::hygiene::ExpnId; use crate::mut_visit::{self, MutVisitor}; -use crate::parse::{self, parser, ParseSess, DirectoryOwnership}; +use crate::parse::{self, parser, DirectoryOwnership}; use crate::parse::token; use crate::ptr::P; +use crate::sess::ParseSess; use crate::symbol::{kw, sym, Ident, Symbol}; use crate::{ThinVec, MACRO_ARGUMENTS}; use crate::tokenstream::{self, TokenStream}; @@ -892,7 +893,7 @@ pub struct ExpansionData { /// when a macro expansion occurs, the resulting nodes have the `backtrace() /// -> expn_data` of their expansion context stored into their span. pub struct ExtCtxt<'a> { - pub parse_sess: &'a parse::ParseSess, + pub parse_sess: &'a ParseSess, pub ecfg: expand::ExpansionConfig<'a>, pub root_path: PathBuf, pub resolver: &'a mut dyn Resolver, @@ -901,7 +902,7 @@ pub struct ExtCtxt<'a> { } impl<'a> ExtCtxt<'a> { - pub fn new(parse_sess: &'a parse::ParseSess, + pub fn new(parse_sess: &'a ParseSess, ecfg: expand::ExpansionConfig<'a>, resolver: &'a mut dyn Resolver) -> ExtCtxt<'a> { @@ -935,7 +936,7 @@ impl<'a> ExtCtxt<'a> { parse::stream_to_parser(self.parse_sess, stream, MACRO_ARGUMENTS) } pub fn source_map(&self) -> &'a SourceMap { self.parse_sess.source_map() } - pub fn parse_sess(&self) -> &'a parse::ParseSess { self.parse_sess } + pub fn parse_sess(&self) -> &'a ParseSess { self.parse_sess } pub fn cfg(&self) -> &ast::CrateConfig { &self.parse_sess.config } pub fn call_site(&self) -> Span { self.current_expansion.id.expn_data().call_site diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 9fcd918cef17..9ef59778f070 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -10,11 +10,12 @@ use crate::ext::mbe::macro_rules::annotate_err_with_kind; use crate::ext::placeholders::{placeholder, PlaceholderExpander}; use crate::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; use crate::mut_visit::*; -use crate::parse::{DirectoryOwnership, PResult, ParseSess}; +use crate::parse::{DirectoryOwnership, PResult}; use crate::parse::token; use crate::parse::parser::Parser; use crate::print::pprust; use crate::ptr::P; +use crate::sess::ParseSess; use crate::symbol::{sym, Symbol}; use crate::tokenstream::{TokenStream, TokenTree}; use crate::visit::{self, Visitor}; diff --git a/src/libsyntax/ext/mbe/macro_check.rs b/src/libsyntax/ext/mbe/macro_check.rs index 97074f5cbe46..aabaff4e1c30 100644 --- a/src/libsyntax/ext/mbe/macro_check.rs +++ b/src/libsyntax/ext/mbe/macro_check.rs @@ -109,7 +109,7 @@ use crate::early_buffered_lints::BufferedEarlyLintId; use crate::ext::mbe::{KleeneToken, TokenTree}; use crate::parse::token::TokenKind; use crate::parse::token::{DelimToken, Token}; -use crate::parse::ParseSess; +use crate::sess::ParseSess; use crate::symbol::{kw, sym}; use rustc_data_structures::fx::FxHashMap; diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax/ext/mbe/macro_parser.rs index 0cb5eff1ef29..ff382c316ffa 100644 --- a/src/libsyntax/ext/mbe/macro_parser.rs +++ b/src/libsyntax/ext/mbe/macro_parser.rs @@ -76,10 +76,11 @@ use TokenTreeOrTokenTreeSlice::*; use crate::ast::{Ident, Name}; use crate::ext::mbe::{self, TokenTree}; -use crate::parse::{Directory, ParseSess, PResult}; +use crate::parse::{Directory, PResult}; use crate::parse::parser::{Parser, PathStyle}; use crate::parse::token::{self, DocComment, Nonterminal, Token}; use crate::print::pprust; +use crate::sess::ParseSess; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream}; diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax/ext/mbe/macro_rules.rs index e4fc269d1479..b42232984226 100644 --- a/src/libsyntax/ext/mbe/macro_rules.rs +++ b/src/libsyntax/ext/mbe/macro_rules.rs @@ -14,8 +14,9 @@ use crate::feature_gate::Features; use crate::parse::parser::Parser; use crate::parse::token::TokenKind::*; use crate::parse::token::{self, NtTT, Token}; -use crate::parse::{Directory, ParseSess}; +use crate::parse::Directory; use crate::print::pprust; +use crate::sess::ParseSess; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax/ext/mbe/quoted.rs index 8cb85bdef762..3cec4bc60e7a 100644 --- a/src/libsyntax/ext/mbe/quoted.rs +++ b/src/libsyntax/ext/mbe/quoted.rs @@ -2,8 +2,8 @@ use crate::ast; use crate::ext::mbe::macro_parser; use crate::ext::mbe::{TokenTree, KleeneOp, KleeneToken, SequenceRepetition, Delimited}; use crate::parse::token::{self, Token}; -use crate::parse::ParseSess; use crate::print::pprust; +use crate::sess::ParseSess; use crate::symbol::kw; use crate::tokenstream; diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 08142ba6c58c..300523c1b0a4 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -1,8 +1,9 @@ use crate::ast; use crate::ext::base::ExtCtxt; -use crate::parse::{self, token, ParseSess}; +use crate::parse::{self, token}; use crate::parse::lexer::comments; use crate::print::pprust; +use crate::sess::ParseSess; use crate::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}; use errors::Diagnostic; diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index ab1620b95249..043a2ffb5a48 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -9,8 +9,8 @@ use super::active::Features; use crate::ast; use crate::attr::AttributeTemplate; +use crate::sess::ParseSess; use crate::symbol::{Symbol, sym}; -use crate::parse::ParseSess; use syntax_pos::Span; use rustc_data_structures::fx::FxHashMap; diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index 2f6d98213e5b..700ce26171a8 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -11,7 +11,8 @@ use crate::attr::{self, check_builtin_attribute}; use crate::source_map::Spanned; use crate::edition::{ALL_EDITIONS, Edition}; use crate::visit::{self, FnKind, Visitor}; -use crate::parse::{token, ParseSess}; +use crate::parse::token; +use crate::sess::ParseSess; use crate::symbol::{Symbol, sym}; use crate::tokenstream::TokenTree; diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 09a47795a822..fa75f5624f8f 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -147,6 +147,7 @@ pub mod ptr; pub mod show_span; pub use syntax_pos::edition; pub use syntax_pos::symbol; +pub mod sess; pub mod tokenstream; pub mod visit; diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index ac3feadce3ae..e6dc9a4c1341 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1,5 +1,5 @@ -use crate::parse::ParseSess; use crate::parse::token::{self, Token, TokenKind}; +use crate::sess::ParseSess; use crate::symbol::{sym, Symbol}; use crate::parse::unescape_error_reporting::{emit_unescape_error, push_escaped_char}; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 53ba9b20690a..cb90caab77a8 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -5,6 +5,7 @@ use crate::parse::parser::{Parser, emit_unclosed_delims}; use crate::parse::token::{Nonterminal, TokenKind}; use crate::tokenstream::{self, TokenStream, TokenTree}; use crate::print::pprust; +use crate::sess::ParseSess; use errors::{FatalError, Level, Diagnostic, DiagnosticBuilder}; #[cfg(target_arch = "x86_64")] @@ -26,8 +27,6 @@ pub mod parser; pub mod attr; pub mod lexer; pub mod token; -mod sess; -pub use sess::ParseSess; crate mod classify; crate mod diagnostics; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a3ac6d0c81f3..86383761484d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -15,12 +15,13 @@ use crate::ast::{ self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, }; -use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep}; +use crate::parse::{PResult, Directory, DirectoryOwnership, SeqSep}; use crate::parse::lexer::UnmatchedBrace; use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration}; use crate::parse::token::{self, Token, TokenKind, DelimToken}; use crate::print::pprust; use crate::ptr::P; +use crate::sess::ParseSess; use crate::source_map::respan; use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint}; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 68dd90b54ab6..136fc355f89d 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -6,10 +6,11 @@ use crate::attr; use crate::source_map::{self, SourceMap, Spanned}; use crate::parse::token::{self, BinOpToken, DelimToken, Nonterminal, Token, TokenKind}; use crate::parse::lexer::comments; -use crate::parse::{self, ParseSess}; +use crate::parse; use crate::print::pp::{self, Breaks}; use crate::print::pp::Breaks::{Consistent, Inconsistent}; use crate::ptr::P; +use crate::sess::ParseSess; use crate::symbol::{kw, sym}; use crate::tokenstream::{self, TokenStream, TokenTree}; diff --git a/src/libsyntax/parse/sess.rs b/src/libsyntax/sess.rs similarity index 100% rename from src/libsyntax/parse/sess.rs rename to src/libsyntax/sess.rs diff --git a/src/libsyntax/tests.rs b/src/libsyntax/tests.rs index f510ac9273d0..fbcf368ccb7b 100644 --- a/src/libsyntax/tests.rs +++ b/src/libsyntax/tests.rs @@ -1,7 +1,8 @@ use crate::{ast, panictry}; -use crate::parse::{ParseSess, PResult, source_file_to_stream}; +use crate::parse::{PResult, source_file_to_stream}; use crate::parse::new_parser_from_source_str; use crate::parse::parser::Parser; +use crate::sess::ParseSess; use crate::source_map::{SourceMap, FilePathMapping}; use crate::tokenstream::TokenStream; use crate::with_default_globals; diff --git a/src/libsyntax_ext/cmdline_attrs.rs b/src/libsyntax_ext/cmdline_attrs.rs index 203c4a834899..2c3159739e24 100644 --- a/src/libsyntax_ext/cmdline_attrs.rs +++ b/src/libsyntax_ext/cmdline_attrs.rs @@ -3,7 +3,8 @@ use syntax::ast::{self, AttrItem, AttrStyle}; use syntax::attr::mk_attr; use syntax::panictry; -use syntax::parse::{self, token, ParseSess}; +use syntax::parse::{self, token}; +use syntax::sess::ParseSess; use syntax_pos::FileName; pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index abdcb6c8e3d3..9c3ec06d59a3 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -190,8 +190,8 @@ use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives}; use syntax::source_map::respan; use syntax::util::map_in_place::MapInPlace; use syntax::ptr::P; +use syntax::sess::ParseSess; use syntax::symbol::{Symbol, kw, sym}; -use syntax::parse::ParseSess; use syntax_pos::{Span}; use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty}; diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 1d48e8231b40..1b7068818b01 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -6,9 +6,9 @@ use syntax::attr; use syntax::ext::base::ExtCtxt; use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::ext::proc_macro::is_proc_macro_attr; -use syntax::parse::ParseSess; use syntax::print::pprust; use syntax::ptr::P; +use syntax::sess::ParseSess; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs index c577b1e33cfe..4f17acf2d0f6 100644 --- a/src/libsyntax_ext/standard_library_imports.rs +++ b/src/libsyntax_ext/standard_library_imports.rs @@ -3,8 +3,8 @@ use syntax::edition::Edition; use syntax::ext::expand::ExpansionConfig; use syntax::ext::hygiene::AstPass; use syntax::ext::base::{ExtCtxt, Resolver}; -use syntax::parse::ParseSess; use syntax::ptr::P; +use syntax::sess::ParseSess; use syntax::symbol::{Ident, Symbol, kw, sym}; use syntax_pos::DUMMY_SP; diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index f79ad1419e0b..0bb279c0cb0d 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -10,8 +10,8 @@ use syntax::ext::base::{ExtCtxt, Resolver}; use syntax::ext::expand::{AstFragment, ExpansionConfig}; use syntax::feature_gate::Features; use syntax::mut_visit::{*, ExpectOne}; -use syntax::parse::ParseSess; use syntax::ptr::P; +use syntax::sess::ParseSess; use syntax::source_map::respan; use syntax::symbol::{sym, Symbol}; use syntax_pos::{Span, DUMMY_SP}; diff --git a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs b/src/test/ui-fulldeps/ast_stmt_expr_attr.rs index 6c5f539b8718..5479119d812f 100644 --- a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs +++ b/src/test/ui-fulldeps/ast_stmt_expr_attr.rs @@ -10,9 +10,10 @@ extern crate syntax; use syntax::ast::*; use syntax::attr::*; use syntax::ast; +use syntax::sess::ParseSess; use syntax::source_map::{FilePathMapping, FileName}; use syntax::parse; -use syntax::parse::{ParseSess, PResult}; +use syntax::parse::PResult; use syntax::parse::new_parser_from_source_str; use syntax::parse::parser::Parser; use syntax::parse::token; diff --git a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs index 8631bcca6d27..ac97ec70be20 100644 --- a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -7,8 +7,9 @@ extern crate syntax; use std::path::Path; +use syntax::sess::ParseSess; use syntax::source_map::FilePathMapping; -use syntax::parse::{self, ParseSess}; +use syntax::parse; #[path = "mod_dir_simple/test.rs"] mod gravy; diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index d4aff7359073..932a173bc67a 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -24,14 +24,14 @@ extern crate syntax; use rustc_data_structures::thin_vec::ThinVec; use syntax::ast::*; +use syntax::sess::ParseSess; use syntax::source_map::{Spanned, DUMMY_SP, FileName}; use syntax::source_map::FilePathMapping; use syntax::mut_visit::{self, MutVisitor, visit_clobber}; -use syntax::parse::{self, ParseSess}; +use syntax::parse; use syntax::print::pprust; use syntax::ptr::P; - fn parse_expr(ps: &ParseSess, src: &str) -> Option> { let src_as_string = src.to_string(); From 8370f14225cfb1a7f0eae8b8dadfaa4393e00d7c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 15 Oct 2019 11:57:06 +0200 Subject: [PATCH 391/545] Remove unnecessary `use crate::sess::ParseSess;`. --- src/libsyntax/ext/expand.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 6e0da7a49ee4..2559e8747627 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -15,7 +15,6 @@ use crate::parse::token; use crate::parse::parser::Parser; use crate::print::pprust; use crate::ptr::P; -use crate::sess::ParseSess; use crate::symbol::{sym, Symbol}; use crate::tokenstream::{TokenStream, TokenTree}; use crate::visit::Visitor; From 53187c5753e09006f0e03799ab01d7cb7ec676c7 Mon Sep 17 00:00:00 2001 From: phosphorus Date: Fri, 11 Oct 2019 20:16:09 +0800 Subject: [PATCH 392/545] Slides path lifetime to the lifetime resolver add test to for the fix add descriptive text for the fix simplified code logics update descriptive comments update to cope with the tidyness requirement merged commit suggestions Co-Authored-By: varkor truncated redundant comments update to cope with tidy-check --- src/librustc/hir/lowering.rs | 12 +++++++---- ...incorrect-explicit-lifetime-name-needed.rs | 14 +++++++++++++ ...rrect-explicit-lifetime-name-needed.stderr | 21 +++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs create mode 100644 src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 72fd054ee8a2..ecf16d944305 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -3281,10 +3281,14 @@ impl<'a> LoweringContext<'a> { let id = self.sess.next_node_id(); self.new_named_lifetime(id, span, hir::LifetimeName::Error) } - // This is the normal case. - AnonymousLifetimeMode::PassThrough => self.new_implicit_lifetime(span), - - AnonymousLifetimeMode::ReportError => self.new_error_lifetime(None, span), + // `PassThrough` is the normal case. + // `new_error_lifetime`, which would usually be used in the case of `ReportError`, + // is unsuitable here, as these can occur from missing lifetime parameters in a + // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit + // lifetime. Instead, we simply create an implicit lifetime, which will be checked + // later, at which point a suitable error will be emitted. + | AnonymousLifetimeMode::PassThrough + | AnonymousLifetimeMode::ReportError => self.new_implicit_lifetime(span), } } diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs new file mode 100644 index 000000000000..54b483f53d4c --- /dev/null +++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.rs @@ -0,0 +1,14 @@ +#![crate_type="lib"] + +struct Nested(K); + +fn should_error() where T : Into<&u32> {} +//~^ ERROR `&` without an explicit lifetime name cannot be used here [E0637] + +trait X<'a, K: 'a> { + fn foo<'b, L: X<&'b Nested>>(); + //~^ ERROR missing lifetime specifier [E0106] +} + +fn bar<'b, L: X<&'b Nested>>(){} +//~^ ERROR missing lifetime specifier [E0106] diff --git a/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr new file mode 100644 index 000000000000..8720288b53e5 --- /dev/null +++ b/src/test/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr @@ -0,0 +1,21 @@ +error[E0637]: `&` without an explicit lifetime name cannot be used here + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:37 + | +LL | fn should_error() where T : Into<&u32> {} + | ^ explicit lifetime name needed here + +error[E0106]: missing lifetime specifier + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:19 + | +LL | fn foo<'b, L: X<&'b Nested>>(); + | ^^^^^^^^^^^^^^^^ expected lifetime parameter + +error[E0106]: missing lifetime specifier + --> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:13:15 + | +LL | fn bar<'b, L: X<&'b Nested>>(){} + | ^^^^^^^^^^^^^^^^^^ expected lifetime parameter + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0106`. From 1fb8cfb4815f99148cd94182accc99866de9a6d8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 15 Oct 2019 15:28:42 +0200 Subject: [PATCH 393/545] Organize `never_type` tests Also move {run-fail -> ui}/never_type --- src/test/ui/coercion/coerce-issue-49593-box-never.rs | 2 +- .../ui/feature-gates/feature-gate-exhaustive-patterns.rs | 1 + .../feature-gates/feature-gate-exhaustive-patterns.stderr | 2 +- src/test/ui/for-loop-while/loop-break-value.rs | 1 + src/test/ui/lint/must_use-unit.rs | 1 - src/test/ui/lint/must_use-unit.stderr | 6 +++--- src/test/{run-fail => ui/never_type}/adjust_never.rs | 1 + .../ui/{ => never_type}/call-fn-never-arg-wrong-type.rs | 0 .../ui/{ => never_type}/call-fn-never-arg-wrong-type.stderr | 0 src/test/{run-fail => ui/never_type}/call-fn-never-arg.rs | 1 + src/test/{run-fail => ui/never_type}/cast-never.rs | 1 + src/test/ui/{ => never_type}/defaulted-never-note.rs | 0 src/test/ui/{ => never_type}/defaulted-never-note.stderr | 0 src/test/ui/{ => never_type}/dispatch_from_dyn_zst.rs | 0 .../ui/{ => never_type}/diverging-fallback-control-flow.rs | 1 + src/test/ui/{ => never_type}/impl-for-never.rs | 3 ++- src/test/ui/{issues => never_type}/issue-13352.rs | 0 src/test/ui/{issues => never_type}/issue-13352.stderr | 0 src/test/ui/{issues => never_type}/issue-2149.rs | 0 src/test/ui/{issues => never_type}/issue-2149.stderr | 0 src/test/ui/{issues => never_type}/issue-44402.rs | 3 ++- src/test/ui/{ => never_type}/never-assign-dead-code.rs | 6 +++--- src/test/ui/{ => never_type}/never-assign-dead-code.stderr | 4 ++-- src/test/ui/{ => never_type}/never-assign-wrong-type.rs | 0 src/test/ui/{ => never_type}/never-assign-wrong-type.stderr | 0 .../{run-fail => ui/never_type}/never-associated-type.rs | 1 + src/test/ui/{ => never_type}/never-from-impl-is-reserved.rs | 0 .../ui/{ => never_type}/never-from-impl-is-reserved.stderr | 0 src/test/ui/{ => never_type}/never-result.rs | 1 + src/test/{run-fail => ui/never_type}/never-type-arg.rs | 1 + src/test/ui/{ => never_type}/never-type-rvalues.rs | 0 src/test/ui/{ => never_type}/never_coercions.rs | 0 src/test/ui/{ => never_type}/never_transmute_never.rs | 2 +- src/test/ui/{ => never_type}/panic-uninitialized-zeroed.rs | 0 src/test/ui/{ => never_type}/try_from.rs | 0 .../auxiliary/unreachable_variant.rs | 0 src/test/ui/{unreachable => reachable}/unreachable-arm.rs | 0 .../ui/{unreachable => reachable}/unreachable-arm.stderr | 0 src/test/ui/{unreachable => reachable}/unreachable-code.rs | 0 .../ui/{unreachable => reachable}/unreachable-code.stderr | 0 .../ui/{unreachable => reachable}/unreachable-in-call.rs | 0 .../{unreachable => reachable}/unreachable-in-call.stderr | 0 .../{unreachable => reachable}/unreachable-loop-patterns.rs | 2 -- .../unreachable-loop-patterns.stderr | 6 +++--- .../{unreachable => reachable}/unreachable-try-pattern.rs | 2 +- .../unreachable-try-pattern.stderr | 0 .../ui/{unreachable => reachable}/unreachable-variant.rs | 0 .../{unreachable => reachable}/unreachable-variant.stderr | 0 .../{unreachable => reachable}/unwarned-match-on-never.rs | 0 .../unwarned-match-on-never.stderr | 0 src/test/ui/{ => uninhabited}/always-inhabited-union-ref.rs | 0 .../ui/{ => uninhabited}/always-inhabited-union-ref.stderr | 0 52 files changed, 28 insertions(+), 20 deletions(-) rename src/test/{run-fail => ui/never_type}/adjust_never.rs (93%) rename src/test/ui/{ => never_type}/call-fn-never-arg-wrong-type.rs (100%) rename src/test/ui/{ => never_type}/call-fn-never-arg-wrong-type.stderr (100%) rename src/test/{run-fail => ui/never_type}/call-fn-never-arg.rs (94%) rename src/test/{run-fail => ui/never_type}/cast-never.rs (93%) rename src/test/ui/{ => never_type}/defaulted-never-note.rs (100%) rename src/test/ui/{ => never_type}/defaulted-never-note.stderr (100%) rename src/test/ui/{ => never_type}/dispatch_from_dyn_zst.rs (100%) rename src/test/ui/{ => never_type}/diverging-fallback-control-flow.rs (99%) rename src/test/ui/{ => never_type}/impl-for-never.rs (99%) rename src/test/ui/{issues => never_type}/issue-13352.rs (100%) rename src/test/ui/{issues => never_type}/issue-13352.stderr (100%) rename src/test/ui/{issues => never_type}/issue-2149.rs (100%) rename src/test/ui/{issues => never_type}/issue-2149.stderr (100%) rename src/test/ui/{issues => never_type}/issue-44402.rs (90%) rename src/test/ui/{ => never_type}/never-assign-dead-code.rs (82%) rename src/test/ui/{ => never_type}/never-assign-dead-code.stderr (92%) rename src/test/ui/{ => never_type}/never-assign-wrong-type.rs (100%) rename src/test/ui/{ => never_type}/never-assign-wrong-type.stderr (100%) rename src/test/{run-fail => ui/never_type}/never-associated-type.rs (96%) rename src/test/ui/{ => never_type}/never-from-impl-is-reserved.rs (100%) rename src/test/ui/{ => never_type}/never-from-impl-is-reserved.stderr (100%) rename src/test/ui/{ => never_type}/never-result.rs (99%) rename src/test/{run-fail => ui/never_type}/never-type-arg.rs (95%) rename src/test/ui/{ => never_type}/never-type-rvalues.rs (100%) rename src/test/ui/{ => never_type}/never_coercions.rs (100%) rename src/test/ui/{ => never_type}/never_transmute_never.rs (87%) rename src/test/ui/{ => never_type}/panic-uninitialized-zeroed.rs (100%) rename src/test/ui/{ => never_type}/try_from.rs (100%) rename src/test/ui/{unreachable => reachable}/auxiliary/unreachable_variant.rs (100%) rename src/test/ui/{unreachable => reachable}/unreachable-arm.rs (100%) rename src/test/ui/{unreachable => reachable}/unreachable-arm.stderr (100%) rename src/test/ui/{unreachable => reachable}/unreachable-code.rs (100%) rename src/test/ui/{unreachable => reachable}/unreachable-code.stderr (100%) rename src/test/ui/{unreachable => reachable}/unreachable-in-call.rs (100%) rename src/test/ui/{unreachable => reachable}/unreachable-in-call.stderr (100%) rename src/test/ui/{unreachable => reachable}/unreachable-loop-patterns.rs (95%) rename src/test/ui/{unreachable => reachable}/unreachable-loop-patterns.stderr (73%) rename src/test/ui/{unreachable => reachable}/unreachable-try-pattern.rs (94%) rename src/test/ui/{unreachable => reachable}/unreachable-try-pattern.stderr (100%) rename src/test/ui/{unreachable => reachable}/unreachable-variant.rs (100%) rename src/test/ui/{unreachable => reachable}/unreachable-variant.stderr (100%) rename src/test/ui/{unreachable => reachable}/unwarned-match-on-never.rs (100%) rename src/test/ui/{unreachable => reachable}/unwarned-match-on-never.stderr (100%) rename src/test/ui/{ => uninhabited}/always-inhabited-union-ref.rs (100%) rename src/test/ui/{ => uninhabited}/always-inhabited-union-ref.stderr (100%) diff --git a/src/test/ui/coercion/coerce-issue-49593-box-never.rs b/src/test/ui/coercion/coerce-issue-49593-box-never.rs index f005245e6dcb..5038eb3ebf45 100644 --- a/src/test/ui/coercion/coerce-issue-49593-box-never.rs +++ b/src/test/ui/coercion/coerce-issue-49593-box-never.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(never_type)] #![allow(unreachable_code)] diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs index 27ff5ace25dd..f0cc9ea70550 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.rs @@ -1,4 +1,5 @@ #![feature(never_type)] + fn foo() -> Result { Ok(123) } diff --git a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr index d77fbc1e8239..08c36cece4cf 100644 --- a/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr +++ b/src/test/ui/feature-gates/feature-gate-exhaustive-patterns.stderr @@ -1,5 +1,5 @@ error[E0005]: refutable pattern in local binding: `Err(_)` not covered - --> $DIR/feature-gate-exhaustive-patterns.rs:7:9 + --> $DIR/feature-gate-exhaustive-patterns.rs:8:9 | LL | let Ok(_x) = foo(); | ^^^^^^ pattern `Err(_)` not covered diff --git a/src/test/ui/for-loop-while/loop-break-value.rs b/src/test/ui/for-loop-while/loop-break-value.rs index e1edbbb929e6..d7209fc4de86 100644 --- a/src/test/ui/for-loop-while/loop-break-value.rs +++ b/src/test/ui/for-loop-while/loop-break-value.rs @@ -1,4 +1,5 @@ // run-pass + #![allow(unreachable_code)] #![feature(never_type)] diff --git a/src/test/ui/lint/must_use-unit.rs b/src/test/ui/lint/must_use-unit.rs index 92568252164f..4dd4798abb7c 100644 --- a/src/test/ui/lint/must_use-unit.rs +++ b/src/test/ui/lint/must_use-unit.rs @@ -1,5 +1,4 @@ #![feature(never_type)] - #![deny(unused_must_use)] #[must_use] diff --git a/src/test/ui/lint/must_use-unit.stderr b/src/test/ui/lint/must_use-unit.stderr index f6229c0442f9..0a9939b2015b 100644 --- a/src/test/ui/lint/must_use-unit.stderr +++ b/src/test/ui/lint/must_use-unit.stderr @@ -1,17 +1,17 @@ error: unused return value of `foo` that must be used - --> $DIR/must_use-unit.rs:14:5 + --> $DIR/must_use-unit.rs:13:5 | LL | foo(); | ^^^^^^ | note: lint level defined here - --> $DIR/must_use-unit.rs:3:9 + --> $DIR/must_use-unit.rs:2:9 | LL | #![deny(unused_must_use)] | ^^^^^^^^^^^^^^^ error: unused return value of `bar` that must be used - --> $DIR/must_use-unit.rs:16:5 + --> $DIR/must_use-unit.rs:15:5 | LL | bar(); | ^^^^^^ diff --git a/src/test/run-fail/adjust_never.rs b/src/test/ui/never_type/adjust_never.rs similarity index 93% rename from src/test/run-fail/adjust_never.rs rename to src/test/ui/never_type/adjust_never.rs index 8661a2f80a7b..3aa5866ebfbe 100644 --- a/src/test/run-fail/adjust_never.rs +++ b/src/test/ui/never_type/adjust_never.rs @@ -1,5 +1,6 @@ // Test that a variable of type ! can coerce to another type. +// run-fail // error-pattern:explicit #![feature(never_type)] diff --git a/src/test/ui/call-fn-never-arg-wrong-type.rs b/src/test/ui/never_type/call-fn-never-arg-wrong-type.rs similarity index 100% rename from src/test/ui/call-fn-never-arg-wrong-type.rs rename to src/test/ui/never_type/call-fn-never-arg-wrong-type.rs diff --git a/src/test/ui/call-fn-never-arg-wrong-type.stderr b/src/test/ui/never_type/call-fn-never-arg-wrong-type.stderr similarity index 100% rename from src/test/ui/call-fn-never-arg-wrong-type.stderr rename to src/test/ui/never_type/call-fn-never-arg-wrong-type.stderr diff --git a/src/test/run-fail/call-fn-never-arg.rs b/src/test/ui/never_type/call-fn-never-arg.rs similarity index 94% rename from src/test/run-fail/call-fn-never-arg.rs rename to src/test/ui/never_type/call-fn-never-arg.rs index f5b2cfaefe02..6218572f8a75 100644 --- a/src/test/run-fail/call-fn-never-arg.rs +++ b/src/test/ui/never_type/call-fn-never-arg.rs @@ -1,5 +1,6 @@ // Test that we can use a ! for an argument of type ! +// run-fail // error-pattern:wowzers! #![feature(never_type)] diff --git a/src/test/run-fail/cast-never.rs b/src/test/ui/never_type/cast-never.rs similarity index 93% rename from src/test/run-fail/cast-never.rs rename to src/test/ui/never_type/cast-never.rs index 0b05a4b91128..46072e186e0f 100644 --- a/src/test/run-fail/cast-never.rs +++ b/src/test/ui/never_type/cast-never.rs @@ -1,5 +1,6 @@ // Test that we can explicitly cast ! to another type +// run-fail // error-pattern:explicit #![feature(never_type)] diff --git a/src/test/ui/defaulted-never-note.rs b/src/test/ui/never_type/defaulted-never-note.rs similarity index 100% rename from src/test/ui/defaulted-never-note.rs rename to src/test/ui/never_type/defaulted-never-note.rs diff --git a/src/test/ui/defaulted-never-note.stderr b/src/test/ui/never_type/defaulted-never-note.stderr similarity index 100% rename from src/test/ui/defaulted-never-note.stderr rename to src/test/ui/never_type/defaulted-never-note.stderr diff --git a/src/test/ui/dispatch_from_dyn_zst.rs b/src/test/ui/never_type/dispatch_from_dyn_zst.rs similarity index 100% rename from src/test/ui/dispatch_from_dyn_zst.rs rename to src/test/ui/never_type/dispatch_from_dyn_zst.rs diff --git a/src/test/ui/diverging-fallback-control-flow.rs b/src/test/ui/never_type/diverging-fallback-control-flow.rs similarity index 99% rename from src/test/ui/diverging-fallback-control-flow.rs rename to src/test/ui/never_type/diverging-fallback-control-flow.rs index 0f0f787b407d..c68e6364ed40 100644 --- a/src/test/ui/diverging-fallback-control-flow.rs +++ b/src/test/ui/never_type/diverging-fallback-control-flow.rs @@ -4,6 +4,7 @@ #![allow(unused_assignments)] #![allow(unused_variables)] #![allow(unreachable_code)] + // Test various cases where we permit an unconstrained variable // to fallback based on control-flow. // diff --git a/src/test/ui/impl-for-never.rs b/src/test/ui/never_type/impl-for-never.rs similarity index 99% rename from src/test/ui/impl-for-never.rs rename to src/test/ui/never_type/impl-for-never.rs index c5f12981ecc2..9423f08858b9 100644 --- a/src/test/ui/impl-for-never.rs +++ b/src/test/ui/never_type/impl-for-never.rs @@ -1,8 +1,9 @@ // run-pass -// Test that we can call static methods on ! both directly and when it appears in a generic #![feature(never_type)] +// Test that we can call static methods on ! both directly and when it appears in a generic + trait StringifyType { fn stringify_type() -> &'static str; } diff --git a/src/test/ui/issues/issue-13352.rs b/src/test/ui/never_type/issue-13352.rs similarity index 100% rename from src/test/ui/issues/issue-13352.rs rename to src/test/ui/never_type/issue-13352.rs diff --git a/src/test/ui/issues/issue-13352.stderr b/src/test/ui/never_type/issue-13352.stderr similarity index 100% rename from src/test/ui/issues/issue-13352.stderr rename to src/test/ui/never_type/issue-13352.stderr diff --git a/src/test/ui/issues/issue-2149.rs b/src/test/ui/never_type/issue-2149.rs similarity index 100% rename from src/test/ui/issues/issue-2149.rs rename to src/test/ui/never_type/issue-2149.rs diff --git a/src/test/ui/issues/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr similarity index 100% rename from src/test/ui/issues/issue-2149.stderr rename to src/test/ui/never_type/issue-2149.stderr diff --git a/src/test/ui/issues/issue-44402.rs b/src/test/ui/never_type/issue-44402.rs similarity index 90% rename from src/test/ui/issues/issue-44402.rs rename to src/test/ui/never_type/issue-44402.rs index 29b7eb5ee49c..699e480dfe7e 100644 --- a/src/test/ui/issues/issue-44402.rs +++ b/src/test/ui/never_type/issue-44402.rs @@ -1,4 +1,5 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass + #![allow(dead_code)] #![feature(never_type)] #![feature(exhaustive_patterns)] diff --git a/src/test/ui/never-assign-dead-code.rs b/src/test/ui/never_type/never-assign-dead-code.rs similarity index 82% rename from src/test/ui/never-assign-dead-code.rs rename to src/test/ui/never_type/never-assign-dead-code.rs index fd5fbc30611a..7bb7c87097c5 100644 --- a/src/test/ui/never-assign-dead-code.rs +++ b/src/test/ui/never_type/never-assign-dead-code.rs @@ -1,9 +1,9 @@ // Test that an assignment of type ! makes the rest of the block dead code. -#![feature(never_type)] -// build-pass (FIXME(62277): could be check-pass?) -#![warn(unused)] +// check-pass +#![feature(never_type)] +#![warn(unused)] fn main() { let x: ! = panic!("aah"); //~ WARN unused diff --git a/src/test/ui/never-assign-dead-code.stderr b/src/test/ui/never_type/never-assign-dead-code.stderr similarity index 92% rename from src/test/ui/never-assign-dead-code.stderr rename to src/test/ui/never_type/never-assign-dead-code.stderr index b887d580e68a..1860150fa8bc 100644 --- a/src/test/ui/never-assign-dead-code.stderr +++ b/src/test/ui/never_type/never-assign-dead-code.stderr @@ -7,7 +7,7 @@ LL | drop(x); | ^^^^^^^^ unreachable statement | note: lint level defined here - --> $DIR/never-assign-dead-code.rs:5:9 + --> $DIR/never-assign-dead-code.rs:6:9 | LL | #![warn(unused)] | ^^^^^^ @@ -29,7 +29,7 @@ LL | let x: ! = panic!("aah"); | ^ help: consider prefixing with an underscore: `_x` | note: lint level defined here - --> $DIR/never-assign-dead-code.rs:5:9 + --> $DIR/never-assign-dead-code.rs:6:9 | LL | #![warn(unused)] | ^^^^^^ diff --git a/src/test/ui/never-assign-wrong-type.rs b/src/test/ui/never_type/never-assign-wrong-type.rs similarity index 100% rename from src/test/ui/never-assign-wrong-type.rs rename to src/test/ui/never_type/never-assign-wrong-type.rs diff --git a/src/test/ui/never-assign-wrong-type.stderr b/src/test/ui/never_type/never-assign-wrong-type.stderr similarity index 100% rename from src/test/ui/never-assign-wrong-type.stderr rename to src/test/ui/never_type/never-assign-wrong-type.stderr diff --git a/src/test/run-fail/never-associated-type.rs b/src/test/ui/never_type/never-associated-type.rs similarity index 96% rename from src/test/run-fail/never-associated-type.rs rename to src/test/ui/never_type/never-associated-type.rs index 587f0f72d5a6..7f0a3fef6a99 100644 --- a/src/test/run-fail/never-associated-type.rs +++ b/src/test/ui/never_type/never-associated-type.rs @@ -1,5 +1,6 @@ // Test that we can use ! as an associated type. +// run-fail // error-pattern:kapow! #![feature(never_type)] diff --git a/src/test/ui/never-from-impl-is-reserved.rs b/src/test/ui/never_type/never-from-impl-is-reserved.rs similarity index 100% rename from src/test/ui/never-from-impl-is-reserved.rs rename to src/test/ui/never_type/never-from-impl-is-reserved.rs diff --git a/src/test/ui/never-from-impl-is-reserved.stderr b/src/test/ui/never_type/never-from-impl-is-reserved.stderr similarity index 100% rename from src/test/ui/never-from-impl-is-reserved.stderr rename to src/test/ui/never_type/never-from-impl-is-reserved.stderr diff --git a/src/test/ui/never-result.rs b/src/test/ui/never_type/never-result.rs similarity index 99% rename from src/test/ui/never-result.rs rename to src/test/ui/never_type/never-result.rs index 98ce326aa663..35af37910ef3 100644 --- a/src/test/ui/never-result.rs +++ b/src/test/ui/never_type/never-result.rs @@ -2,6 +2,7 @@ #![allow(unused_variables)] #![allow(unreachable_code)] + // Test that we can extract a ! through pattern matching then use it as several different types. #![feature(never_type)] diff --git a/src/test/run-fail/never-type-arg.rs b/src/test/ui/never_type/never-type-arg.rs similarity index 95% rename from src/test/run-fail/never-type-arg.rs rename to src/test/ui/never_type/never-type-arg.rs index 1747e96eef4e..a82d351f6cf2 100644 --- a/src/test/run-fail/never-type-arg.rs +++ b/src/test/ui/never_type/never-type-arg.rs @@ -1,5 +1,6 @@ // Test that we can use ! as an argument to a trait impl. +// run-fail // error-pattern:oh no! #![feature(never_type)] diff --git a/src/test/ui/never-type-rvalues.rs b/src/test/ui/never_type/never-type-rvalues.rs similarity index 100% rename from src/test/ui/never-type-rvalues.rs rename to src/test/ui/never_type/never-type-rvalues.rs diff --git a/src/test/ui/never_coercions.rs b/src/test/ui/never_type/never_coercions.rs similarity index 100% rename from src/test/ui/never_coercions.rs rename to src/test/ui/never_type/never_coercions.rs diff --git a/src/test/ui/never_transmute_never.rs b/src/test/ui/never_type/never_transmute_never.rs similarity index 87% rename from src/test/ui/never_transmute_never.rs rename to src/test/ui/never_type/never_transmute_never.rs index 5bad756b8762..fce3ced9aac7 100644 --- a/src/test/ui/never_transmute_never.rs +++ b/src/test/ui/never_type/never_transmute_never.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![crate_type="lib"] diff --git a/src/test/ui/panic-uninitialized-zeroed.rs b/src/test/ui/never_type/panic-uninitialized-zeroed.rs similarity index 100% rename from src/test/ui/panic-uninitialized-zeroed.rs rename to src/test/ui/never_type/panic-uninitialized-zeroed.rs diff --git a/src/test/ui/try_from.rs b/src/test/ui/never_type/try_from.rs similarity index 100% rename from src/test/ui/try_from.rs rename to src/test/ui/never_type/try_from.rs diff --git a/src/test/ui/unreachable/auxiliary/unreachable_variant.rs b/src/test/ui/reachable/auxiliary/unreachable_variant.rs similarity index 100% rename from src/test/ui/unreachable/auxiliary/unreachable_variant.rs rename to src/test/ui/reachable/auxiliary/unreachable_variant.rs diff --git a/src/test/ui/unreachable/unreachable-arm.rs b/src/test/ui/reachable/unreachable-arm.rs similarity index 100% rename from src/test/ui/unreachable/unreachable-arm.rs rename to src/test/ui/reachable/unreachable-arm.rs diff --git a/src/test/ui/unreachable/unreachable-arm.stderr b/src/test/ui/reachable/unreachable-arm.stderr similarity index 100% rename from src/test/ui/unreachable/unreachable-arm.stderr rename to src/test/ui/reachable/unreachable-arm.stderr diff --git a/src/test/ui/unreachable/unreachable-code.rs b/src/test/ui/reachable/unreachable-code.rs similarity index 100% rename from src/test/ui/unreachable/unreachable-code.rs rename to src/test/ui/reachable/unreachable-code.rs diff --git a/src/test/ui/unreachable/unreachable-code.stderr b/src/test/ui/reachable/unreachable-code.stderr similarity index 100% rename from src/test/ui/unreachable/unreachable-code.stderr rename to src/test/ui/reachable/unreachable-code.stderr diff --git a/src/test/ui/unreachable/unreachable-in-call.rs b/src/test/ui/reachable/unreachable-in-call.rs similarity index 100% rename from src/test/ui/unreachable/unreachable-in-call.rs rename to src/test/ui/reachable/unreachable-in-call.rs diff --git a/src/test/ui/unreachable/unreachable-in-call.stderr b/src/test/ui/reachable/unreachable-in-call.stderr similarity index 100% rename from src/test/ui/unreachable/unreachable-in-call.stderr rename to src/test/ui/reachable/unreachable-in-call.stderr diff --git a/src/test/ui/unreachable/unreachable-loop-patterns.rs b/src/test/ui/reachable/unreachable-loop-patterns.rs similarity index 95% rename from src/test/ui/unreachable/unreachable-loop-patterns.rs rename to src/test/ui/reachable/unreachable-loop-patterns.rs index 56ab1a270a75..6f1d2efa1b20 100644 --- a/src/test/ui/unreachable/unreachable-loop-patterns.rs +++ b/src/test/ui/reachable/unreachable-loop-patterns.rs @@ -1,5 +1,3 @@ -// compile-fail - #![feature(never_type)] #![feature(exhaustive_patterns)] diff --git a/src/test/ui/unreachable/unreachable-loop-patterns.stderr b/src/test/ui/reachable/unreachable-loop-patterns.stderr similarity index 73% rename from src/test/ui/unreachable/unreachable-loop-patterns.stderr rename to src/test/ui/reachable/unreachable-loop-patterns.stderr index 254d1178d142..bb5103320d2c 100644 --- a/src/test/ui/unreachable/unreachable-loop-patterns.stderr +++ b/src/test/ui/reachable/unreachable-loop-patterns.stderr @@ -1,17 +1,17 @@ error: unreachable pattern - --> $DIR/unreachable-loop-patterns.rs:20:9 + --> $DIR/unreachable-loop-patterns.rs:18:9 | LL | for _ in unimplemented!() as Void {} | ^ | note: lint level defined here - --> $DIR/unreachable-loop-patterns.rs:7:9 + --> $DIR/unreachable-loop-patterns.rs:5:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern - --> $DIR/unreachable-loop-patterns.rs:20:14 + --> $DIR/unreachable-loop-patterns.rs:18:14 | LL | for _ in unimplemented!() as Void {} | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/unreachable/unreachable-try-pattern.rs b/src/test/ui/reachable/unreachable-try-pattern.rs similarity index 94% rename from src/test/ui/unreachable/unreachable-try-pattern.rs rename to src/test/ui/reachable/unreachable-try-pattern.rs index cbc5fcee2f03..23360e73f4a3 100644 --- a/src/test/ui/unreachable/unreachable-try-pattern.rs +++ b/src/test/ui/reachable/unreachable-try-pattern.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(never_type, exhaustive_patterns)] #![warn(unreachable_code)] #![warn(unreachable_patterns)] diff --git a/src/test/ui/unreachable/unreachable-try-pattern.stderr b/src/test/ui/reachable/unreachable-try-pattern.stderr similarity index 100% rename from src/test/ui/unreachable/unreachable-try-pattern.stderr rename to src/test/ui/reachable/unreachable-try-pattern.stderr diff --git a/src/test/ui/unreachable/unreachable-variant.rs b/src/test/ui/reachable/unreachable-variant.rs similarity index 100% rename from src/test/ui/unreachable/unreachable-variant.rs rename to src/test/ui/reachable/unreachable-variant.rs diff --git a/src/test/ui/unreachable/unreachable-variant.stderr b/src/test/ui/reachable/unreachable-variant.stderr similarity index 100% rename from src/test/ui/unreachable/unreachable-variant.stderr rename to src/test/ui/reachable/unreachable-variant.stderr diff --git a/src/test/ui/unreachable/unwarned-match-on-never.rs b/src/test/ui/reachable/unwarned-match-on-never.rs similarity index 100% rename from src/test/ui/unreachable/unwarned-match-on-never.rs rename to src/test/ui/reachable/unwarned-match-on-never.rs diff --git a/src/test/ui/unreachable/unwarned-match-on-never.stderr b/src/test/ui/reachable/unwarned-match-on-never.stderr similarity index 100% rename from src/test/ui/unreachable/unwarned-match-on-never.stderr rename to src/test/ui/reachable/unwarned-match-on-never.stderr diff --git a/src/test/ui/always-inhabited-union-ref.rs b/src/test/ui/uninhabited/always-inhabited-union-ref.rs similarity index 100% rename from src/test/ui/always-inhabited-union-ref.rs rename to src/test/ui/uninhabited/always-inhabited-union-ref.rs diff --git a/src/test/ui/always-inhabited-union-ref.stderr b/src/test/ui/uninhabited/always-inhabited-union-ref.stderr similarity index 100% rename from src/test/ui/always-inhabited-union-ref.stderr rename to src/test/ui/uninhabited/always-inhabited-union-ref.stderr From dee53d7c90812d0cbabe7f19b35c125432c1c8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 9 Oct 2019 10:10:54 -0700 Subject: [PATCH 394/545] Fix suggestion to constrain trait for method to be found --- src/librustc_typeck/check/method/suggest.rs | 113 +++++++++++------- src/test/ui/suggestions/constrain-trait.fixed | 47 ++++++++ src/test/ui/suggestions/constrain-trait.rs | 47 ++++++++ .../ui/suggestions/constrain-trait.stderr | 27 +++++ 4 files changed, 191 insertions(+), 43 deletions(-) create mode 100644 src/test/ui/suggestions/constrain-trait.fixed create mode 100644 src/test/ui/suggestions/constrain-trait.rs create mode 100644 src/test/ui/suggestions/constrain-trait.stderr diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 96cc5aa1dc24..f2d001eadedd 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -777,7 +777,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { "items from traits can only be used if the trait is implemented and in scope" }); - let mut msg = format!( + let message = |action| format!( "the following {traits_define} an item `{name}`, perhaps you need to {action} \ {one_of_them}:", traits_define = if candidates.len() == 1 { @@ -785,11 +785,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { "traits define" }, - action = if let Some(param) = param_type { - format!("restrict type parameter `{}` with", param) - } else { - "implement".to_string() - }, + action = action, one_of_them = if candidates.len() == 1 { "it" } else { @@ -809,50 +805,81 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Get the `hir::Param` to verify whether it already has any bounds. // We do this to avoid suggesting code that ends up as `T: FooBar`, // instead we suggest `T: Foo + Bar` in that case. - let mut has_bounds = None; - let mut impl_trait = false; - if let Node::GenericParam(ref param) = hir.get(id) { - let kind = ¶m.kind; - if let hir::GenericParamKind::Type { synthetic: Some(_), .. } = kind { - // We've found `fn foo(x: impl Trait)` instead of - // `fn foo(x: T)`. We want to suggest the correct - // `fn foo(x: impl Trait + TraitBound)` instead of - // `fn foo(x: T)`. (See #63706.) - impl_trait = true; - has_bounds = param.bounds.get(1); - } else { - has_bounds = param.bounds.get(0); + match hir.get(id) { + Node::GenericParam(ref param) => { + let mut impl_trait = false; + let has_bounds = if let hir::GenericParamKind::Type { + synthetic: Some(_), .. + } = ¶m.kind { + // We've found `fn foo(x: impl Trait)` instead of + // `fn foo(x: T)`. We want to suggest the correct + // `fn foo(x: impl Trait + TraitBound)` instead of + // `fn foo(x: T)`. (#63706) + impl_trait = true; + param.bounds.get(1) + } else { + param.bounds.get(0) + }; + let sp = hir.span(id); + let sp = if let Some(first_bound) = has_bounds { + // `sp` only covers `T`, change it so that it covers + // `T:` when appropriate + sp.until(first_bound.span()) + } else { + sp + }; + // FIXME: contrast `t.def_id` against `param.bounds` to not suggest + // traits already there. That can happen when the cause is that + // we're in a const scope or associated function used as a method. + err.span_suggestions( + sp, + &message(format!( + "restrict type parameter `{}` with", + param.name.ident().as_str(), + )), + candidates.iter().map(|t| format!( + "{}{} {}{}", + param.name.ident().as_str(), + if impl_trait { " +" } else { ":" }, + self.tcx.def_path_str(t.def_id), + if has_bounds.is_some() { " + "} else { "" }, + )), + Applicability::MaybeIncorrect, + ); + suggested = true; } + Node::Item(hir::Item { + kind: hir::ItemKind::Trait(.., bounds, _), ident, .. + }) => { + let (sp, sep, article) = if bounds.is_empty() { + (ident.span.shrink_to_hi(), ":", "a") + } else { + (bounds.last().unwrap().span().shrink_to_hi(), " +", "another") + }; + err.span_suggestions( + sp, + &message(format!("add {} supertrait for", article)), + candidates.iter().map(|t| format!( + "{} {}", + sep, + self.tcx.def_path_str(t.def_id), + )), + Applicability::MaybeIncorrect, + ); + suggested = true; + } + _ => {} } - let sp = hir.span(id); - // `sp` only covers `T`, change it so that it covers `T:` when appropriate. - let sp = if let Some(first_bound) = has_bounds { - sp.until(first_bound.span()) - } else { - sp - }; - - // FIXME: contrast `t.def_id` against `param.bounds` to not suggest traits - // already there. That can happen when the cause is that we're in a const - // scope or associated function used as a method. - err.span_suggestions( - sp, - &msg[..], - candidates.iter().map(|t| format!( - "{}{} {}{}", - param, - if impl_trait { " +" } else { ":" }, - self.tcx.def_path_str(t.def_id), - if has_bounds.is_some() { " + " } else { "" }, - )), - Applicability::MaybeIncorrect, - ); - suggested = true; } }; } if !suggested { + let mut msg = message(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 #{}: `{}`", diff --git a/src/test/ui/suggestions/constrain-trait.fixed b/src/test/ui/suggestions/constrain-trait.fixed new file mode 100644 index 000000000000..dda9e931353b --- /dev/null +++ b/src/test/ui/suggestions/constrain-trait.fixed @@ -0,0 +1,47 @@ +// run-rustfix +// check-only + +#[derive(Debug)] +struct Demo { + a: String +} + +trait GetString { + fn get_a(&self) -> &String; +} + +trait UseString: std::fmt::Debug + GetString { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self` + } +} + +trait UseString2: GetString { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self` + } +} + +impl GetString for Demo { + fn get_a(&self) -> &String { + &self.a + } +} + +impl UseString for Demo {} +impl UseString2 for Demo {} + + +#[cfg(test)] +mod tests { + use crate::{Demo, UseString}; + + #[test] + fn it_works() { + let d = Demo { a: "test".to_string() }; + d.use_string(); + } +} + + +fn main() {} diff --git a/src/test/ui/suggestions/constrain-trait.rs b/src/test/ui/suggestions/constrain-trait.rs new file mode 100644 index 000000000000..4ef0eff5bd76 --- /dev/null +++ b/src/test/ui/suggestions/constrain-trait.rs @@ -0,0 +1,47 @@ +// run-rustfix +// check-only + +#[derive(Debug)] +struct Demo { + a: String +} + +trait GetString { + fn get_a(&self) -> &String; +} + +trait UseString: std::fmt::Debug { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self` + } +} + +trait UseString2 { + fn use_string(&self) { + println!("{:?}", self.get_a()); //~ ERROR no method named `get_a` found for type `&Self` + } +} + +impl GetString for Demo { + fn get_a(&self) -> &String { + &self.a + } +} + +impl UseString for Demo {} +impl UseString2 for Demo {} + + +#[cfg(test)] +mod tests { + use crate::{Demo, UseString}; + + #[test] + fn it_works() { + let d = Demo { a: "test".to_string() }; + d.use_string(); + } +} + + +fn main() {} diff --git a/src/test/ui/suggestions/constrain-trait.stderr b/src/test/ui/suggestions/constrain-trait.stderr new file mode 100644 index 000000000000..3cc351ac80ae --- /dev/null +++ b/src/test/ui/suggestions/constrain-trait.stderr @@ -0,0 +1,27 @@ +error[E0599]: no method named `get_a` found for type `&Self` in the current scope + --> $DIR/constrain-trait.rs:15:31 + | +LL | println!("{:?}", self.get_a()); + | ^^^^^ method not found in `&Self` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `get_a`, perhaps you need to add another supertrait for it: + | +LL | trait UseString: std::fmt::Debug + GetString { + | ^^^^^^^^^^^ + +error[E0599]: no method named `get_a` found for type `&Self` in the current scope + --> $DIR/constrain-trait.rs:21:31 + | +LL | println!("{:?}", self.get_a()); + | ^^^^^ method not found in `&Self` + | + = help: items from traits can only be used if the type parameter is bounded by the trait +help: the following trait defines an item `get_a`, perhaps you need to add a supertrait for it: + | +LL | trait UseString2: GetString { + | ^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. From e505857914795dd2171acb4193a010f9d09ebc7c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 22 May 2019 13:46:14 +0300 Subject: [PATCH 395/545] rustc_metadata: remove now-redundant length from the start of the encoding. --- src/librustc_metadata/index.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 037f9d356308..8db7a51700bc 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -110,12 +110,8 @@ impl Index<'tcx> { crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); - - // First we write the length of the lower range ... - buf.emit_raw_bytes(&(self.positions.len() as u32 / 4).to_le_bytes()); - // ... then the values. buf.emit_raw_bytes(&self.positions); - Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4 + 1) + Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4) } } @@ -124,12 +120,12 @@ impl Lazy<[Index<'tcx>]> { /// DefIndex (if any). #[inline(never)] crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { - let bytes = &bytes[self.position..]; debug!("Index::lookup: index={:?} len={:?}", def_index, self.meta); - let position = u32::read_from_bytes_at(bytes, 1 + def_index.index()); + let bytes = &bytes[self.position..][..self.meta * 4]; + let position = u32::read_from_bytes_at(bytes, def_index.index()); if position == u32::MAX { debug!("Index::lookup: position=u32::MAX"); None From ea134563e709af1fdcf07766b281b0407b1e3500 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 18:24:38 +0300 Subject: [PATCH 396/545] rustc_metadata: use NonZeroUsize for the position of a Lazy. --- src/librustc_metadata/decoder.rs | 20 +++++++++++++------- src/librustc_metadata/encoder.rs | 16 +++++++++------- src/librustc_metadata/index.rs | 14 +++++++++----- src/librustc_metadata/schema.rs | 13 +++++++------ 4 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 6969d608d76d..a2955212bd49 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -25,6 +25,7 @@ use rustc::util::captures::Captures; use std::io; use std::mem; +use std::num::NonZeroUsize; use std::u32; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; @@ -131,7 +132,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) { impl<'a, 'tcx, T: Decodable> Lazy { crate fn decode>(self, meta: M) -> T { - let mut dcx = meta.decoder(self.position); + let mut dcx = meta.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); T::decode(&mut dcx).unwrap() } @@ -142,7 +143,7 @@ impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { self, meta: M, ) -> impl ExactSizeIterator + Captures<'a> + Captures<'tcx> + 'x { - let mut dcx = meta.decoder(self.position); + let mut dcx = meta.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } @@ -166,13 +167,14 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { let position = match self.lazy_state { LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), LazyState::NodeStart(start) => { + let start = start.get(); assert!(distance + min_size <= start); start - distance - min_size } - LazyState::Previous(last_min_end) => last_min_end + distance, + LazyState::Previous(last_min_end) => last_min_end.get() + distance, }; - self.lazy_state = LazyState::Previous(position + min_size); - Ok(Lazy::from_position_and_meta(position, meta)) + self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap()); + Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta)) } } @@ -384,7 +386,9 @@ impl<'tcx> MetadataBlob { } crate fn get_rustc_version(&self) -> String { - Lazy::::from_position(METADATA_HEADER.len() + 4).decode(self) + Lazy::::from_position( + NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap(), + ).decode(self) } crate fn get_root(&self) -> CrateRoot<'tcx> { @@ -393,7 +397,9 @@ impl<'tcx> MetadataBlob { let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | ((slice[offset + 2] as u32) << 8) | ((slice[offset + 3] as u32) << 0)) as usize; - Lazy::>::from_position(pos).decode(self) + Lazy::>::from_position( + NonZeroUsize::new(pos).unwrap(), + ).decode(self) } crate fn list_crate_metadata(&self, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 03a14f886455..76bac1251260 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -23,11 +23,12 @@ use rustc::session::config::{self, CrateType}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::sync::Lrc; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; use std::hash::Hash; +use std::num::NonZeroUsize; use std::path::Path; -use rustc_data_structures::sync::Lrc; use std::u32; use syntax::ast; use syntax::attr; @@ -271,10 +272,11 @@ impl<'tcx> EncodeContext<'tcx> { &mut self, lazy: Lazy, ) -> Result<(), ::Error> { - let min_end = lazy.position + T::min_size(lazy.meta); + let min_end = lazy.position.get() + T::min_size(lazy.meta); let distance = match self.lazy_state { LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), LazyState::NodeStart(start) => { + let start = start.get(); assert!(min_end <= start); start - min_end } @@ -284,10 +286,10 @@ impl<'tcx> EncodeContext<'tcx> { "make sure that the calls to `lazy*` \ are in the same order as the metadata fields", ); - lazy.position - last_min_end + lazy.position.get() - last_min_end.get() } }; - self.lazy_state = LazyState::Previous(min_end); + self.lazy_state = LazyState::Previous(NonZeroUsize::new(min_end).unwrap()); self.emit_usize(distance) } @@ -295,14 +297,14 @@ impl<'tcx> EncodeContext<'tcx> { &mut self, value: impl EncodeContentsForLazy, ) -> Lazy { - let pos = self.position(); + let pos = NonZeroUsize::new(self.position()).unwrap(); assert_eq!(self.lazy_state, LazyState::NoNode); self.lazy_state = LazyState::NodeStart(pos); let meta = value.encode_contents_for_lazy(self); self.lazy_state = LazyState::NoNode; - assert!(pos + ::min_size(meta) <= self.position()); + assert!(pos.get() + ::min_size(meta) <= self.position()); Lazy::from_position_and_meta(pos, meta) } @@ -1934,7 +1936,7 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { // Encode the root position. let header = METADATA_HEADER.len(); - let pos = root.position; + let pos = root.position.get(); result[header + 0] = (pos >> 24) as u8; result[header + 1] = (pos >> 16) as u8; result[header + 2] = (pos >> 8) as u8; diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 8db7a51700bc..6f47ebb91446 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -3,6 +3,7 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex}; use rustc_serialize::opaque::Encoder; use std::marker::PhantomData; +use std::num::NonZeroUsize; use std::u32; use log::debug; @@ -94,8 +95,8 @@ impl Index<'tcx> { } fn record_index(&mut self, item: DefIndex, entry: Lazy>) { - assert!(entry.position < (u32::MAX as usize)); - let position = entry.position as u32; + assert!(entry.position.get() < (u32::MAX as usize)); + let position = entry.position.get() as u32; let array_index = item.index(); let positions = &mut self.positions; @@ -111,7 +112,10 @@ impl Index<'tcx> { crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); buf.emit_raw_bytes(&self.positions); - Lazy::from_position_and_meta(pos as usize, self.positions.len() / 4) + Lazy::from_position_and_meta( + NonZeroUsize::new(pos as usize).unwrap(), + self.positions.len() / 4, + ) } } @@ -124,14 +128,14 @@ impl Lazy<[Index<'tcx>]> { def_index, self.meta); - let bytes = &bytes[self.position..][..self.meta * 4]; + let bytes = &bytes[self.position.get()..][..self.meta * 4]; let position = u32::read_from_bytes_at(bytes, def_index.index()); if position == u32::MAX { debug!("Index::lookup: position=u32::MAX"); None } else { debug!("Index::lookup: position={:?}", position); - Some(Lazy::from_position(position as usize)) + Some(Lazy::from_position(NonZeroUsize::new(position as usize).unwrap())) } } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d3539e714012..9541e5c39cda 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -20,6 +20,7 @@ use syntax::symbol::Symbol; use syntax_pos::{self, Span}; use std::marker::PhantomData; +use std::num::NonZeroUsize; crate fn rustc_version() -> String { format!("rustc {}", @@ -102,13 +103,13 @@ crate struct Lazy::Meta> where T: ?Sized + LazyMeta, Meta: 'static + Copy, { - pub position: usize, + pub position: NonZeroUsize, pub meta: Meta, _marker: PhantomData, } impl Lazy { - crate fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy { + crate fn from_position_and_meta(position: NonZeroUsize, meta: T::Meta) -> Lazy { Lazy { position, meta, @@ -118,14 +119,14 @@ impl Lazy { } impl Lazy { - crate fn from_position(position: usize) -> Lazy { + crate fn from_position(position: NonZeroUsize) -> Lazy { Lazy::from_position_and_meta(position, ()) } } impl Lazy<[T]> { crate fn empty() -> Lazy<[T]> { - Lazy::from_position_and_meta(0, 0) + Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0) } } @@ -147,12 +148,12 @@ crate enum LazyState { /// Inside a metadata node, and before any `Lazy`. /// The position is that of the node itself. - NodeStart(usize), + NodeStart(NonZeroUsize), /// Inside a metadata node, with a previous `Lazy`. /// The position is a conservative estimate of where that /// previous `Lazy` would end (see their comments). - Previous(usize), + Previous(NonZeroUsize), } #[derive(RustcEncodable, RustcDecodable)] From 83b3c392187003236aafe10e153816c13f7b896d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 19:56:59 +0300 Subject: [PATCH 397/545] rustc_metadata: use 0 in index::Index to indicate missing entries. --- src/librustc_metadata/index.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 6f47ebb91446..d37765120be9 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -2,9 +2,9 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex}; use rustc_serialize::opaque::Encoder; +use std::convert::TryInto; use std::marker::PhantomData; use std::num::NonZeroUsize; -use std::u32; use log::debug; /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. @@ -73,7 +73,7 @@ impl FixedSizeEncoding for u32 { /// of each DefIndex. It is not required that all definitions appear /// in the metadata, nor that they are serialized in order, and /// therefore we first allocate the vector here and fill it with -/// `u32::MAX`. Whenever an index is visited, we fill in the +/// `0`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. crate struct Index<'tcx> { @@ -84,7 +84,7 @@ crate struct Index<'tcx> { impl Index<'tcx> { crate fn new(max_index: usize) -> Self { Index { - positions: vec![0xff; max_index * 4], + positions: vec![0; max_index * 4], _marker: PhantomData, } } @@ -95,12 +95,11 @@ impl Index<'tcx> { } fn record_index(&mut self, item: DefIndex, entry: Lazy>) { - assert!(entry.position.get() < (u32::MAX as usize)); - let position = entry.position.get() as u32; + let position: u32 = entry.position.get().try_into().unwrap(); let array_index = item.index(); let positions = &mut self.positions; - assert!(u32::read_from_bytes_at(positions, array_index) == u32::MAX, + assert!(u32::read_from_bytes_at(positions, array_index) == 0, "recorded position for item {:?} twice, first at {:?} and now at {:?}", item, u32::read_from_bytes_at(positions, array_index), @@ -130,12 +129,7 @@ impl Lazy<[Index<'tcx>]> { let bytes = &bytes[self.position.get()..][..self.meta * 4]; let position = u32::read_from_bytes_at(bytes, def_index.index()); - if position == u32::MAX { - debug!("Index::lookup: position=u32::MAX"); - None - } else { - debug!("Index::lookup: position={:?}", position); - Some(Lazy::from_position(NonZeroUsize::new(position as usize).unwrap())) - } + debug!("Index::lookup: position={:?}", position); + NonZeroUsize::new(position as usize).map(Lazy::from_position) } } From f49274032bc2819c6f9acaaf4e85e5200fc8bbba Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 23 May 2019 20:29:01 +0300 Subject: [PATCH 398/545] rustc_metadata: rename index::Index to table::Table. --- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 16 ++++++++-------- src/librustc_metadata/lib.rs | 12 ++++++------ src/librustc_metadata/schema.rs | 4 ++-- src/librustc_metadata/{index.rs => table.rs} | 14 +++++++------- 5 files changed, 24 insertions(+), 24 deletions(-) rename src/librustc_metadata/{index.rs => table.rs} (94%) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index a2955212bd49..684dfd69d2db 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -472,7 +472,7 @@ impl<'a, 'tcx> CrateMetadata { } fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) + self.root.entries_table.lookup(self.blob.raw_bytes(), item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 76bac1251260..abfee8eaa3cd 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,5 +1,5 @@ -use crate::index::Index; use crate::schema::*; +use crate::table::Table; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -47,7 +47,7 @@ struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, - entries_index: Index<'tcx>, + entries_table: Table<'tcx>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -325,7 +325,7 @@ impl<'tcx> EncodeContext<'tcx> { let entry = op(self, data); let entry = self.lazy(entry); - self.entries_index.record(id, entry); + self.entries_table.record(id, entry); } fn encode_info_for_items(&mut self) { @@ -477,8 +477,8 @@ impl<'tcx> EncodeContext<'tcx> { i = self.position(); - let entries_index = self.entries_index.write_index(&mut self.opaque); - let entries_index_bytes = self.position() - i; + let entries_table = self.entries_table.encode(&mut self.opaque); + let entries_table_bytes = self.position() - i; // Encode the proc macro data i = self.position(); @@ -537,7 +537,7 @@ impl<'tcx> EncodeContext<'tcx> { impls, exported_symbols, interpret_alloc_index, - entries_index, + entries_table, }); let total_bytes = self.position(); @@ -562,7 +562,7 @@ impl<'tcx> EncodeContext<'tcx> { println!(" def-path table bytes: {}", def_path_table_bytes); println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes); println!(" item bytes: {}", item_bytes); - println!(" entries index bytes: {}", entries_index_bytes); + println!(" entries table bytes: {}", entries_table_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -1916,7 +1916,7 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut ecx = EncodeContext { opaque: encoder, tcx, - entries_index: Index::new(tcx.hir().definitions().def_index_count()), + entries_table: Table::new(tcx.hir().definitions().def_index_count()), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 6aa684b1c3d0..291ee23ff726 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -26,15 +26,15 @@ extern crate rustc_data_structures; pub mod error_codes; -mod index; mod encoder; mod decoder; -mod cstore_impl; -mod schema; -mod native_libs; -mod link_args; -mod foreign_modules; mod dependency_format; +mod cstore_impl; +mod foreign_modules; +mod link_args; +mod native_libs; +mod schema; +mod table; pub mod creader; pub mod cstore; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 9541e5c39cda..52bbebb17f26 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -1,4 +1,4 @@ -use crate::index; +use crate::table::Table; use rustc::hir; use rustc::hir::def::{self, CtorKind}; @@ -186,7 +186,7 @@ crate struct CrateRoot<'tcx> { pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, pub interpret_alloc_index: Lazy<[u32]>, - pub entries_index: Lazy<[index::Index<'tcx>]>, + pub entries_table: Lazy<[Table<'tcx>]>, /// The DefIndex's of any proc macros delcared by /// this crate diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/table.rs similarity index 94% rename from src/librustc_metadata/index.rs rename to src/librustc_metadata/table.rs index d37765120be9..c53d69907044 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/table.rs @@ -76,14 +76,14 @@ impl FixedSizeEncoding for u32 { /// `0`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. -crate struct Index<'tcx> { +crate struct Table<'tcx> { positions: Vec, _marker: PhantomData<&'tcx ()>, } -impl Index<'tcx> { +impl Table<'tcx> { crate fn new(max_index: usize) -> Self { - Index { + Table { positions: vec![0; max_index * 4], _marker: PhantomData, } @@ -108,7 +108,7 @@ impl Index<'tcx> { position.write_to_bytes_at(positions, array_index) } - crate fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { + crate fn encode(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); buf.emit_raw_bytes(&self.positions); Lazy::from_position_and_meta( @@ -118,18 +118,18 @@ impl Index<'tcx> { } } -impl Lazy<[Index<'tcx>]> { +impl Lazy<[Table<'tcx>]> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { - debug!("Index::lookup: index={:?} len={:?}", + debug!("Table::lookup: index={:?} len={:?}", def_index, self.meta); let bytes = &bytes[self.position.get()..][..self.meta * 4]; let position = u32::read_from_bytes_at(bytes, def_index.index()); - debug!("Index::lookup: position={:?}", position); + debug!("Table::lookup: position={:?}", position); NonZeroUsize::new(position as usize).map(Lazy::from_position) } } From ffd18fc22c7dcfd59bb09567217046f6e0b71e7f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 22:52:12 +0300 Subject: [PATCH 399/545] rustc_metadata: parametrize Table by element type. --- src/librustc_metadata/encoder.rs | 2 +- src/librustc_metadata/schema.rs | 54 ++++++++++++++++++-------------- src/librustc_metadata/table.rs | 25 +++++++-------- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index abfee8eaa3cd..ef11ebdae43b 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -47,7 +47,7 @@ struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, - entries_table: Table<'tcx>, + entries_table: Table>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 52bbebb17f26..a1b097225b7d 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -156,6 +156,14 @@ crate enum LazyState { Previous(NonZeroUsize), } +// FIXME(#59875) `Lazy!(T)` replaces `Lazy`, passing the `Meta` parameter +// manually, instead of relying on the default, to get the correct variance. +// Only needed when `T` itself contains a parameter (e.g. `'tcx`). +macro_rules! Lazy { + ([$T:ty]) => {Lazy<[$T], usize>}; + ($T:ty) => {Lazy<$T, ()>}; +} + #[derive(RustcEncodable, RustcDecodable)] crate struct CrateRoot<'tcx> { pub name: Symbol, @@ -183,10 +191,10 @@ crate struct CrateRoot<'tcx> { pub source_map: Lazy<[syntax_pos::SourceFile]>, pub def_path_table: Lazy, pub impls: Lazy<[TraitImpls]>, - pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, + pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy<[Table<'tcx>]>, + pub entries_table: Lazy!([Table>]), /// The DefIndex's of any proc macros delcared by /// this crate @@ -226,14 +234,14 @@ crate struct Entry<'tcx> { pub stability: Option>, pub deprecation: Option>, - pub ty: Option>>, + pub ty: Option)>, pub inherent_impls: Lazy<[DefIndex]>, pub variances: Lazy<[ty::Variance]>, pub generics: Option>, - pub predicates: Option>>, - pub predicates_defined_on: Option>>, + pub predicates: Option)>, + pub predicates_defined_on: Option)>, - pub mir: Option>>, + pub mir: Option)>, pub promoted_mir: Option>>>, } @@ -253,22 +261,22 @@ crate enum EntryKind<'tcx> { OpaqueTy, Enum(ReprOptions), Field, - Variant(Lazy>), - Struct(Lazy>, ReprOptions), - Union(Lazy>, ReprOptions), - Fn(Lazy>), - ForeignFn(Lazy>), + Variant(Lazy!(VariantData<'tcx>)), + Struct(Lazy!(VariantData<'tcx>), ReprOptions), + Union(Lazy!(VariantData<'tcx>), ReprOptions), + Fn(Lazy!(FnData<'tcx>)), + ForeignFn(Lazy!(FnData<'tcx>)), Mod(Lazy), MacroDef(Lazy), - Closure(Lazy>), - Generator(Lazy>), - Trait(Lazy>), - Impl(Lazy>), - Method(Lazy>), + Closure(Lazy!(ClosureData<'tcx>)), + Generator(Lazy!(GeneratorData<'tcx>)), + Trait(Lazy!(TraitData<'tcx>)), + Impl(Lazy!(ImplData<'tcx>)), + Method(Lazy!(MethodData<'tcx>)), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), AssocConst(AssocContainer, ConstQualif, Lazy), - TraitAlias(Lazy>), + TraitAlias(Lazy!(TraitAliasData<'tcx>)), } /// Additional data for EntryKind::Const and EntryKind::AssocConst @@ -298,7 +306,7 @@ crate struct FnData<'tcx> { pub asyncness: hir::IsAsync, pub constness: hir::Constness, pub param_names: Lazy<[ast::Name]>, - pub sig: Lazy>, + pub sig: Lazy!(ty::PolyFnSig<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] @@ -309,7 +317,7 @@ crate struct VariantData<'tcx> { pub ctor: Option, /// If this is a tuple struct or variant /// ctor, this is its "function" signature. - pub ctor_sig: Option>>, + pub ctor_sig: Option)>, } #[derive(RustcEncodable, RustcDecodable)] @@ -318,12 +326,12 @@ crate struct TraitData<'tcx> { pub paren_sugar: bool, pub has_auto_impl: bool, pub is_marker: bool, - pub super_predicates: Lazy>, + pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] crate struct TraitAliasData<'tcx> { - pub super_predicates: Lazy>, + pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] @@ -334,7 +342,7 @@ crate struct ImplData<'tcx> { /// This is `Some` only for impls of `CoerceUnsized`. pub coerce_unsized_info: Option, - pub trait_ref: Option>>, + pub trait_ref: Option)>, } @@ -385,7 +393,7 @@ crate struct MethodData<'tcx> { #[derive(RustcEncodable, RustcDecodable)] crate struct ClosureData<'tcx> { - pub sig: Lazy>, + pub sig: Lazy!(ty::PolyFnSig<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index c53d69907044..94966a44edd2 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -69,19 +69,16 @@ impl FixedSizeEncoding for u32 { } } -/// While we are generating the metadata, we also track the position -/// of each DefIndex. It is not required that all definitions appear -/// in the metadata, nor that they are serialized in order, and -/// therefore we first allocate the vector here and fill it with -/// `0`. Whenever an index is visited, we fill in the -/// appropriate spot by calling `record_position`. We should never -/// visit the same index twice. -crate struct Table<'tcx> { +/// Random-access position table, allowing encoding in an arbitrary order +/// (e.g. while visiting the definitions of a crate), and on-demand decoding +/// of specific indices (e.g. queries for per-definition data). +/// Similar to `Vec>`, but with zero-copy decoding. +crate struct Table { positions: Vec, - _marker: PhantomData<&'tcx ()>, + _marker: PhantomData, } -impl Table<'tcx> { +impl Table { crate fn new(max_index: usize) -> Self { Table { positions: vec![0; max_index * 4], @@ -89,12 +86,12 @@ impl Table<'tcx> { } } - crate fn record(&mut self, def_id: DefId, entry: Lazy>) { + crate fn record(&mut self, def_id: DefId, entry: Lazy) { assert!(def_id.is_local()); self.record_index(def_id.index, entry); } - fn record_index(&mut self, item: DefIndex, entry: Lazy>) { + crate fn record_index(&mut self, item: DefIndex, entry: Lazy) { let position: u32 = entry.position.get().try_into().unwrap(); let array_index = item.index(); @@ -118,11 +115,11 @@ impl Table<'tcx> { } } -impl Lazy<[Table<'tcx>]> { +impl Lazy<[Table]> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] - crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { + crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { debug!("Table::lookup: index={:?} len={:?}", def_index, self.meta); From dd1264e90a47d9818d868276cd09363fe78056c4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 23:36:00 +0300 Subject: [PATCH 400/545] rustc_metadata: replace Lazy<[Table]> with Lazy>. --- src/librustc_metadata/decoder.rs | 19 ++++++++++++++----- src/librustc_metadata/encoder.rs | 15 ++++++++++++--- src/librustc_metadata/schema.rs | 12 +++++++----- src/librustc_metadata/table.rs | 18 +++++++++++++----- 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 684dfd69d2db..c2ec9115d310 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -2,6 +2,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob}; use crate::schema::*; +use crate::table::Table; use rustc_index::vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; @@ -28,7 +29,7 @@ use std::mem; use std::num::NonZeroUsize; use std::u32; -use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; +use rustc_serialize::{Decodable, Decoder, Encodable, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; use syntax::source_map::{self, respan, Spanned}; @@ -130,7 +131,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) { } } -impl<'a, 'tcx, T: Decodable> Lazy { +impl<'a, 'tcx, T: Encodable + Decodable> Lazy { crate fn decode>(self, meta: M) -> T { let mut dcx = meta.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); @@ -138,7 +139,7 @@ impl<'a, 'tcx, T: Decodable> Lazy { } } -impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> { +impl<'a: 'x, 'tcx: 'x, 'x, T: Encodable + Decodable> Lazy<[T]> { crate fn decode>( self, meta: M, @@ -237,13 +238,13 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> { } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { self.read_lazy_with_meta(()) } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; if len == 0 { @@ -254,6 +255,14 @@ impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { } } +impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> + where T: LazyMeta, +{ + fn specialized_decode(&mut self) -> Result>, Self::Error> { + let len = self.read_usize()?; + self.read_lazy_with_meta(len) + } +} impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { #[inline] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index ef11ebdae43b..53d3039a2842 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -98,13 +98,13 @@ impl<'tcx> Encoder for EncodeContext<'tcx> { } } -impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { +impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { fn specialized_encode(&mut self, lazy: &Lazy) -> Result<(), Self::Error> { self.emit_lazy_distance(*lazy) } } -impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { +impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta)?; if lazy.meta == 0 { @@ -114,6 +114,15 @@ impl<'tcx, T> SpecializedEncoder> for EncodeContext<'tcx> { } } +impl<'tcx, T> SpecializedEncoder>> for EncodeContext<'tcx> + where T: LazyMeta, +{ + fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { + self.emit_usize(lazy.meta)?; + self.emit_lazy_distance(*lazy) + } +} + impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { #[inline] fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> { @@ -258,7 +267,7 @@ impl EncodeContentsForLazy for T { } } -impl EncodeContentsForLazy<[T]> for I +impl EncodeContentsForLazy<[T]> for I where I: IntoIterator, I::Item: EncodeContentsForLazy, { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index a1b097225b7d..6ae20a9d438f 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -14,6 +14,7 @@ use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc_index::vec::IndexVec; use rustc_data_structures::svh::Svh; +use rustc_serialize::Encodable; use syntax::{ast, attr}; use syntax::edition::Edition; use syntax::symbol::Symbol; @@ -53,7 +54,7 @@ crate trait LazyMeta { fn min_size(meta: Self::Meta) -> usize; } -impl LazyMeta for T { +impl LazyMeta for T { type Meta = (); fn min_size(_: ()) -> usize { @@ -62,7 +63,7 @@ impl LazyMeta for T { } } -impl LazyMeta for [T] { +impl LazyMeta for [T] { type Meta = usize; fn min_size(len: usize) -> usize { @@ -118,13 +119,13 @@ impl Lazy { } } -impl Lazy { +impl Lazy { crate fn from_position(position: NonZeroUsize) -> Lazy { Lazy::from_position_and_meta(position, ()) } } -impl Lazy<[T]> { +impl Lazy<[T]> { crate fn empty() -> Lazy<[T]> { Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0) } @@ -160,6 +161,7 @@ crate enum LazyState { // manually, instead of relying on the default, to get the correct variance. // Only needed when `T` itself contains a parameter (e.g. `'tcx`). macro_rules! Lazy { + (Table<$T:ty>) => {Lazy, usize>}; ([$T:ty]) => {Lazy<[$T], usize>}; ($T:ty) => {Lazy<$T, ()>}; } @@ -194,7 +196,7 @@ crate struct CrateRoot<'tcx> { pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy!([Table>]), + pub entries_table: Lazy!(Table>), /// The DefIndex's of any proc macros delcared by /// this crate diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index 94966a44edd2..e18535060e6a 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -1,7 +1,7 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex}; -use rustc_serialize::opaque::Encoder; +use rustc_serialize::{Encodable, opaque::Encoder}; use std::convert::TryInto; use std::marker::PhantomData; use std::num::NonZeroUsize; @@ -73,12 +73,12 @@ impl FixedSizeEncoding for u32 { /// (e.g. while visiting the definitions of a crate), and on-demand decoding /// of specific indices (e.g. queries for per-definition data). /// Similar to `Vec>`, but with zero-copy decoding. -crate struct Table { +crate struct Table> { positions: Vec, _marker: PhantomData, } -impl Table { +impl> Table { crate fn new(max_index: usize) -> Self { Table { positions: vec![0; max_index * 4], @@ -105,7 +105,7 @@ impl Table { position.write_to_bytes_at(positions, array_index) } - crate fn encode(&self, buf: &mut Encoder) -> Lazy<[Self]> { + crate fn encode(&self, buf: &mut Encoder) -> Lazy { let pos = buf.position(); buf.emit_raw_bytes(&self.positions); Lazy::from_position_and_meta( @@ -115,7 +115,15 @@ impl Table { } } -impl Lazy<[Table]> { +impl> LazyMeta for Table { + type Meta = usize; + + fn min_size(len: usize) -> usize { + len * 4 + } +} + +impl Lazy> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] From 5d52a7e0d0f230627c20dc874c17c528261a397f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 Apr 2019 19:18:12 +0300 Subject: [PATCH 401/545] rustc_metadata: split tables into an usize-keyed Table and a DefIndex-keyed PerDefTable. --- src/librustc_metadata/decoder.rs | 6 +-- src/librustc_metadata/encoder.rs | 10 ++-- src/librustc_metadata/schema.rs | 5 +- src/librustc_metadata/table.rs | 91 ++++++++++++++++++++++---------- 4 files changed, 75 insertions(+), 37 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c2ec9115d310..c640e411f634 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -2,7 +2,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob}; use crate::schema::*; -use crate::table::Table; +use crate::table::PerDefTable; use rustc_index::vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; @@ -255,10 +255,10 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, } } -impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> +impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> where T: LazyMeta, { - fn specialized_decode(&mut self) -> Result>, Self::Error> { + fn specialized_decode(&mut self) -> Result>, Self::Error> { let len = self.read_usize()?; self.read_lazy_with_meta(len) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 53d3039a2842..df99541df587 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,5 +1,5 @@ use crate::schema::*; -use crate::table::Table; +use crate::table::PerDefTable; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -47,7 +47,7 @@ struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, - entries_table: Table>, + entries_table: PerDefTable>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -114,10 +114,10 @@ impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { } } -impl<'tcx, T> SpecializedEncoder>> for EncodeContext<'tcx> +impl<'tcx, T> SpecializedEncoder>> for EncodeContext<'tcx> where T: LazyMeta, { - fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { + fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta)?; self.emit_lazy_distance(*lazy) } @@ -1925,7 +1925,7 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut ecx = EncodeContext { opaque: encoder, tcx, - entries_table: Table::new(tcx.hir().definitions().def_index_count()), + entries_table: PerDefTable::new(tcx.hir().definitions().def_index_count()), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 6ae20a9d438f..dffc8f33b2de 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -1,4 +1,4 @@ -use crate::table::Table; +use crate::table::PerDefTable; use rustc::hir; use rustc::hir::def::{self, CtorKind}; @@ -162,6 +162,7 @@ crate enum LazyState { // Only needed when `T` itself contains a parameter (e.g. `'tcx`). macro_rules! Lazy { (Table<$T:ty>) => {Lazy, usize>}; + (PerDefTable<$T:ty>) => {Lazy, usize>}; ([$T:ty]) => {Lazy<[$T], usize>}; ($T:ty) => {Lazy<$T, ()>}; } @@ -196,7 +197,7 @@ crate struct CrateRoot<'tcx> { pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy!(Table>), + pub entries_table: Lazy!(PerDefTable>), /// The DefIndex's of any proc macros delcared by /// this crate diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index e18535060e6a..c60c8e2cbce5 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -73,44 +73,41 @@ impl FixedSizeEncoding for u32 { /// (e.g. while visiting the definitions of a crate), and on-demand decoding /// of specific indices (e.g. queries for per-definition data). /// Similar to `Vec>`, but with zero-copy decoding. +// FIXME(eddyb) newtype `[u8]` here, such that `Box>` would be used +// when building it, and `Lazy>` or `&Table` when reading it. +// Sadly, that doesn't work for `DefPerTable`, which is `(Table, Table)`, +// and so would need two lengths in its metadata, which is not supported yet. crate struct Table> { - positions: Vec, + bytes: Vec, _marker: PhantomData, } impl> Table { - crate fn new(max_index: usize) -> Self { + crate fn new(len: usize) -> Self { Table { - positions: vec![0; max_index * 4], + bytes: vec![0; len * 4], _marker: PhantomData, } } - crate fn record(&mut self, def_id: DefId, entry: Lazy) { - assert!(def_id.is_local()); - self.record_index(def_id.index, entry); - } - - crate fn record_index(&mut self, item: DefIndex, entry: Lazy) { + crate fn record(&mut self, i: usize, entry: Lazy) { let position: u32 = entry.position.get().try_into().unwrap(); - let array_index = item.index(); - let positions = &mut self.positions; - assert!(u32::read_from_bytes_at(positions, array_index) == 0, - "recorded position for item {:?} twice, first at {:?} and now at {:?}", - item, - u32::read_from_bytes_at(positions, array_index), + assert!(u32::read_from_bytes_at(&self.bytes, i) == 0, + "recorded position for index {:?} twice, first at {:?} and now at {:?}", + i, + u32::read_from_bytes_at(&self.bytes, i), position); - position.write_to_bytes_at(positions, array_index) + position.write_to_bytes_at(&mut self.bytes, i) } crate fn encode(&self, buf: &mut Encoder) -> Lazy { let pos = buf.position(); - buf.emit_raw_bytes(&self.positions); + buf.emit_raw_bytes(&self.bytes); Lazy::from_position_and_meta( NonZeroUsize::new(pos as usize).unwrap(), - self.positions.len() / 4, + self.bytes.len(), ) } } @@ -119,22 +116,62 @@ impl> LazyMeta for Table { type Meta = usize; fn min_size(len: usize) -> usize { - len * 4 + len } } impl Lazy> { - /// Given the metadata, extract out the offset of a particular - /// DefIndex (if any). + /// Given the metadata, extract out the offset of a particular index (if any). #[inline(never)] - crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { - debug!("Table::lookup: index={:?} len={:?}", - def_index, - self.meta); + crate fn lookup(&self, bytes: &[u8], i: usize) -> Option> { + debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - let bytes = &bytes[self.position.get()..][..self.meta * 4]; - let position = u32::read_from_bytes_at(bytes, def_index.index()); + let bytes = &bytes[self.position.get()..][..self.meta]; + let position = u32::read_from_bytes_at(bytes, i); debug!("Table::lookup: position={:?}", position); + NonZeroUsize::new(position as usize).map(Lazy::from_position) } } + + +/// Per-definition table, similar to `Table` but keyed on `DefIndex`. +// FIXME(eddyb) replace by making `Table` behave like `IndexVec`, +// and by using `newtype_index!` to define `DefIndex`. +crate struct PerDefTable>(Table); + +impl> PerDefTable { + crate fn new(def_index_count: usize) -> Self { + PerDefTable(Table::new(def_index_count)) + } + + crate fn record(&mut self, def_id: DefId, entry: Lazy) { + assert!(def_id.is_local()); + self.0.record(def_id.index.index(), entry); + } + + crate fn encode(&self, buf: &mut Encoder) -> Lazy { + let lazy = self.0.encode(buf); + Lazy::from_position_and_meta(lazy.position, lazy.meta) + } +} + +impl> LazyMeta for PerDefTable { + type Meta = as LazyMeta>::Meta; + + fn min_size(meta: Self::Meta) -> usize { + Table::::min_size(meta) + } +} + +impl Lazy> { + fn as_table(&self) -> Lazy> { + Lazy::from_position_and_meta(self.position, self.meta) + } + + /// Given the metadata, extract out the offset of a particular DefIndex (if any). + #[inline(never)] + crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { + self.as_table().lookup(bytes, def_index.index()) + } +} From 677f0df63b7f39c3b22a84004c1697e85743c470 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 Apr 2019 21:52:18 +0300 Subject: [PATCH 402/545] rustc_metadata: add a helper macro for recording into PerDefTable's. --- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 232 +++++++++++++++---------------- src/librustc_metadata/schema.rs | 9 +- 3 files changed, 117 insertions(+), 126 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c640e411f634..7ba395a1bd50 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -481,7 +481,7 @@ impl<'a, 'tcx> CrateMetadata { } fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - self.root.entries_table.lookup(self.blob.raw_bytes(), item_id) + self.root.per_def.entry.lookup(self.blob.raw_bytes(), item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index df99541df587..51634e372a2c 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -47,7 +47,7 @@ struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, - entries_table: PerDefTable>, + per_def: PerDefTables<'tcx>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -60,6 +60,10 @@ struct EncodeContext<'tcx> { source_file_cache: Lrc, } +struct PerDefTables<'tcx> { + entry: PerDefTable>, +} + macro_rules! encoder_methods { ($($name:ident($ty:ty);)*) => { $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { @@ -276,6 +280,18 @@ impl EncodeContentsForLazy<[T]> for I } } +// Shorthand for `$self.$tables.$table.record($key, $self.lazy($value))`, which would +// normally need extra variables to avoid errors about multiple mutable borrows. +macro_rules! record { + ($self:ident.$tables:ident.$table:ident[$key:expr] <- $value:expr) => {{ + { + let value = $value; + let lazy = $self.lazy(value); + $self.$tables.$table.record($key, lazy); + } + }} +} + impl<'tcx> EncodeContext<'tcx> { fn emit_lazy_distance( &mut self, @@ -318,31 +334,10 @@ impl<'tcx> EncodeContext<'tcx> { Lazy::from_position_and_meta(pos, meta) } - /// Emit the data for a `DefId` to the metadata. The function to - /// emit the data is `op`, and it will be given `data` as - /// arguments. This `record` function will call `op` to generate - /// the `Entry` (which may point to other encoded information) - /// and will then record the `Lazy` for use in the index. - // FIXME(eddyb) remove this. - fn record( - &mut self, - id: DefId, - op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>, - data: DATA, - ) { - assert!(id.is_local()); - - let entry = op(self, data); - let entry = self.lazy(entry); - self.entries_table.record(id, entry); - } - fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; - self.record(DefId::local(CRATE_DEF_INDEX), - EncodeContext::encode_info_for_mod, - (hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis)); + self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.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); @@ -486,8 +481,10 @@ impl<'tcx> EncodeContext<'tcx> { i = self.position(); - let entries_table = self.entries_table.encode(&mut self.opaque); - let entries_table_bytes = self.position() - i; + let per_def = LazyPerDefTables { + entry: self.per_def.entry.encode(&mut self.opaque), + }; + let per_def_bytes = self.position() - i; // Encode the proc macro data i = self.position(); @@ -546,7 +543,7 @@ impl<'tcx> EncodeContext<'tcx> { impls, exported_symbols, interpret_alloc_index, - entries_table, + per_def, }); let total_bytes = self.position(); @@ -571,7 +568,7 @@ impl<'tcx> EncodeContext<'tcx> { println!(" def-path table bytes: {}", def_path_table_bytes); println!(" proc-macro-data-bytes: {}", proc_macro_data_bytes); println!(" item bytes: {}", item_bytes); - println!(" entries table bytes: {}", entries_table_bytes); + println!(" per-def table bytes: {}", per_def_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -596,8 +593,9 @@ impl EncodeContext<'tcx> { fn encode_enum_variant_info( &mut self, - (enum_did, index): (DefId, VariantIdx), - ) -> Entry<'tcx> { + enum_did: DefId, + index: VariantIdx, + ) { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; @@ -619,7 +617,7 @@ impl EncodeContext<'tcx> { let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); let enum_vis = &tcx.hir().expect_item(enum_id).vis; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Variant(self.lazy(data)), visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), span: self.lazy(tcx.def_span(def_id)), @@ -644,13 +642,14 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn encode_enum_variant_ctor( &mut self, - (enum_did, index): (DefId, VariantIdx), - ) -> Entry<'tcx> { + enum_did: DefId, + index: VariantIdx, + ) { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; @@ -677,7 +676,7 @@ impl EncodeContext<'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Variant(self.lazy(data)), visibility: self.lazy(ctor_vis), span: self.lazy(tcx.def_span(def_id)), @@ -699,13 +698,16 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn encode_info_for_mod( &mut self, - (id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility), - ) -> Entry<'tcx> { + id: hir::HirId, + md: &hir::Mod, + attrs: &[ast::Attribute], + vis: &hir::Visibility, + ) { let tcx = self.tcx; let def_id = tcx.hir().local_def_id(id); debug!("EncodeContext::encode_info_for_mod({:?})", def_id); @@ -717,7 +719,7 @@ impl EncodeContext<'tcx> { }, }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Mod(self.lazy(data)), visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), span: self.lazy(tcx.def_span(def_id)), @@ -737,13 +739,15 @@ impl EncodeContext<'tcx> { mir: None, promoted_mir: None, - } + }) } fn encode_field( &mut self, - (adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize), - ) -> Entry<'tcx> { + adt_def_id: DefId, + variant_index: VariantIdx, + field_index: usize, + ) { let tcx = self.tcx; let variant = &tcx.adt_def(adt_def_id).variants[variant_index]; let field = &variant.fields[field_index]; @@ -754,7 +758,7 @@ impl EncodeContext<'tcx> { let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Field, visibility: self.lazy(field.vis), span: self.lazy(tcx.def_span(def_id)), @@ -772,10 +776,10 @@ impl EncodeContext<'tcx> { mir: None, promoted_mir: None, - } + }) } - fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> { + fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) { debug!("EncodeContext::encode_struct_ctor({:?})", def_id); let tcx = self.tcx; let adt_def = tcx.adt_def(adt_def_id); @@ -811,7 +815,7 @@ impl EncodeContext<'tcx> { let repr_options = get_repr_options(tcx, adt_def_id); - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Struct(self.lazy(data), repr_options), visibility: self.lazy(ctor_vis), span: self.lazy(tcx.def_span(def_id)), @@ -833,7 +837,7 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn encode_generics(&mut self, def_id: DefId) -> Lazy { @@ -854,7 +858,7 @@ impl EncodeContext<'tcx> { self.lazy(&*tcx.predicates_defined_on(def_id)) } - fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_trait_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; @@ -908,7 +912,7 @@ impl EncodeContext<'tcx> { ty::AssocKind::OpaqueTy => span_bug!(ast_item.span, "opaque type in trait"), }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(trait_item.vis), span: self.lazy(ast_item.span), @@ -943,7 +947,7 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn metadata_output_only(&self) -> bool { @@ -951,7 +955,7 @@ impl EncodeContext<'tcx> { !self.tcx.sess.opts.output_types.should_codegen() } - fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_impl_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; @@ -1014,7 +1018,7 @@ impl EncodeContext<'tcx> { hir::ImplItemKind::TyAlias(..) => false, }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(impl_item.vis), span: self.lazy(ast_item.span), @@ -1036,7 +1040,7 @@ impl EncodeContext<'tcx> { mir: if mir { self.encode_optimized_mir(def_id) } else { None }, promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, - } + }) } fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) @@ -1110,7 +1114,7 @@ impl EncodeContext<'tcx> { self.lazy(rendered_const) } - fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { + fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { let tcx = self.tcx; debug!("EncodeContext::encode_info_for_item({:?})", def_id); @@ -1136,7 +1140,7 @@ impl EncodeContext<'tcx> { EntryKind::Fn(self.lazy(data)) } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis)); + return self.encode_info_for_mod(item.hir_id, m, &item.attrs, &item.vis); } hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, @@ -1245,7 +1249,7 @@ impl EncodeContext<'tcx> { _ => false, }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), span: self.lazy(item.span), @@ -1340,20 +1344,22 @@ impl EncodeContext<'tcx> { // necessary.) predicates_defined_on: match item.kind { hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)), + hir::ItemKind::TraitAlias(..) => { + Some(self.encode_predicates_defined_on(def_id)) + } _ => None, // not *wrong* for other kinds of items, but not needed }, mir: if mir { self.encode_optimized_mir(def_id) } else { None }, promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, - } + }) } /// Serialize the text of exported macros - fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> { + fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) { use syntax::print::pprust; let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::MacroDef(self.lazy(MacroDef { body: pprust::tts_to_string(macro_def.body.clone()), legacy: macro_def.legacy, @@ -1373,7 +1379,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: None, promoted_mir: None, - } + }) } fn encode_info_for_generic_param( @@ -1381,9 +1387,9 @@ impl EncodeContext<'tcx> { def_id: DefId, entry_kind: EntryKind<'tcx>, encode_type: bool, - ) -> Entry<'tcx> { + ) { let tcx = self.tcx; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: entry_kind, visibility: self.lazy(ty::Visibility::Public), span: self.lazy(tcx.def_span(def_id)), @@ -1400,26 +1406,10 @@ impl EncodeContext<'tcx> { mir: None, promoted_mir: None, - } + }) } - fn encode_info_for_ty_param( - &mut self, - (def_id, encode_type): (DefId, bool), - ) -> Entry<'tcx> { - debug!("EncodeContext::encode_info_for_ty_param({:?})", def_id); - self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type) - } - - fn encode_info_for_const_param( - &mut self, - def_id: DefId, - ) -> Entry<'tcx> { - debug!("EncodeContext::encode_info_for_const_param({:?})", def_id); - self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true) - } - - fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_closure(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_closure({:?})", def_id); let tcx = self.tcx; @@ -1443,7 +1433,7 @@ impl EncodeContext<'tcx> { _ => bug!("closure that is neither generator nor closure") }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(ty::Visibility::Public), span: self.lazy(tcx.def_span(def_id)), @@ -1461,10 +1451,10 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } - fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_anon_const(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); let tcx = self.tcx; let id = tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -1472,7 +1462,7 @@ impl EncodeContext<'tcx> { let const_data = self.encode_rendered_const_for_body(body_id); let mir = tcx.mir_const_qualif(def_id).0; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind: EntryKind::Const(ConstQualif { mir }, const_data), visibility: self.lazy(ty::Visibility::Public), span: self.lazy(tcx.def_span(def_id)), @@ -1490,7 +1480,7 @@ impl EncodeContext<'tcx> { mir: self.encode_optimized_mir(def_id), promoted_mir: self.encode_promoted_mir(def_id), - } + }) } fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> Lazy<[ast::Attribute]> { @@ -1668,9 +1658,11 @@ impl EncodeContext<'tcx> { Lazy::empty() } - fn encode_info_for_foreign_item(&mut self, - (def_id, nitem): (DefId, &hir::ForeignItem)) - -> Entry<'tcx> { + fn encode_info_for_foreign_item( + &mut self, + def_id: DefId, + nitem: &hir::ForeignItem, + ) { let tcx = self.tcx; debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id); @@ -1690,7 +1682,7 @@ impl EncodeContext<'tcx> { hir::ForeignItemKind::Type => EntryKind::ForeignType, }; - Entry { + record!(self.per_def.entry[def_id] <- Entry { kind, visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), span: self.lazy(nitem.span), @@ -1711,10 +1703,11 @@ impl EncodeContext<'tcx> { mir: None, promoted_mir: None, - } + }) } } +// FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR. impl Visitor<'tcx> for EncodeContext<'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::OnlyBodies(&self.tcx.hir()) @@ -1726,7 +1719,7 @@ impl Visitor<'tcx> for EncodeContext<'tcx> { fn visit_anon_const(&mut self, c: &'tcx AnonConst) { intravisit::walk_anon_const(self, c); let def_id = self.tcx.hir().local_def_id(c.hir_id); - self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); + self.encode_info_for_anon_const(def_id); } fn visit_item(&mut self, item: &'tcx hir::Item) { intravisit::walk_item(self, item); @@ -1734,24 +1727,21 @@ impl Visitor<'tcx> for EncodeContext<'tcx> { match item.kind { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these - _ => self.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)), + _ => self.encode_info_for_item(def_id, item), } self.encode_addl_info_for_item(item); } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { intravisit::walk_foreign_item(self, ni); let def_id = self.tcx.hir().local_def_id(ni.hir_id); - self.record(def_id, - EncodeContext::encode_info_for_foreign_item, - (def_id, ni)); + self.encode_info_for_foreign_item(def_id, ni); } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { intravisit::walk_generics(self, generics); self.encode_info_for_generics(generics); } fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { - let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); - self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def); + self.encode_info_for_macro_def(macro_def); } } @@ -1759,10 +1749,10 @@ impl EncodeContext<'tcx> { fn encode_fields(&mut self, adt_def_id: DefId) { let def = self.tcx.adt_def(adt_def_id); for (variant_index, variant) in def.variants.iter_enumerated() { - for (field_index, field) in variant.fields.iter().enumerate() { - self.record(field.did, - EncodeContext::encode_field, - (adt_def_id, variant_index, field_index)); + for (field_index, _field) in variant.fields.iter().enumerate() { + // FIXME(eddyb) `adt_def_id` is leftover from incremental isolation, + // pass `def`, `variant` or `field` instead. + self.encode_field(adt_def_id, variant_index, field_index); } } } @@ -1773,14 +1763,14 @@ impl EncodeContext<'tcx> { match param.kind { GenericParamKind::Lifetime { .. } => continue, GenericParamKind::Type { ref default, .. } => { - self.record( + self.encode_info_for_generic_param( def_id, - EncodeContext::encode_info_for_ty_param, - (def_id, default.is_some()), + EntryKind::TypeParam, + default.is_some(), ); } GenericParamKind::Const { .. } => { - self.record(def_id, EncodeContext::encode_info_for_const_param, def_id); + self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); } } } @@ -1790,7 +1780,7 @@ impl EncodeContext<'tcx> { match expr.kind { hir::ExprKind::Closure(..) => { let def_id = self.tcx.hir().local_def_id(expr.hir_id); - self.record(def_id, EncodeContext::encode_info_for_closure, def_id); + self.encode_info_for_closure(def_id); } _ => {} } @@ -1821,14 +1811,14 @@ impl EncodeContext<'tcx> { let def = self.tcx.adt_def(def_id); for (i, variant) in def.variants.iter_enumerated() { - self.record(variant.def_id, - EncodeContext::encode_enum_variant_info, - (def_id, i)); + // FIXME(eddyb) `def_id` is leftover from incremental isolation, + // pass `def` or `variant` instead. + self.encode_enum_variant_info(def_id, i); - if let Some(ctor_def_id) = variant.ctor_def_id { - self.record(ctor_def_id, - EncodeContext::encode_enum_variant_ctor, - (def_id, i)); + // FIXME(eddyb) `def_id` is leftover from incremental isolation, + // pass `def`, `variant` or `ctor_def_id` instead. + if let Some(_ctor_def_id) = variant.ctor_def_id { + self.encode_enum_variant_ctor(def_id, i); } } } @@ -1838,9 +1828,7 @@ impl EncodeContext<'tcx> { // If the struct has a constructor, encode it. if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id); - self.record(ctor_def_id, - EncodeContext::encode_struct_ctor, - (def_id, ctor_def_id)); + self.encode_struct_ctor(def_id, ctor_def_id); } } hir::ItemKind::Union(..) => { @@ -1848,16 +1836,12 @@ impl EncodeContext<'tcx> { } hir::ItemKind::Impl(..) => { for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.record(trait_item_def_id, - EncodeContext::encode_info_for_impl_item, - trait_item_def_id); + self.encode_info_for_impl_item(trait_item_def_id); } } hir::ItemKind::Trait(..) => { for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.record(item_def_id, - EncodeContext::encode_info_for_trait_item, - item_def_id); + self.encode_info_for_trait_item(item_def_id); } } } @@ -1925,7 +1909,9 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { let mut ecx = EncodeContext { opaque: encoder, tcx, - entries_table: PerDefTable::new(tcx.hir().definitions().def_index_count()), + per_def: PerDefTables { + entry: PerDefTable::new(tcx.hir().definitions().def_index_count()), + }, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index dffc8f33b2de..9d6748732b8b 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -197,7 +197,7 @@ crate struct CrateRoot<'tcx> { pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy!(PerDefTable>), + pub per_def: LazyPerDefTables<'tcx>, /// The DefIndex's of any proc macros delcared by /// this crate @@ -227,6 +227,11 @@ crate struct TraitImpls { pub impls: Lazy<[DefIndex]>, } +#[derive(RustcEncodable, RustcDecodable)] +crate struct LazyPerDefTables<'tcx> { + pub entry: Lazy!(PerDefTable>), +} + #[derive(RustcEncodable, RustcDecodable)] crate struct Entry<'tcx> { pub kind: EntryKind<'tcx>, @@ -245,7 +250,7 @@ crate struct Entry<'tcx> { pub predicates_defined_on: Option)>, pub mir: Option)>, - pub promoted_mir: Option>>>, + pub promoted_mir: Option>)>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] From cef495028019b5bbb380bfa1d7a10e9e06dbf166 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 Apr 2019 23:30:53 +0300 Subject: [PATCH 403/545] rustc_metadata: generalize Table to hold T, not Lazy, elements. --- src/librustc_metadata/decoder.rs | 6 +- src/librustc_metadata/encoder.rs | 10 +-- src/librustc_metadata/schema.rs | 2 +- src/librustc_metadata/table.rs | 108 ++++++++++++++++++++----------- 4 files changed, 78 insertions(+), 48 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 7ba395a1bd50..f1ae04875298 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -2,7 +2,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob}; use crate::schema::*; -use crate::table::PerDefTable; +use crate::table::{FixedSizeEncoding, PerDefTable}; use rustc_index::vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; @@ -256,7 +256,7 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, } impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> - where T: LazyMeta, + where Option: FixedSizeEncoding, { fn specialized_decode(&mut self) -> Result>, Self::Error> { let len = self.read_usize()?; @@ -481,7 +481,7 @@ impl<'a, 'tcx> CrateMetadata { } fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - self.root.per_def.entry.lookup(self.blob.raw_bytes(), item_id) + self.root.per_def.entry.get(self.blob.raw_bytes(), item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 51634e372a2c..c9426aaece94 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,5 +1,5 @@ use crate::schema::*; -use crate::table::PerDefTable; +use crate::table::{FixedSizeEncoding, PerDefTable}; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -61,7 +61,7 @@ struct EncodeContext<'tcx> { } struct PerDefTables<'tcx> { - entry: PerDefTable>, + entry: PerDefTable>>, } macro_rules! encoder_methods { @@ -119,7 +119,7 @@ impl<'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'tcx> { } impl<'tcx, T> SpecializedEncoder>> for EncodeContext<'tcx> - where T: LazyMeta, + where Option: FixedSizeEncoding, { fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta)?; @@ -280,14 +280,14 @@ impl EncodeContentsForLazy<[T]> for I } } -// Shorthand for `$self.$tables.$table.record($key, $self.lazy($value))`, which would +// Shorthand for `$self.$tables.$table.set($key, $self.lazy($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record { ($self:ident.$tables:ident.$table:ident[$key:expr] <- $value:expr) => {{ { let value = $value; let lazy = $self.lazy(value); - $self.$tables.$table.record($key, lazy); + $self.$tables.$table.set($key, lazy); } }} } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 9d6748732b8b..e70ba2532caa 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -229,7 +229,7 @@ crate struct TraitImpls { #[derive(RustcEncodable, RustcDecodable)] crate struct LazyPerDefTables<'tcx> { - pub entry: Lazy!(PerDefTable>), + pub entry: Lazy!(PerDefTable>>), } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index c60c8e2cbce5..c069ea2830c1 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -8,7 +8,10 @@ use std::num::NonZeroUsize; use log::debug; /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. -trait FixedSizeEncoding { +/// Used mainly for Lazy positions and lengths. +/// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`, +/// but this has no impact on safety. +crate trait FixedSizeEncoding: Default { const BYTE_LEN: usize; // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead, @@ -38,7 +41,7 @@ macro_rules! fixed_size_encoding_byte_len_and_defaults { b.len() / BYTE_LEN, ) }; - Self::from_bytes(&b[i]) + FixedSizeEncoding::from_bytes(&b[i]) } fn write_to_bytes_at(self, b: &mut [u8], i: usize) { const BYTE_LEN: usize = $byte_len; @@ -69,37 +72,69 @@ impl FixedSizeEncoding for u32 { } } -/// Random-access position table, allowing encoding in an arbitrary order -/// (e.g. while visiting the definitions of a crate), and on-demand decoding -/// of specific indices (e.g. queries for per-definition data). -/// Similar to `Vec>`, but with zero-copy decoding. -// FIXME(eddyb) newtype `[u8]` here, such that `Box>` would be used +// NOTE(eddyb) there could be an impl for `usize`, which would enable a more +// generic `Lazy` impl, but in the general case we might not need / want to +// fit every `usize` in `u32`. +impl FixedSizeEncoding for Option> { + fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN); + + fn from_bytes(b: &[u8]) -> Self { + Some(Lazy::from_position(NonZeroUsize::new(u32::from_bytes(b) as usize)?)) + } + + fn write_to_bytes(self, b: &mut [u8]) { + let position = self.map_or(0, |lazy| lazy.position.get()); + let position: u32 = position.try_into().unwrap(); + + position.write_to_bytes(b) + } +} + +impl FixedSizeEncoding for Option> { + fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2); + + fn from_bytes(b: &[u8]) -> Self { + Some(Lazy::from_position_and_meta( + >>::from_bytes(b)?.position, + u32::from_bytes(&b[u32::BYTE_LEN..]) as usize, + )) + } + + fn write_to_bytes(self, b: &mut [u8]) { + self.map(|lazy| Lazy::::from_position(lazy.position)) + .write_to_bytes(b); + + let len = self.map_or(0, |lazy| lazy.meta); + let len: u32 = len.try_into().unwrap(); + + len.write_to_bytes(&mut b[u32::BYTE_LEN..]); + } +} + +/// Random-access table, similar to `Vec>`, but without requiring +/// encoding or decoding all the values eagerly and in-order. +// FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box>` would be used // when building it, and `Lazy>` or `&Table` when reading it. // Sadly, that doesn't work for `DefPerTable`, which is `(Table, Table)`, // and so would need two lengths in its metadata, which is not supported yet. -crate struct Table> { +crate struct Table where Option: FixedSizeEncoding { + // FIXME(eddyb) store `[u8; >::BYTE_LEN]` instead of `u8` in `Vec`, + // once that starts being allowed by the compiler (i.e. lazy normalization). bytes: Vec, _marker: PhantomData, } -impl> Table { +impl Table where Option: FixedSizeEncoding { crate fn new(len: usize) -> Self { Table { - bytes: vec![0; len * 4], + // FIXME(eddyb) only allocate and encode as many entries as needed. + bytes: vec![0; len * >::BYTE_LEN], _marker: PhantomData, } } - crate fn record(&mut self, i: usize, entry: Lazy) { - let position: u32 = entry.position.get().try_into().unwrap(); - - assert!(u32::read_from_bytes_at(&self.bytes, i) == 0, - "recorded position for index {:?} twice, first at {:?} and now at {:?}", - i, - u32::read_from_bytes_at(&self.bytes, i), - position); - - position.write_to_bytes_at(&mut self.bytes, i) + crate fn set(&mut self, i: usize, value: T) { + Some(value).write_to_bytes_at(&mut self.bytes, i); } crate fn encode(&self, buf: &mut Encoder) -> Lazy { @@ -112,7 +147,7 @@ impl> Table { } } -impl> LazyMeta for Table { +impl LazyMeta for Table where Option: FixedSizeEncoding { type Meta = usize; fn min_size(len: usize) -> usize { @@ -120,34 +155,29 @@ impl> LazyMeta for Table { } } -impl Lazy> { - /// Given the metadata, extract out the offset of a particular index (if any). +impl Lazy> where Option: FixedSizeEncoding { + /// Given the metadata, extract out the value at a particular index (if any). #[inline(never)] - crate fn lookup(&self, bytes: &[u8], i: usize) -> Option> { + crate fn get(&self, bytes: &[u8], i: usize) -> Option { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - let bytes = &bytes[self.position.get()..][..self.meta]; - let position = u32::read_from_bytes_at(bytes, i); - debug!("Table::lookup: position={:?}", position); - - NonZeroUsize::new(position as usize).map(Lazy::from_position) + >::read_from_bytes_at(&bytes[self.position.get()..][..self.meta], i) } } - /// Per-definition table, similar to `Table` but keyed on `DefIndex`. // FIXME(eddyb) replace by making `Table` behave like `IndexVec`, // and by using `newtype_index!` to define `DefIndex`. -crate struct PerDefTable>(Table); +crate struct PerDefTable(Table) where Option: FixedSizeEncoding; -impl> PerDefTable { +impl PerDefTable where Option: FixedSizeEncoding { crate fn new(def_index_count: usize) -> Self { PerDefTable(Table::new(def_index_count)) } - crate fn record(&mut self, def_id: DefId, entry: Lazy) { + crate fn set(&mut self, def_id: DefId, value: T) { assert!(def_id.is_local()); - self.0.record(def_id.index.index(), entry); + self.0.set(def_id.index.index(), value); } crate fn encode(&self, buf: &mut Encoder) -> Lazy { @@ -156,7 +186,7 @@ impl> PerDefTable { } } -impl> LazyMeta for PerDefTable { +impl LazyMeta for PerDefTable where Option: FixedSizeEncoding { type Meta = as LazyMeta>::Meta; fn min_size(meta: Self::Meta) -> usize { @@ -164,14 +194,14 @@ impl> LazyMeta for PerDefTable { } } -impl Lazy> { +impl Lazy> where Option: FixedSizeEncoding { fn as_table(&self) -> Lazy> { Lazy::from_position_and_meta(self.position, self.meta) } - /// Given the metadata, extract out the offset of a particular DefIndex (if any). + /// Given the metadata, extract out the value at a particular DefIndex (if any). #[inline(never)] - crate fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { - self.as_table().lookup(bytes, def_index.index()) + crate fn get(&self, bytes: &[u8], def_index: DefIndex) -> Option { + self.as_table().get(bytes, def_index.index()) } } From 972b93b20e2d21307622eacb812d8a552ecf0f81 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 14 Apr 2019 01:36:08 +0300 Subject: [PATCH 404/545] rustc_metadata: use decoder::Metadata instead of &[u8] for Lazy>::get. --- src/librustc_metadata/decoder.rs | 10 +++++----- src/librustc_metadata/table.rs | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f1ae04875298..6da936374c78 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -132,8 +132,8 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) { } impl<'a, 'tcx, T: Encodable + Decodable> Lazy { - crate fn decode>(self, meta: M) -> T { - let mut dcx = meta.decoder(self.position.get()); + crate fn decode>(self, metadata: M) -> T { + let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); T::decode(&mut dcx).unwrap() } @@ -142,9 +142,9 @@ impl<'a, 'tcx, T: Encodable + Decodable> Lazy { impl<'a: 'x, 'tcx: 'x, 'x, T: Encodable + Decodable> Lazy<[T]> { crate fn decode>( self, - meta: M, + metadata: M, ) -> impl ExactSizeIterator + Captures<'a> + Captures<'tcx> + 'x { - let mut dcx = meta.decoder(self.position.get()); + let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } @@ -481,7 +481,7 @@ impl<'a, 'tcx> CrateMetadata { } fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - self.root.per_def.entry.get(self.blob.raw_bytes(), item_id) + self.root.per_def.entry.get(self, item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index c069ea2830c1..0585aa1d3884 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -1,3 +1,4 @@ +use crate::decoder::Metadata; use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex}; @@ -158,10 +159,15 @@ impl LazyMeta for Table where Option: FixedSizeEncoding { impl Lazy> where Option: FixedSizeEncoding { /// Given the metadata, extract out the value at a particular index (if any). #[inline(never)] - crate fn get(&self, bytes: &[u8], i: usize) -> Option { + crate fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>( + &self, + metadata: M, + i: usize, + ) -> Option { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - >::read_from_bytes_at(&bytes[self.position.get()..][..self.meta], i) + let bytes = &metadata.raw_bytes()[self.position.get()..][..self.meta]; + >::read_from_bytes_at(bytes, i) } } @@ -201,7 +207,11 @@ impl Lazy> where Option: FixedSizeEncoding { /// Given the metadata, extract out the value at a particular DefIndex (if any). #[inline(never)] - crate fn get(&self, bytes: &[u8], def_index: DefIndex) -> Option { - self.as_table().get(bytes, def_index.index()) + crate fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>( + &self, + metadata: M, + def_index: DefIndex, + ) -> Option { + self.as_table().get(metadata, def_index.index()) } } From ee747f645ffdfcea4f39ad4ccc4d83742a4ea3aa Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 14 Apr 2019 04:19:28 +0300 Subject: [PATCH 405/545] rustc_metadata: replace Entry table with one table for each of its fields (AoS -> SoA). --- src/librustc_metadata/decoder.rs | 190 +++---- src/librustc_metadata/encoder.rs | 833 +++++++++++++------------------ src/librustc_metadata/schema.rs | 35 +- 3 files changed, 465 insertions(+), 593 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 6da936374c78..962846b04753 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -473,27 +473,20 @@ impl<'a, 'tcx> CrateMetadata { self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some() } - fn entry_unless_proc_macro(&self, id: DefIndex) -> Option> { - match self.is_proc_macro(id) { - true => None, - false => Some(self.entry(id)), - } + fn maybe_kind(&self, item_id: DefIndex) -> Option> { + self.root.per_def.kind.get(self, item_id).map(|k| k.decode(self)) } - fn maybe_entry(&self, item_id: DefIndex) -> Option>> { - self.root.per_def.entry.get(self, item_id) - } - - fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { - match self.maybe_entry(item_id) { - None => { - bug!("entry: id not found: {:?} in crate {:?} with number {}", - item_id, - self.root.name, - self.cnum) - } - Some(d) => d.decode(self), - } + fn kind(&self, item_id: DefIndex) -> EntryKind<'tcx> { + assert!(!self.is_proc_macro(item_id)); + self.maybe_kind(item_id).unwrap_or_else(|| { + bug!( + "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}", + item_id, + self.root.name, + self.cnum, + ) + }) } fn local_def_id(&self, index: DefIndex) -> DefId { @@ -529,7 +522,7 @@ impl<'a, 'tcx> CrateMetadata { crate fn def_kind(&self, index: DefIndex) -> Option { if !self.is_proc_macro(index) { - self.entry(index).kind.def_kind() + self.kind(index).def_kind() } else { Some(DefKind::Macro( macro_kind(self.raw_proc_macro(index)) @@ -538,7 +531,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_span(&self, index: DefIndex, sess: &Session) -> Span { - self.entry(index).span.decode((self, sess)) + self.root.per_def.span.get(self, index).unwrap().decode((self, sess)) } crate fn load_proc_macro(&self, id: DefIndex, sess: &Session) -> SyntaxExtension { @@ -567,12 +560,12 @@ impl<'a, 'tcx> CrateMetadata { helper_attrs, self.root.edition, Symbol::intern(name), - &self.get_attributes(&self.entry(id), sess), + &self.get_item_attrs(id, sess), ) } crate fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { - match self.entry(item_id).kind { + match self.kind(item_id) { EntryKind::Trait(data) => { let data = data.decode((self, sess)); ty::TraitDef::new(self.local_def_id(item_id), @@ -597,18 +590,24 @@ impl<'a, 'tcx> CrateMetadata { fn get_variant( &self, tcx: TyCtxt<'tcx>, - item: &Entry<'_>, + kind: &EntryKind<'_>, index: DefIndex, parent_did: DefId, - adt_kind: ty::AdtKind, ) -> ty::VariantDef { - let data = match item.kind { + let data = match kind { EntryKind::Variant(data) | EntryKind::Struct(data, _) | EntryKind::Union(data, _) => data.decode(self), _ => bug!(), }; + let adt_kind = match kind { + EntryKind::Variant(_) => ty::AdtKind::Enum, + EntryKind::Struct(..) => ty::AdtKind::Struct, + EntryKind::Union(..) => ty::AdtKind::Union, + _ => bug!(), + }; + let variant_did = if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { @@ -622,14 +621,12 @@ impl<'a, 'tcx> CrateMetadata { variant_did, ctor_did, data.discr, - item.children.decode(self).map(|index| { - let f = self.entry(index); - ty::FieldDef { + self.root.per_def.children.get(self, index).unwrap_or(Lazy::empty()) + .decode(self).map(|index| ty::FieldDef { did: self.local_def_id(index), ident: Ident::with_dummy_span(self.item_name(index)), - vis: f.visibility.decode(self) - } - }).collect(), + vis: self.get_visibility(index), + }).collect(), data.ctor_kind, adt_kind, parent_did, @@ -638,28 +635,28 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::AdtDef { - let item = self.entry(item_id); + let kind = self.kind(item_id); let did = self.local_def_id(item_id); - let (kind, repr) = match item.kind { + let (adt_kind, repr) = match kind { EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr), EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr), EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr), _ => bug!("get_adt_def called on a non-ADT {:?}", did), }; - let variants = if let ty::AdtKind::Enum = kind { - item.children + let variants = if let ty::AdtKind::Enum = adt_kind { + self.root.per_def.children.get(self, item_id).unwrap_or(Lazy::empty()) .decode(self) .map(|index| { - self.get_variant(tcx, &self.entry(index), index, did, kind) + self.get_variant(tcx, &self.kind(index), index, did) }) .collect() } else { - std::iter::once(self.get_variant(tcx, &item, item_id, did, kind)).collect() + std::iter::once(self.get_variant(tcx, &kind, item_id, did)).collect() }; - tcx.alloc_adt_def(did, kind, variants, repr) + tcx.alloc_adt_def(did, adt_kind, variants, repr) } crate fn get_predicates( @@ -667,7 +664,7 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - self.entry(item_id).predicates.unwrap().decode((self, tcx)) + self.root.per_def.predicates.get(self, item_id).unwrap().decode((self, tcx)) } crate fn get_predicates_defined_on( @@ -675,7 +672,7 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - self.entry(item_id).predicates_defined_on.unwrap().decode((self, tcx)) + self.root.per_def.predicates_defined_on.get(self, item_id).unwrap().decode((self, tcx)) } crate fn get_super_predicates( @@ -683,7 +680,7 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, tcx: TyCtxt<'tcx>, ) -> ty::GenericPredicates<'tcx> { - let super_predicates = match self.entry(item_id).kind { + let super_predicates = match self.kind(item_id) { EntryKind::Trait(data) => data.decode(self).super_predicates, EntryKind::TraitAlias(data) => data.decode(self).super_predicates, _ => bug!("def-index does not refer to trait or trait alias"), @@ -693,34 +690,35 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_generics(&self, item_id: DefIndex, sess: &Session) -> ty::Generics { - self.entry(item_id).generics.unwrap().decode((self, sess)) + self.root.per_def.generics.get(self, item_id).unwrap().decode((self, sess)) } crate fn get_type(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { - self.entry(id).ty.unwrap().decode((self, tcx)) + self.root.per_def.ty.get(self, id).unwrap().decode((self, tcx)) } crate fn get_stability(&self, id: DefIndex) -> Option { match self.is_proc_macro(id) { true => self.root.proc_macro_stability.clone(), - false => self.entry(id).stability.map(|stab| stab.decode(self)), + false => self.root.per_def.stability.get(self, id).map(|stab| stab.decode(self)), } } crate fn get_deprecation(&self, id: DefIndex) -> Option { - self.entry_unless_proc_macro(id) - .and_then(|entry| entry.deprecation.map(|depr| depr.decode(self))) + self.root.per_def.deprecation.get(self, id) + .filter(|_| !self.is_proc_macro(id)) + .map(|depr| depr.decode(self)) } crate fn get_visibility(&self, id: DefIndex) -> ty::Visibility { match self.is_proc_macro(id) { true => ty::Visibility::Public, - false => self.entry(id).visibility.decode(self), + false => self.root.per_def.visibility.get(self, id).unwrap().decode(self), } } fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Impl(data) => data.decode(self), _ => bug!(), } @@ -816,38 +814,42 @@ impl<'a, 'tcx> CrateMetadata { } // Find the item. - let item = match self.maybe_entry(id) { + let kind = match self.maybe_kind(id) { None => return, - Some(item) => item.decode((self, sess)), + Some(kind) => kind, }; // Iterate over all children. let macros_only = self.dep_kind.lock().macros_only(); - for child_index in item.children.decode((self, sess)) { + let children = self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty()); + for child_index in children.decode((self, sess)) { if macros_only { continue } // Get the item. - if let Some(child) = self.maybe_entry(child_index) { - let child = child.decode((self, sess)); - match child.kind { + if let Some(child_kind) = self.maybe_kind(child_index) { + match child_kind { EntryKind::MacroDef(..) => {} _ if macros_only => continue, _ => {} } // Hand off the item to the callback. - match child.kind { + match child_kind { // FIXME(eddyb) Don't encode these in children. EntryKind::ForeignMod => { - for child_index in child.children.decode((self, sess)) { + let child_children = + self.root.per_def.children.get(self, child_index) + .unwrap_or(Lazy::empty()); + for child_index in child_children.decode((self, sess)) { if let Some(kind) = self.def_kind(child_index) { callback(def::Export { res: Res::Def(kind, self.local_def_id(child_index)), ident: Ident::with_dummy_span(self.item_name(child_index)), vis: self.get_visibility(child_index), - span: self.entry(child_index).span.decode((self, sess)), + span: self.root.per_def.span.get(self, child_index).unwrap() + .decode((self, sess)), }); } } @@ -859,7 +861,7 @@ impl<'a, 'tcx> CrateMetadata { } let def_key = self.def_key(child_index); - let span = child.span.decode((self, sess)); + let span = self.get_span(child_index, sess); if let (Some(kind), Some(name)) = (self.def_kind(child_index), def_key.disambiguated_data.data.get_opt_name()) { let ident = Ident::from_interned_str(name); @@ -912,7 +914,7 @@ impl<'a, 'tcx> CrateMetadata { } } - if let EntryKind::Mod(data) = item.kind { + if let EntryKind::Mod(data) = kind { for exp in data.decode((self, sess)).reexports.decode((self, sess)) { match exp.res { Res::Def(DefKind::Macro(..), _) => {} @@ -926,15 +928,16 @@ impl<'a, 'tcx> CrateMetadata { crate fn is_item_mir_available(&self, id: DefIndex) -> bool { !self.is_proc_macro(id) && - self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() + self.root.per_def.mir.get(self, id).is_some() } crate fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { - self.entry_unless_proc_macro(id) - .and_then(|entry| entry.mir.map(|mir| mir.decode((self, tcx)))) + self.root.per_def.mir.get(self, id) + .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { bug!("get_optimized_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) + .decode((self, tcx)) } crate fn get_promoted_mir( @@ -942,15 +945,16 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, id: DefIndex, ) -> IndexVec> { - self.entry_unless_proc_macro(id) - .and_then(|entry| entry.promoted_mir.map(|promoted| promoted.decode((self, tcx)))) + self.root.per_def.promoted_mir.get(self, id) + .filter(|_| !self.is_proc_macro(id)) .unwrap_or_else(|| { bug!("get_promoted_mir: missing MIR for `{:?}`", self.local_def_id(id)) }) + .decode((self, tcx)) } crate fn mir_const_qualif(&self, id: DefIndex) -> u8 { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Const(qualif, _) | EntryKind::AssocConst(AssocContainer::ImplDefault, qualif, _) | EntryKind::AssocConst(AssocContainer::ImplFinal, qualif, _) => { @@ -961,12 +965,11 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem { - let item = self.entry(id); let def_key = self.def_key(id); let parent = self.local_def_id(def_key.parent.unwrap()); let name = def_key.disambiguated_data.data.get_opt_name().unwrap(); - let (kind, container, has_self) = match item.kind { + let (kind, container, has_self) = match self.kind(id) { EntryKind::AssocConst(container, _, _) => { (ty::AssocKind::Const, container, false) } @@ -986,7 +989,7 @@ impl<'a, 'tcx> CrateMetadata { ty::AssocItem { ident: Ident::from_interned_str(name), kind, - vis: item.visibility.decode(self), + vis: self.get_visibility(id), defaultness: container.defaultness(), def_id: self.local_def_id(id), container: container.with_def_id(parent), @@ -995,11 +998,12 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_item_variances(&self, id: DefIndex) -> Vec { - self.entry(id).variances.decode(self).collect() + self.root.per_def.variances.get(self, id).unwrap_or(Lazy::empty()) + .decode(self).collect() } crate fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { - match self.entry(node_id).kind { + match self.kind(node_id) { EntryKind::Struct(data, _) | EntryKind::Union(data, _) | EntryKind::Variant(data) => data.decode(self).ctor_kind, @@ -1008,7 +1012,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { - match self.entry(node_id).kind { + match self.kind(node_id) { EntryKind::Struct(data, _) => { data.decode(self).ctor.map(|index| self.local_def_id(index)) } @@ -1030,8 +1034,9 @@ impl<'a, 'tcx> CrateMetadata { node_id }; - let item = self.entry(item_id); - Lrc::from(self.get_attributes(&item, sess)) + Lrc::from(self.root.per_def.attributes.get(self, item_id).unwrap_or(Lazy::empty()) + .decode((self, sess)) + .collect::>()) } crate fn get_struct_field_names( @@ -1039,17 +1044,12 @@ impl<'a, 'tcx> CrateMetadata { id: DefIndex, sess: &Session, ) -> Vec> { - self.entry(id) - .children + self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty()) .decode(self) .map(|index| respan(self.get_span(index, sess), self.item_name(index))) .collect() } - fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec { - item.attributes.decode((self, sess)).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 { @@ -1070,10 +1070,11 @@ impl<'a, 'tcx> CrateMetadata { tcx: TyCtxt<'tcx>, id: DefIndex, ) -> &'tcx [DefId] { - tcx.arena.alloc_from_iter(self.entry(id) - .inherent_impls - .decode(self) - .map(|index| self.local_def_id(index))) + tcx.arena.alloc_from_iter( + self.root.per_def.inherent_impls.get(self, id).unwrap_or(Lazy::empty()) + .decode(self) + .map(|index| self.local_def_id(index)) + ) } crate fn get_implementations_for_trait( @@ -1115,7 +1116,7 @@ impl<'a, 'tcx> CrateMetadata { _ => return None, } def_key.parent.and_then(|parent_index| { - match self.entry(parent_index).kind { + match self.kind(parent_index) { EntryKind::Trait(_) | EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)), _ => None, @@ -1168,7 +1169,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_fn_param_names(&self, id: DefIndex) -> Vec { - let param_names = match self.entry(id).kind { + 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, @@ -1191,7 +1192,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_rendered_const(&self, id: DefIndex) -> String { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Const(_, data) | EntryKind::AssocConst(_, _, data) => data.decode(self).0, _ => bug!(), @@ -1199,15 +1200,14 @@ impl<'a, 'tcx> CrateMetadata { } crate fn get_macro(&self, id: DefIndex) -> MacroDef { - let entry = self.entry(id); - match entry.kind { + match self.kind(id) { EntryKind::MacroDef(macro_def) => macro_def.decode(self), _ => bug!(), } } crate fn is_const_fn_raw(&self, id: DefIndex) -> bool { - let constness = match self.entry(id).kind { + let constness = match self.kind(id) { EntryKind::Method(data) => data.decode(self).fn_data.constness, EntryKind::Fn(data) => data.decode(self).constness, EntryKind::Variant(..) | EntryKind::Struct(..) => hir::Constness::Const, @@ -1217,16 +1217,16 @@ impl<'a, 'tcx> CrateMetadata { } crate fn asyncness(&self, id: DefIndex) -> hir::IsAsync { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Fn(data) => data.decode(self).asyncness, EntryKind::Method(data) => data.decode(self).fn_data.asyncness, EntryKind::ForeignFn(data) => data.decode(self).asyncness, - _ => bug!("asyncness: expect functions entry."), + _ => bug!("asyncness: expected function kind"), } } crate fn is_foreign_item(&self, id: DefIndex) -> bool { - match self.entry(id).kind { + match self.kind(id) { EntryKind::ForeignImmStatic | EntryKind::ForeignMutStatic | EntryKind::ForeignFn(_) => true, @@ -1235,7 +1235,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn static_mutability(&self, id: DefIndex) -> Option { - match self.entry(id).kind { + match self.kind(id) { EntryKind::ImmStatic | EntryKind::ForeignImmStatic => Some(hir::MutImmutable), EntryKind::MutStatic | @@ -1245,7 +1245,7 @@ impl<'a, 'tcx> CrateMetadata { } crate fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { - let sig = match self.entry(id).kind { + let sig = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).sig, EntryKind::Method(data) => data.decode(self).fn_data.sig, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c9426aaece94..3bc3fee4164f 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -15,7 +15,7 @@ use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, use rustc::middle::lang_items; use rustc::mir::{self, interpret}; use rustc::traits::specialization_graph; -use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName}; +use rustc::ty::{self, Ty, TyCtxt, SymbolName}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::ty::layout::VariantIdx; @@ -61,7 +61,23 @@ struct EncodeContext<'tcx> { } struct PerDefTables<'tcx> { - entry: PerDefTable>>, + kind: PerDefTable>>, + visibility: PerDefTable>, + span: PerDefTable>, + attributes: PerDefTable>, + children: PerDefTable>, + stability: PerDefTable>, + deprecation: PerDefTable>, + + ty: PerDefTable>>, + inherent_impls: PerDefTable>, + variances: PerDefTable>, + generics: PerDefTable>, + predicates: PerDefTable>>, + predicates_defined_on: PerDefTable>>, + + mir: PerDefTable>>, + promoted_mir: PerDefTable>>>, } macro_rules! encoder_methods { @@ -482,7 +498,23 @@ impl<'tcx> EncodeContext<'tcx> { i = self.position(); let per_def = LazyPerDefTables { - entry: self.per_def.entry.encode(&mut self.opaque), + kind: self.per_def.kind.encode(&mut self.opaque), + visibility: self.per_def.visibility.encode(&mut self.opaque), + span: self.per_def.span.encode(&mut self.opaque), + attributes: self.per_def.attributes.encode(&mut self.opaque), + children: self.per_def.children.encode(&mut self.opaque), + stability: self.per_def.stability.encode(&mut self.opaque), + deprecation: self.per_def.deprecation.encode(&mut self.opaque), + + ty: self.per_def.ty.encode(&mut self.opaque), + inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque), + variances: self.per_def.variances.encode(&mut self.opaque), + generics: self.per_def.generics.encode(&mut self.opaque), + predicates: self.per_def.predicates.encode(&mut self.opaque), + predicates_defined_on: self.per_def.predicates_defined_on.encode(&mut self.opaque), + + mir: self.per_def.mir.encode(&mut self.opaque), + promoted_mir: self.per_def.promoted_mir.encode(&mut self.opaque), }; let per_def_bytes = self.position() - i; @@ -578,17 +610,14 @@ impl<'tcx> EncodeContext<'tcx> { } impl EncodeContext<'tcx> { - fn encode_variances_of(&mut self, def_id: DefId) -> Lazy<[ty::Variance]> { + fn encode_variances_of(&mut self, def_id: DefId) { debug!("EncodeContext::encode_variances_of({:?})", def_id); - let tcx = self.tcx; - self.lazy(&tcx.variances_of(def_id)[..]) + record!(self.per_def.variances[def_id] <- &self.tcx.variances_of(def_id)[..]); } - fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { - let tcx = self.tcx; - let ty = tcx.type_of(def_id); - debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty); - self.lazy(ty) + fn encode_item_type(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_item_type({:?})", def_id); + record!(self.per_def.ty[def_id] <- self.tcx.type_of(def_id)); } fn encode_enum_variant_info( @@ -617,32 +646,25 @@ impl EncodeContext<'tcx> { let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); let enum_vis = &tcx.hir().expect_item(enum_id).vis; - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Variant(self.lazy(data)), - visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: self.lazy(variant.fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - })), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data))); + record!(self.per_def.visibility[def_id] <- + ty::Visibility::from_hir(enum_vis, enum_id, self.tcx)); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); + record!(self.per_def.children[def_id] <- variant.fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + })); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn encode_enum_variant_ctor( @@ -676,29 +698,19 @@ impl EncodeContext<'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Variant(self.lazy(data)), - visibility: self.lazy(ctor_vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + record!(self.per_def.kind[def_id] <- EntryKind::Variant(self.lazy(data))); + record!(self.per_def.visibility[def_id] <- ctor_vis); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn encode_info_for_mod( @@ -719,27 +731,15 @@ impl EncodeContext<'tcx> { }, }; - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Mod(self.lazy(data)), - visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(attrs), - children: self.lazy(md.item_ids.iter().map(|item_id| { - tcx.hir().local_def_id(item_id.id).index - })), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: None, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None, - promoted_mir: None, - }) + record!(self.per_def.kind[def_id] <- EntryKind::Mod(self.lazy(data))); + record!(self.per_def.visibility[def_id] <- ty::Visibility::from_hir(vis, id, self.tcx)); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.per_def.attributes[def_id] <- attrs); + record!(self.per_def.children[def_id] <- md.item_ids.iter().map(|item_id| { + tcx.hir().local_def_id(item_id.id).index + })); + self.encode_stability(def_id); + self.encode_deprecation(def_id); } fn encode_field( @@ -758,25 +758,15 @@ impl EncodeContext<'tcx> { let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Field, - visibility: self.lazy(field.vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: None, - promoted_mir: None, - }) + record!(self.per_def.kind[def_id] <- EntryKind::Field); + record!(self.per_def.visibility[def_id] <- field.vis); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.per_def.attributes[def_id] <- &variant_data.fields()[field_index].attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + self.encode_generics(def_id); + self.encode_predicates(def_id); } fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) { @@ -813,49 +803,35 @@ impl EncodeContext<'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - let repr_options = get_repr_options(tcx, adt_def_id); - - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Struct(self.lazy(data), repr_options), - visibility: self.lazy(ctor_vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + record!(self.per_def.kind[def_id] <- EntryKind::Struct(self.lazy(data), adt_def.repr)); + record!(self.per_def.visibility[def_id] <- ctor_vis); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } - fn encode_generics(&mut self, def_id: DefId) -> Lazy { + fn encode_generics(&mut self, def_id: DefId) { debug!("EncodeContext::encode_generics({:?})", def_id); - let tcx = self.tcx; - self.lazy(tcx.generics_of(def_id)) + record!(self.per_def.generics[def_id] <- self.tcx.generics_of(def_id)); } - fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { + fn encode_predicates(&mut self, def_id: DefId) { debug!("EncodeContext::encode_predicates({:?})", def_id); - let tcx = self.tcx; - self.lazy(&*tcx.predicates_of(def_id)) + record!(self.per_def.predicates[def_id] <- &*self.tcx.predicates_of(def_id)); } - fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy> { + fn encode_predicates_defined_on(&mut self, def_id: DefId) { debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); - let tcx = self.tcx; - self.lazy(&*tcx.predicates_defined_on(def_id)) + record!(self.per_def.predicates_defined_on[def_id] <- + &*self.tcx.predicates_defined_on(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) { @@ -875,7 +851,7 @@ impl EncodeContext<'tcx> { span_bug!(ast_item.span, "traits cannot have final items"), }; - let kind = match trait_item.kind { + record!(self.per_def.kind[def_id] <- match trait_item.kind { ty::AssocKind::Const => { let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); @@ -884,7 +860,7 @@ impl EncodeContext<'tcx> { EntryKind::AssocConst(container, ConstQualif { mir: 0 }, rendered_const) } ty::AssocKind::Method => { - let fn_data = if let hir::TraitItemKind::Method(method_sig, m) = &ast_item.kind { + let fn_data = if let hir::TraitItemKind::Method(m_sig, m) = &ast_item.kind { let param_names = match *m { hir::TraitMethod::Required(ref names) => { self.encode_fn_param_names(names) @@ -894,10 +870,10 @@ impl EncodeContext<'tcx> { } }; FnData { - asyncness: method_sig.header.asyncness, + asyncness: m_sig.header.asyncness, constness: hir::Constness::NotConst, param_names, - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() @@ -910,44 +886,31 @@ impl EncodeContext<'tcx> { } ty::AssocKind::Type => EntryKind::AssocType(container), ty::AssocKind::OpaqueTy => span_bug!(ast_item.span, "opaque type in trait"), - }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(trait_item.vis), - span: self.lazy(ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: match trait_item.kind { - ty::AssocKind::Const | - ty::AssocKind::Method => { - Some(self.encode_item_type(def_id)) + }); + record!(self.per_def.visibility[def_id] <- trait_item.vis); + record!(self.per_def.span[def_id] <- ast_item.span); + record!(self.per_def.attributes[def_id] <- &ast_item.attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + match trait_item.kind { + ty::AssocKind::Const | + ty::AssocKind::Method => { + self.encode_item_type(def_id); + } + ty::AssocKind::Type => { + if trait_item.defaultness.has_value() { + self.encode_item_type(def_id); } - ty::AssocKind::Type => { - if trait_item.defaultness.has_value() { - Some(self.encode_item_type(def_id)) - } else { - None - } - } - ty::AssocKind::OpaqueTy => unreachable!(), - }, - inherent_impls: Lazy::empty(), - variances: if trait_item.kind == ty::AssocKind::Method { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + } + ty::AssocKind::OpaqueTy => unreachable!(), + } + if trait_item.kind == ty::AssocKind::Method { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn metadata_output_only(&self) -> bool { @@ -970,7 +933,7 @@ impl EncodeContext<'tcx> { span_bug!(ast_item.span, "impl items always have values (currently)"), }; - let kind = match impl_item.kind { + record!(self.per_def.kind[def_id] <- match impl_item.kind { ty::AssocKind::Const => { if let hir::ImplItemKind::Const(_, body_id) = ast_item.kind { let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id).0; @@ -988,7 +951,7 @@ impl EncodeContext<'tcx> { asyncness: sig.header.asyncness, constness: sig.header.constness, param_names: self.encode_fn_param_names_for_body(body), - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() @@ -1001,8 +964,18 @@ impl EncodeContext<'tcx> { } ty::AssocKind::OpaqueTy => EntryKind::AssocOpaqueTy(container), ty::AssocKind::Type => EntryKind::AssocType(container) - }; - + }); + record!(self.per_def.visibility[def_id] <- impl_item.vis); + record!(self.per_def.span[def_id] <- ast_item.span); + record!(self.per_def.attributes[def_id] <- &ast_item.attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if impl_item.kind == ty::AssocKind::Method { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); let mir = match ast_item.kind { hir::ImplItemKind::Const(..) => true, hir::ImplItemKind::Method(ref sig, _) => { @@ -1017,30 +990,10 @@ impl EncodeContext<'tcx> { hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => false, }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(impl_item.vis), - span: self.lazy(ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if impl_item.kind == ty::AssocKind::Method { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: if mir { self.encode_optimized_mir(def_id) } else { None }, - promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, - }) + if mir { + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); + } } fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) @@ -1060,51 +1013,44 @@ impl EncodeContext<'tcx> { self.lazy(param_names.iter().map(|ident| ident.name)) } - fn encode_optimized_mir(&mut self, def_id: DefId) -> Option>> { + fn encode_optimized_mir(&mut self, def_id: DefId) { debug!("EntryBuilder::encode_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { - let mir = self.tcx.optimized_mir(def_id); - Some(self.lazy(mir)) - } else { - None + record!(self.per_def.mir[def_id] <- self.tcx.optimized_mir(def_id)); } } - fn encode_promoted_mir( - &mut self, - def_id: DefId, - ) -> Option>>> { + fn encode_promoted_mir(&mut self, def_id: DefId) { debug!("EncodeContext::encode_promoted_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { - let promoted = self.tcx.promoted_mir(def_id); - Some(self.lazy(promoted)) - } else { - None + record!(self.per_def.promoted_mir[def_id] <- self.tcx.promoted_mir(def_id)); } } // Encodes the inherent implementations of a structure, enumeration, or trait. - fn encode_inherent_implementations(&mut self, def_id: DefId) -> Lazy<[DefIndex]> { + fn encode_inherent_implementations(&mut self, def_id: DefId) { debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); let implementations = self.tcx.inherent_impls(def_id); - if implementations.is_empty() { - Lazy::empty() - } else { - self.lazy(implementations.iter().map(|&def_id| { + if !implementations.is_empty() { + record!(self.per_def.inherent_impls[def_id] <- implementations.iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index - })) + })); } } - fn encode_stability(&mut self, def_id: DefId) -> Option> { + fn encode_stability(&mut self, def_id: DefId) { debug!("EncodeContext::encode_stability({:?})", def_id); - self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) + if let Some(stab) = self.tcx.lookup_stability(def_id) { + record!(self.per_def.stability[def_id] <- stab) + } } - fn encode_deprecation(&mut self, def_id: DefId) -> Option> { + fn encode_deprecation(&mut self, def_id: DefId) { debug!("EncodeContext::encode_deprecation({:?})", def_id); - self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(depr)) + if let Some(depr) = self.tcx.lookup_deprecation(def_id) { + record!(self.per_def.deprecation[def_id] <- depr); + } } fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy { @@ -1119,11 +1065,11 @@ impl EncodeContext<'tcx> { debug!("EncodeContext::encode_info_for_item({:?})", def_id); - let kind = match item.kind { + record!(self.per_def.kind[def_id] <- match item.kind { hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic, hir::ItemKind::Static(_, hir::MutImmutable, _) => EntryKind::ImmStatic, hir::ItemKind::Const(_, body_id) => { - let mir = tcx.at(item.span).mir_const_qualif(def_id).0; + let mir = self.tcx.at(item.span).mir_const_qualif(def_id).0; EntryKind::Const( ConstQualif { mir }, self.encode_rendered_const_for_body(body_id) @@ -1146,42 +1092,42 @@ impl EncodeContext<'tcx> { hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, hir::ItemKind::TyAlias(..) => EntryKind::Type, hir::ItemKind::OpaqueTy(..) => EntryKind::OpaqueTy, - hir::ItemKind::Enum(..) => EntryKind::Enum(get_repr_options(tcx, def_id)), + hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr), hir::ItemKind::Struct(ref struct_def, _) => { - let variant = tcx.adt_def(def_id).non_enum_variant(); + let adt_def = self.tcx.adt_def(def_id); + let variant = adt_def.non_enum_variant(); // Encode def_ids for each field and method // for methods, write all the stuff get_trait_method // needs to know - let ctor = struct_def.ctor_hir_id() - .map(|ctor_hir_id| tcx.hir().local_def_id(ctor_hir_id).index); - - let repr_options = get_repr_options(tcx, def_id); + let ctor = struct_def.ctor_hir_id().map(|ctor_hir_id| { + self.tcx.hir().local_def_id(ctor_hir_id).index + }); EntryKind::Struct(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor, ctor_sig: None, - }), repr_options) + }), adt_def.repr) } hir::ItemKind::Union(..) => { - let variant = tcx.adt_def(def_id).non_enum_variant(); - let repr_options = get_repr_options(tcx, def_id); + let adt_def = self.tcx.adt_def(def_id); + let variant = adt_def.non_enum_variant(); EntryKind::Union(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: None, ctor_sig: None, - }), repr_options) + }), adt_def.repr) } hir::ItemKind::Impl(_, _, defaultness, ..) => { - let trait_ref = tcx.impl_trait_ref(def_id); - let polarity = tcx.impl_polarity(def_id); + let trait_ref = self.tcx.impl_trait_ref(def_id); + let polarity = self.tcx.impl_polarity(def_id); let parent = if let Some(trait_ref) = trait_ref { - let trait_def = tcx.trait_def(trait_ref.def_id); - trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| { + 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, @@ -1195,8 +1141,8 @@ impl EncodeContext<'tcx> { // "unsized info", else just store None let coerce_unsized_info = trait_ref.and_then(|t| { - if Some(t.def_id) == tcx.lang_items().coerce_unsized_trait() { - Some(tcx.at(item.span).coerce_unsized_info(def_id)) + if Some(t.def_id) == self.tcx.lang_items().coerce_unsized_trait() { + Some(self.tcx.at(item.span).coerce_unsized_info(def_id)) } else { None } @@ -1213,11 +1159,11 @@ impl EncodeContext<'tcx> { EntryKind::Impl(self.lazy(data)) } hir::ItemKind::Trait(..) => { - let trait_def = tcx.trait_def(def_id); + let trait_def = self.tcx.trait_def(def_id); let data = TraitData { unsafety: trait_def.unsafety, paren_sugar: trait_def.paren_sugar, - has_auto_impl: tcx.trait_is_auto(def_id), + has_auto_impl: self.tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), }; @@ -1233,7 +1179,95 @@ impl EncodeContext<'tcx> { } hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), - }; + }); + record!(self.per_def.visibility[def_id] <- + ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)); + record!(self.per_def.span[def_id] <- item.span); + record!(self.per_def.attributes[def_id] <- &item.attrs); + // FIXME(eddyb) there should be a nicer way to do this. + match item.kind { + hir::ItemKind::ForeignMod(ref fm) => record!(self.per_def.children[def_id] <- + fm.items + .iter() + .map(|foreign_item| tcx.hir().local_def_id( + foreign_item.hir_id).index) + ), + hir::ItemKind::Enum(..) => record!(self.per_def.children[def_id] <- + self.tcx.adt_def(def_id).variants.iter().map(|v| { + assert!(v.def_id.is_local()); + v.def_id.index + }) + ), + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) => record!(self.per_def.children[def_id] <- + self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + }) + ), + hir::ItemKind::Impl(..) | + hir::ItemKind::Trait(..) => { + let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id); + record!(self.per_def.children[def_id] <- + associated_item_def_ids.iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + }) + ); + } + _ => {} + } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + match item.kind { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::TyAlias(..) | + hir::ItemKind::OpaqueTy(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) => self.encode_item_type(def_id), + _ => {} + } + self.encode_inherent_implementations(def_id); + match item.kind { + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), + _ => {} + } + match item.kind { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::TyAlias(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) | + hir::ItemKind::OpaqueTy(..) | + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + self.encode_generics(def_id); + self.encode_predicates(def_id); + } + _ => {} + } + // The only time that `predicates_defined_on` is used (on + // an external item) is for traits, during chalk lowering, + // so only encode it in that case as an efficiency + // hack. (No reason not to expand it in the future if + // necessary.) + match item.kind { + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + self.encode_predicates_defined_on(def_id); + } + _ => {} // not *wrong* for other kinds of items, but not needed + } let mir = match item.kind { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, @@ -1248,174 +1282,48 @@ impl EncodeContext<'tcx> { } _ => false, }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), - span: self.lazy(item.span), - attributes: self.encode_attributes(&item.attrs), - children: match item.kind { - hir::ItemKind::ForeignMod(ref fm) => { - self.lazy(fm.items - .iter() - .map(|foreign_item| tcx.hir().local_def_id( - foreign_item.hir_id).index)) - } - hir::ItemKind::Enum(..) => { - let def = self.tcx.adt_def(def_id); - self.lazy(def.variants.iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - })) - } - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(def_id); - self.lazy(def.non_enum_variant().fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - })) - } - hir::ItemKind::Impl(..) | - hir::ItemKind::Trait(..) => { - self.lazy(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { - assert!(def_id.is_local()); - def_id.index - })) - } - _ => Lazy::empty(), - }, - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: match item.kind { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::TyAlias(..) | - hir::ItemKind::OpaqueTy(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) => Some(self.encode_item_type(def_id)), - _ => None, - }, - inherent_impls: self.encode_inherent_implementations(def_id), - variances: match item.kind { - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => Lazy::empty(), - }, - generics: match item.kind { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::TyAlias(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::OpaqueTy(..) | - hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)), - hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)), - _ => None, - }, - predicates: match item.kind { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::TyAlias(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::OpaqueTy(..) | - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)), - _ => None, - }, - - // The only time that `predicates_defined_on` is used (on - // an external item) is for traits, during chalk lowering, - // so only encode it in that case as an efficiency - // hack. (No reason not to expand it in the future if - // necessary.) - predicates_defined_on: match item.kind { - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => { - Some(self.encode_predicates_defined_on(def_id)) - } - _ => None, // not *wrong* for other kinds of items, but not needed - }, - - mir: if mir { self.encode_optimized_mir(def_id) } else { None }, - promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, - }) + if mir { + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); + } } /// Serialize the text of exported macros fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) { use syntax::print::pprust; let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::MacroDef(self.lazy(MacroDef { - body: pprust::tts_to_string(macro_def.body.clone()), - legacy: macro_def.legacy, - })), - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(macro_def.span), - attributes: self.encode_attributes(¯o_def.attrs), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - children: Lazy::empty(), - ty: None, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - mir: None, - promoted_mir: None, - }) + record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(MacroDef { + body: pprust::tts_to_string(macro_def.body.clone()), + legacy: macro_def.legacy, + }))); + record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); + record!(self.per_def.span[def_id] <- macro_def.span); + record!(self.per_def.attributes[def_id] <- ¯o_def.attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); } fn encode_info_for_generic_param( &mut self, def_id: DefId, - entry_kind: EntryKind<'tcx>, + kind: EntryKind<'tcx>, encode_type: bool, ) { - let tcx = self.tcx; - record!(self.per_def.entry[def_id] <- Entry { - kind: entry_kind, - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: None, - deprecation: None, - ty: if encode_type { Some(self.encode_item_type(def_id)) } else { None }, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None, - promoted_mir: None, - }) + 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)); + if encode_type { + self.encode_item_type(def_id); + } } fn encode_info_for_closure(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_closure({:?})", def_id); - let tcx = self.tcx; let tables = self.tcx.typeck_tables_of(def_id); let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); - let kind = match tables.node_type(hir_id).kind { + + record!(self.per_def.kind[def_id] <- match tables.node_type(hir_id).kind { ty::Generator(def_id, ..) => { let layout = self.tcx.generator_layout(def_id); let data = GeneratorData { @@ -1430,61 +1338,32 @@ impl EncodeContext<'tcx> { EntryKind::Closure(self.lazy(data)) } - _ => bug!("closure that is neither generator nor closure") - }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: Lazy::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: None, - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) + _ => bug!("closure that is neither generator nor closure"), + }); + record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + record!(self.per_def.attributes[def_id] <- &self.tcx.get_attrs(def_id)[..]); + self.encode_item_type(def_id); + self.encode_generics(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn encode_info_for_anon_const(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); - let tcx = self.tcx; - let id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let body_id = tcx.hir().body_owned_by(id); + let id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); + let body_id = self.tcx.hir().body_owned_by(id); let const_data = self.encode_rendered_const_for_body(body_id); - let mir = tcx.mir_const_qualif(def_id).0; + let mir = self.tcx.mir_const_qualif(def_id).0; - record!(self.per_def.entry[def_id] <- Entry { - kind: EntryKind::Const(ConstQualif { mir }, const_data), - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - promoted_mir: self.encode_promoted_mir(def_id), - }) - } - - fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> Lazy<[ast::Attribute]> { - self.lazy(attrs) + record!(self.per_def.kind[def_id] <- EntryKind::Const(ConstQualif { mir }, const_data)); + record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); + record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); + self.encode_item_type(def_id); + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); + self.encode_promoted_mir(def_id); } fn encode_native_libraries(&mut self) -> Lazy<[NativeLibrary]> { @@ -1667,7 +1546,7 @@ impl EncodeContext<'tcx> { debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id); - let kind = match nitem.kind { + record!(self.per_def.kind[def_id] <- match nitem.kind { hir::ForeignItemKind::Fn(_, ref names, _) => { let data = FnData { asyncness: hir::IsAsync::NotAsync, @@ -1680,30 +1559,19 @@ impl EncodeContext<'tcx> { hir::ForeignItemKind::Static(_, hir::MutMutable) => EntryKind::ForeignMutStatic, hir::ForeignItemKind::Static(_, hir::MutImmutable) => EntryKind::ForeignImmStatic, hir::ForeignItemKind::Type => EntryKind::ForeignType, - }; - - record!(self.per_def.entry[def_id] <- Entry { - kind, - visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), - span: self.lazy(nitem.span), - attributes: self.encode_attributes(&nitem.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: match nitem.kind { - hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => Lazy::empty(), - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: None, - promoted_mir: None, - }) + }); + record!(self.per_def.visibility[def_id] <- + ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx)); + record!(self.per_def.span[def_id] <- nitem.span); + record!(self.per_def.attributes[def_id] <- &nitem.attrs); + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if let hir::ForeignItemKind::Fn(..) = nitem.kind { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); } } @@ -1906,11 +1774,28 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { // Since encoding metadata is not in a query, and nothing is cached, // there's no need to do dep-graph tracking for any of it. let (root, mut result) = tcx.dep_graph.with_ignore(move || { + let def_count = tcx.hir().definitions().def_index_count(); let mut ecx = EncodeContext { opaque: encoder, tcx, per_def: PerDefTables { - entry: PerDefTable::new(tcx.hir().definitions().def_index_count()), + kind: PerDefTable::new(def_count), + visibility: PerDefTable::new(def_count), + span: PerDefTable::new(def_count), + attributes: PerDefTable::new(def_count), + children: PerDefTable::new(def_count), + stability: PerDefTable::new(def_count), + deprecation: PerDefTable::new(def_count), + + ty: PerDefTable::new(def_count), + inherent_impls: PerDefTable::new(def_count), + variances: PerDefTable::new(def_count), + generics: PerDefTable::new(def_count), + predicates: PerDefTable::new(def_count), + predicates_defined_on: PerDefTable::new(def_count), + + mir: PerDefTable::new(def_count), + promoted_mir: PerDefTable::new(def_count), }, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), @@ -1939,11 +1824,3 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { EncodedMetadata { raw_data: result } } - -fn get_repr_options(tcx: TyCtxt<'_>, did: DefId) -> ReprOptions { - let ty = tcx.type_of(did); - match ty.kind { - ty::Adt(ref def, _) => return def.repr, - _ => bug!("{} is not an ADT", ty), - } -} diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index e70ba2532caa..96f35783278f 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -229,28 +229,23 @@ crate struct TraitImpls { #[derive(RustcEncodable, RustcDecodable)] crate struct LazyPerDefTables<'tcx> { - pub entry: Lazy!(PerDefTable>>), -} + pub kind: Lazy!(PerDefTable)>), + pub visibility: Lazy!(PerDefTable>), + pub span: Lazy!(PerDefTable>), + pub attributes: Lazy!(PerDefTable>), + pub children: Lazy!(PerDefTable>), + pub stability: Lazy!(PerDefTable>), + pub deprecation: Lazy!(PerDefTable>), -#[derive(RustcEncodable, RustcDecodable)] -crate struct Entry<'tcx> { - pub kind: EntryKind<'tcx>, - pub visibility: Lazy, - pub span: Lazy, - pub attributes: Lazy<[ast::Attribute]>, - pub children: Lazy<[DefIndex]>, - pub stability: Option>, - pub deprecation: Option>, + pub ty: Lazy!(PerDefTable)>), + pub inherent_impls: Lazy!(PerDefTable>), + pub variances: Lazy!(PerDefTable>), + pub generics: Lazy!(PerDefTable>), + pub predicates: Lazy!(PerDefTable)>), + pub predicates_defined_on: Lazy!(PerDefTable)>), - pub ty: Option)>, - pub inherent_impls: Lazy<[DefIndex]>, - pub variances: Lazy<[ty::Variance]>, - pub generics: Option>, - pub predicates: Option)>, - pub predicates_defined_on: Option)>, - - pub mir: Option)>, - pub promoted_mir: Option>)>, + pub mir: Lazy!(PerDefTable)>), + pub promoted_mir: Lazy!(PerDefTable>)>), } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] From 34066d60c38b8e1049a60e1eaf26cd84a67e7655 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 14 Apr 2019 05:21:39 +0300 Subject: [PATCH 406/545] rustc_metadata: don't use more space than needed, for each Table. --- src/librustc_metadata/encoder.rs | 22 ++-------------------- src/librustc_metadata/table.rs | 32 +++++++++++++++++++------------- 2 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 3bc3fee4164f..f1436e4c09df 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -60,6 +60,7 @@ struct EncodeContext<'tcx> { source_file_cache: Lrc, } +#[derive(Default)] struct PerDefTables<'tcx> { kind: PerDefTable>>, visibility: PerDefTable>, @@ -1774,29 +1775,10 @@ crate fn encode_metadata(tcx: TyCtxt<'_>) -> EncodedMetadata { // Since encoding metadata is not in a query, and nothing is cached, // there's no need to do dep-graph tracking for any of it. let (root, mut result) = tcx.dep_graph.with_ignore(move || { - let def_count = tcx.hir().definitions().def_index_count(); let mut ecx = EncodeContext { opaque: encoder, tcx, - per_def: PerDefTables { - kind: PerDefTable::new(def_count), - visibility: PerDefTable::new(def_count), - span: PerDefTable::new(def_count), - attributes: PerDefTable::new(def_count), - children: PerDefTable::new(def_count), - stability: PerDefTable::new(def_count), - deprecation: PerDefTable::new(def_count), - - ty: PerDefTable::new(def_count), - inherent_impls: PerDefTable::new(def_count), - variances: PerDefTable::new(def_count), - generics: PerDefTable::new(def_count), - predicates: PerDefTable::new(def_count), - predicates_defined_on: PerDefTable::new(def_count), - - mir: PerDefTable::new(def_count), - promoted_mir: PerDefTable::new(def_count), - }, + per_def: Default::default(), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index 0585aa1d3884..5cfa137d04f7 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -23,7 +23,7 @@ crate trait FixedSizeEncoding: Default { // FIXME(eddyb) make these generic functions, or at least defaults here. // (same problem as above, needs `[u8; Self::BYTE_LEN]`) // For now, a macro (`fixed_size_encoding_byte_len_and_defaults`) is used. - fn read_from_bytes_at(b: &[u8], i: usize) -> Self; + fn maybe_read_from_bytes_at(b: &[u8], i: usize) -> Option; fn write_to_bytes_at(self, b: &mut [u8], i: usize); } @@ -31,7 +31,7 @@ crate trait FixedSizeEncoding: Default { macro_rules! fixed_size_encoding_byte_len_and_defaults { ($byte_len:expr) => { const BYTE_LEN: usize = $byte_len; - fn read_from_bytes_at(b: &[u8], i: usize) -> Self { + fn maybe_read_from_bytes_at(b: &[u8], i: usize) -> Option { const BYTE_LEN: usize = $byte_len; // HACK(eddyb) ideally this would be done with fully safe code, // but slicing `[u8]` with `i * N..` is optimized worse, due to the @@ -42,7 +42,7 @@ macro_rules! fixed_size_encoding_byte_len_and_defaults { b.len() / BYTE_LEN, ) }; - FixedSizeEncoding::from_bytes(&b[i]) + b.get(i).map(|b| FixedSizeEncoding::from_bytes(b)) } fn write_to_bytes_at(self, b: &mut [u8], i: usize) { const BYTE_LEN: usize = $byte_len; @@ -116,8 +116,7 @@ impl FixedSizeEncoding for Option> { /// encoding or decoding all the values eagerly and in-order. // FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box>` would be used // when building it, and `Lazy>` or `&Table` when reading it. -// Sadly, that doesn't work for `DefPerTable`, which is `(Table, Table)`, -// and so would need two lengths in its metadata, which is not supported yet. +// (not sure if that is possible given that the `Vec` is being resized now) crate struct Table where Option: FixedSizeEncoding { // FIXME(eddyb) store `[u8; >::BYTE_LEN]` instead of `u8` in `Vec`, // once that starts being allowed by the compiler (i.e. lazy normalization). @@ -125,16 +124,21 @@ crate struct Table where Option: FixedSizeEncoding { _marker: PhantomData, } -impl Table where Option: FixedSizeEncoding { - crate fn new(len: usize) -> Self { +impl Default for Table where Option: FixedSizeEncoding { + fn default() -> Self { Table { - // FIXME(eddyb) only allocate and encode as many entries as needed. - bytes: vec![0; len * >::BYTE_LEN], + bytes: vec![], _marker: PhantomData, } } +} +impl Table where Option: FixedSizeEncoding { crate fn set(&mut self, i: usize, value: T) { + let needed = (i + 1) * >::BYTE_LEN; + if self.bytes.len() < needed { + self.bytes.resize(needed, 0); + } Some(value).write_to_bytes_at(&mut self.bytes, i); } @@ -167,7 +171,7 @@ impl Lazy> where Option: FixedSizeEncoding { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); let bytes = &metadata.raw_bytes()[self.position.get()..][..self.meta]; - >::read_from_bytes_at(bytes, i) + >::maybe_read_from_bytes_at(bytes, i)? } } @@ -176,11 +180,13 @@ impl Lazy> where Option: FixedSizeEncoding { // and by using `newtype_index!` to define `DefIndex`. crate struct PerDefTable(Table) where Option: FixedSizeEncoding; -impl PerDefTable where Option: FixedSizeEncoding { - crate fn new(def_index_count: usize) -> Self { - PerDefTable(Table::new(def_index_count)) +impl Default for PerDefTable where Option: FixedSizeEncoding { + fn default() -> Self { + PerDefTable(Table::default()) } +} +impl PerDefTable where Option: FixedSizeEncoding { crate fn set(&mut self, def_id: DefId, value: T) { assert!(def_id.is_local()); self.0.set(def_id.index.index(), value); From d89dddc9204a540efcd7f86c36d60381020b2422 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Oct 2019 18:42:08 +0300 Subject: [PATCH 407/545] rustc_metadata: address some review comments. --- src/librustc_metadata/table.rs | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index 5cfa137d04f7..e164c28c953b 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -23,7 +23,13 @@ crate trait FixedSizeEncoding: Default { // FIXME(eddyb) make these generic functions, or at least defaults here. // (same problem as above, needs `[u8; Self::BYTE_LEN]`) // For now, a macro (`fixed_size_encoding_byte_len_and_defaults`) is used. + + /// Read a `Self` value (encoded as `Self::BYTE_LEN` bytes), + /// from `&b[i * Self::BYTE_LEN..]`, returning `None` if `i` + /// is not in bounds, or `Some(Self::from_bytes(...))` otherwise. fn maybe_read_from_bytes_at(b: &[u8], i: usize) -> Option; + /// Write a `Self` value (encoded as `Self::BYTE_LEN` bytes), + /// at `&mut b[i * Self::BYTE_LEN..]`, using `Self::write_to_bytes`. fn write_to_bytes_at(self, b: &mut [u8], i: usize); } @@ -112,8 +118,11 @@ impl FixedSizeEncoding for Option> { } } -/// Random-access table, similar to `Vec>`, but without requiring -/// encoding or decoding all the values eagerly and in-order. +/// Random-access table (i.e. offeringconstant-time `get`/`set`), similar to +/// `Vec>`, but without requiring encoding or decoding all the values +/// eagerly and in-order. +/// A total of `(max_idx + 1) * as FixedSizeEncoding>::BYTE_LEN` bytes +/// are used for a table, where `max_idx` is the largest index passed to `set`. // FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box>` would be used // when building it, and `Lazy>` or `&Table` when reading it. // (not sure if that is possible given that the `Vec` is being resized now) @@ -135,10 +144,16 @@ impl Default for Table where Option: FixedSizeEncoding { impl Table where Option: FixedSizeEncoding { crate fn set(&mut self, i: usize, value: T) { + // FIXME(eddyb) investigate more compact encodings for sparse tables. + // On the PR @michaelwoerister mentioned: + // > Space requirements could perhaps be optimized by using the HAMT `popcnt` + // > trick (i.e. divide things into buckets of 32 or 64 items and then + // > store bit-masks of which item in each bucket is actually serialized). let needed = (i + 1) * >::BYTE_LEN; if self.bytes.len() < needed { self.bytes.resize(needed, 0); } + Some(value).write_to_bytes_at(&mut self.bytes, i); } @@ -170,12 +185,13 @@ impl Lazy> where Option: FixedSizeEncoding { ) -> Option { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - let bytes = &metadata.raw_bytes()[self.position.get()..][..self.meta]; + let start = self.position.get(); + let bytes = &metadata.raw_bytes()[start..start + self.meta]; >::maybe_read_from_bytes_at(bytes, i)? } } -/// Per-definition table, similar to `Table` but keyed on `DefIndex`. +/// Like a `Table` but using `DefIndex` instead of `usize` as keys. // FIXME(eddyb) replace by making `Table` behave like `IndexVec`, // and by using `newtype_index!` to define `DefIndex`. crate struct PerDefTable(Table) where Option: FixedSizeEncoding; From fe819a074c748fd3d11fcc0be8164645a7cd58db Mon Sep 17 00:00:00 2001 From: wangxiangqing Date: Sun, 13 Oct 2019 12:59:23 +0800 Subject: [PATCH 408/545] Collect occurrences of for mismatched braces diagnostic Change-Id: I20ba0b62308370ee961141fa1aefc4b9c9f0cb3a --- src/libsyntax/parse/lexer/tokentrees.rs | 2 +- .../parser/mismatched-delim-brace-empty-block.rs | 4 +++- .../mismatched-delim-brace-empty-block.stderr | 15 +++++++++------ 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/libsyntax/parse/lexer/tokentrees.rs b/src/libsyntax/parse/lexer/tokentrees.rs index b088d160b923..b4dd23c9f9b0 100644 --- a/src/libsyntax/parse/lexer/tokentrees.rs +++ b/src/libsyntax/parse/lexer/tokentrees.rs @@ -126,7 +126,7 @@ impl<'a> TokenTreesReader<'a> { let (open_brace, open_brace_span) = self.open_braces.pop().unwrap(); let close_brace_span = self.token.span; - if close_brace_span.lo() == open_brace_span.hi() { + 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); } diff --git a/src/test/ui/parser/mismatched-delim-brace-empty-block.rs b/src/test/ui/parser/mismatched-delim-brace-empty-block.rs index bcc95c09e1e9..0f5a2cb09ecc 100644 --- a/src/test/ui/parser/mismatched-delim-brace-empty-block.rs +++ b/src/test/ui/parser/mismatched-delim-brace-empty-block.rs @@ -1,3 +1,5 @@ -fn main() {} +fn main() { + +} let _ = (); } //~ ERROR unexpected close delimiter 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 82fe8930c325..5ae5fc91a4e8 100644 --- a/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr +++ b/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr @@ -1,11 +1,14 @@ error: unexpected close delimiter: `}` - --> $DIR/mismatched-delim-brace-empty-block.rs:3:1 + --> $DIR/mismatched-delim-brace-empty-block.rs:5:1 | -LL | fn main() {} - | -- this block is empty, you might have not meant to close it -LL | let _ = (); -LL | } - | ^ unexpected close delimiter +LL | fn main() { + | ___________- +LL | | +LL | | } + | |_- this block is empty, you might have not meant to close it +LL | let _ = (); +LL | } + | ^ unexpected close delimiter error: aborting due to previous error From d82c1c546df10f07b854a2e5b088404d80ec22c9 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Tue, 15 Oct 2019 18:05:13 +0100 Subject: [PATCH 409/545] Avoid unused lifetime warning for lifetimes introduced when desugering async. --- src/librustc/middle/resolve_lifetime.rs | 8 +++- src/test/ui/async-await/unused-lifetime.rs | 42 +++++++++++++++++++ .../ui/async-await/unused-lifetime.stderr | 32 ++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/async-await/unused-lifetime.rs create mode 100644 src/test/ui/async-await/unused-lifetime.stderr diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index 8836a632a7ca..86afde16dc80 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -709,15 +709,22 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { match param.kind { GenericParamKind::Lifetime { .. } => { let (name, reg) = Region::early(&self.tcx.hir(), &mut index, ¶m); + let def_id = if let Region::EarlyBound(_ ,def_id , _) = reg { + def_id + } else { + bug!(); + }; if let hir::ParamName::Plain(param_name) = name { if param_name.name == kw::UnderscoreLifetime { // Pick the elided lifetime "definition" if one exists // and use it to make an elision scope. + self.lifetime_uses.insert(def_id.clone(), LifetimeUseSet::Many); elision = Some(reg); } else { lifetimes.insert(name, reg); } } else { + self.lifetime_uses.insert(def_id.clone(), LifetimeUseSet::Many); lifetimes.insert(name, reg); } } @@ -1623,7 +1630,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { _ => None, } { debug!("id = {:?} span = {:?} name = {:?}", id, span, name); - if name.name == kw::UnderscoreLifetime { continue; } diff --git a/src/test/ui/async-await/unused-lifetime.rs b/src/test/ui/async-await/unused-lifetime.rs new file mode 100644 index 000000000000..1cf546bcb426 --- /dev/null +++ b/src/test/ui/async-await/unused-lifetime.rs @@ -0,0 +1,42 @@ +// edition:2018 + +// Avoid spurious warnings of unused lifetime. The below async functions +// are desugered to have an unused lifetime +// but we don't want to warn about that as there's nothing they can do about it. + +#![deny(unused_lifetimes)] +#![allow(dead_code)] + +pub async fn october(s: &str) { + println!("{}", s); +} + +pub async fn async_fn(&mut ref s: &mut[i32]) { + println!("{:?}", s); +} + +macro_rules! foo_macro { + () => { + pub async fn async_fn_in_macro(&mut ref _s: &mut[i32]) {} + }; +} + +foo_macro!(); + +pub async fn func_with_unused_lifetime<'a>(s: &'a str) { + //~^ ERROR lifetime parameter `'a` never used + println!("{}", s); +} + +pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) { + //~^ ERROR lifetime parameter `'a` never used + //~^^ ERROR lifetime parameter `'b` never used + println!("{}", s); +} + +pub async fn func_with_unused_lifetime_in_two_params<'c>(s: &'c str, t: &'c str) { + //~^ ERROR lifetime parameter `'c` never used + println!("{}", s); +} + +fn main() {} diff --git a/src/test/ui/async-await/unused-lifetime.stderr b/src/test/ui/async-await/unused-lifetime.stderr new file mode 100644 index 000000000000..885cdc04cfa4 --- /dev/null +++ b/src/test/ui/async-await/unused-lifetime.stderr @@ -0,0 +1,32 @@ +error: lifetime parameter `'a` never used + --> $DIR/unused-lifetime.rs:26:40 + | +LL | pub async fn func_with_unused_lifetime<'a>(s: &'a str) { + | ^^ + | +note: lint level defined here + --> $DIR/unused-lifetime.rs:7:9 + | +LL | #![deny(unused_lifetimes)] + | ^^^^^^^^^^^^^^^^ + +error: lifetime parameter `'a` never used + --> $DIR/unused-lifetime.rs:31:44 + | +LL | pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) { + | ^^ + +error: lifetime parameter `'b` never used + --> $DIR/unused-lifetime.rs:31:48 + | +LL | pub async fn func_with_two_unused_lifetime<'a, 'b>(s: &'a str, t: &'b str) { + | ^^ + +error: lifetime parameter `'c` never used + --> $DIR/unused-lifetime.rs:37:54 + | +LL | pub async fn func_with_unused_lifetime_in_two_params<'c>(s: &'c str, t: &'c str) { + | ^^ + +error: aborting due to 4 previous errors + From fa3a4aeae5f3a4c403bf07038c56e74df3d9df70 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 15 Oct 2019 12:55:39 -0300 Subject: [PATCH 410/545] Implement AsRef<[T]> for List --- src/librustc/ty/mod.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 3692caada577..e74f8fb074f7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -700,6 +700,13 @@ impl Deref for List { type Target = [T]; #[inline(always)] fn deref(&self) -> &[T] { + self.as_ref() + } +} + +impl AsRef<[T]> for List { + #[inline(always)] + fn as_ref(&self) -> &[T] { unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) } From c39af6e79b135ed0462b5cb11eb530cbd07facad Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 15 Oct 2019 22:11:39 +0300 Subject: [PATCH 411/545] rustc_codegen_ssa: remove some unnecessary Box special-casing. --- src/librustc_codegen_ssa/base.rs | 46 +++++++++++++------------------- 1 file changed, 19 insertions(+), 27 deletions(-) diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 1c441ca7cbf2..5f2d17f28c25 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -168,12 +168,6 @@ pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b))); (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None)) } - (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { - let (a, b) = (src_ty.boxed_ty(), dst_ty.boxed_ty()); - assert!(bx.cx().type_is_sized(a)); - let ptr_ty = bx.cx().type_ptr_to(bx.cx().backend_type(bx.cx().layout_of(b))); - (bx.pointercast(src, ptr_ty), unsized_info(bx.cx(), a, b, None)) - } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); @@ -196,6 +190,8 @@ pub fn unsize_thin_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } let (lldata, llextra) = result.unwrap(); // HACK(eddyb) have to bitcast pointers until LLVM removes pointee types. + // FIXME(eddyb) move these out of this `match` arm, so they're always + // applied, uniformly, no matter the source/destination types. (bx.bitcast(lldata, bx.cx().scalar_pair_element_backend_type(dst_layout, 0, true)), bx.bitcast(llextra, bx.cx().scalar_pair_element_backend_type(dst_layout, 1, true))) } @@ -212,31 +208,27 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) { let src_ty = src.layout.ty; let dst_ty = dst.layout.ty; - let mut coerce_ptr = || { - let (base, info) = match bx.load_operand(src).val { - OperandValue::Pair(base, info) => { - // fat-ptr to fat-ptr unsize preserves the vtable - // i.e., &'a fmt::Debug+Send => &'a fmt::Debug - // So we need to pointercast the base to ensure - // the types match up. - let thin_ptr = dst.layout.field(bx.cx(), FAT_PTR_ADDR); - (bx.pointercast(base, bx.cx().backend_type(thin_ptr)), info) - } - OperandValue::Immediate(base) => { - unsize_thin_ptr(bx, base, src_ty, dst_ty) - } - OperandValue::Ref(..) => bug!() - }; - OperandValue::Pair(base, info).store(bx, dst); - }; match (&src_ty.kind, &dst_ty.kind) { (&ty::Ref(..), &ty::Ref(..)) | (&ty::Ref(..), &ty::RawPtr(..)) | (&ty::RawPtr(..), &ty::RawPtr(..)) => { - coerce_ptr() - } - (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => { - coerce_ptr() + let (base, info) = match bx.load_operand(src).val { + OperandValue::Pair(base, info) => { + // fat-ptr to fat-ptr unsize preserves the vtable + // i.e., &'a fmt::Debug+Send => &'a fmt::Debug + // So we need to pointercast the base to ensure + // the types match up. + // FIXME(eddyb) use `scalar_pair_element_backend_type` here, + // like `unsize_thin_ptr` does. + let thin_ptr = dst.layout.field(bx.cx(), FAT_PTR_ADDR); + (bx.pointercast(base, bx.cx().backend_type(thin_ptr)), info) + } + OperandValue::Immediate(base) => { + unsize_thin_ptr(bx, base, src_ty, dst_ty) + } + OperandValue::Ref(..) => bug!() + }; + OperandValue::Pair(base, info).store(bx, dst); } (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { From 2918a7d5a9e65721a31598b50e975ae0882feac3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Oct 2019 10:02:55 +1100 Subject: [PATCH 412/545] Add `BitIter::new()`. This factors out some duplicated code. --- src/librustc_index/bit_set.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs index 8c49e0dde0dc..bfaeb847d80b 100644 --- a/src/librustc_index/bit_set.rs +++ b/src/librustc_index/bit_set.rs @@ -168,11 +168,7 @@ impl BitSet { /// Iterates over the indices of set bits in a sorted order. #[inline] pub fn iter(&self) -> BitIter<'_, T> { - BitIter { - cur: None, - iter: self.words.iter().enumerate(), - marker: PhantomData, - } + BitIter::new(&self.words) } /// Duplicates the set as a hybrid set. @@ -296,6 +292,17 @@ pub struct BitIter<'a, T: Idx> { marker: PhantomData } +impl<'a, T: Idx> BitIter<'a, T> { + #[inline] + fn new(words: &'a [Word]) -> BitIter<'a, T> { + BitIter { + cur: None, + iter: words.iter().enumerate(), + marker: PhantomData, + } + } +} + impl<'a, T: Idx> Iterator for BitIter<'a, T> { type Item = T; fn next(&mut self) -> Option { @@ -851,11 +858,7 @@ impl BitMatrix { pub fn iter(&self, row: R) -> BitIter<'_, C> { assert!(row.index() < self.num_rows); let (start, end) = self.range(row); - BitIter { - cur: None, - iter: self.words[start..end].iter().enumerate(), - marker: PhantomData, - } + BitIter::new(&self.words[start..end]) } /// Returns the number of elements in `row`. From 60851b08e523e1a3ab4defc8b6049751b6bf1ad5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Oct 2019 10:11:30 +1100 Subject: [PATCH 413/545] Optimize `BitSet` iteration. This commit removes an `Option` check in `BitIter::next()`, avoids calling `trailing_zeros()` when it's not necessary, and avoids the need for `enumerate()`. This gives a tiny (0.2%) instruction count win on a couple of benchmarks. The commit also adds some comments, which is good because this iteration code is moderately complex. --- src/librustc_index/bit_set.rs | 44 ++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs index bfaeb847d80b..d8c6e4c33e2f 100644 --- a/src/librustc_index/bit_set.rs +++ b/src/librustc_index/bit_set.rs @@ -287,17 +287,32 @@ impl ToString for BitSet { } pub struct BitIter<'a, T: Idx> { - cur: Option<(Word, usize)>, - iter: iter::Enumerate>, + /// A copy of the current word, but with any already-visited bits cleared. + /// (This lets us use `trailing_zeros()` to find the next set bit.) When it + /// is reduced to 0, we move onto the next word. + word: Word, + + /// The offset (measured in bits) of the current word. + offset: usize, + + /// Underlying iterator over the words. + iter: slice::Iter<'a, Word>, + marker: PhantomData } impl<'a, T: Idx> BitIter<'a, T> { #[inline] fn new(words: &'a [Word]) -> BitIter<'a, T> { + // We initialize `word` and `offset` to degenerate values. On the first + // call to `next()` we will fall through to getting the first word from + // `iter`, which sets `word` to the first word (if there is one) and + // `offset` to 0. Doing it this way saves us from having to maintain + // additional state about whether we have started. BitIter { - cur: None, - iter: words.iter().enumerate(), + word: 0, + offset: std::usize::MAX - (WORD_BITS - 1), + iter: words.iter(), marker: PhantomData, } } @@ -307,17 +322,20 @@ impl<'a, T: Idx> Iterator for BitIter<'a, T> { type Item = T; fn next(&mut self) -> Option { loop { - if let Some((ref mut word, offset)) = self.cur { - let bit_pos = word.trailing_zeros() as usize; - if bit_pos != WORD_BITS { - let bit = 1 << bit_pos; - *word ^= bit; - return Some(T::new(bit_pos + offset)) - } + if self.word != 0 { + // Get the position of the next set bit in the current word, + // then clear the bit. + let bit_pos = self.word.trailing_zeros() as usize; + let bit = 1 << bit_pos; + self.word ^= bit; + return Some(T::new(bit_pos + self.offset)) } - let (i, word) = self.iter.next()?; - self.cur = Some((*word, WORD_BITS * i)); + // Move onto the next word. `wrapping_add()` is needed to handle + // the degenerate initial value given to `offset` in `new()`. + let word = self.iter.next()?; + self.word = *word; + self.offset = self.offset.wrapping_add(WORD_BITS); } } } From 1a2597b64a9d76eb336878e9b0b9dd4021b0240c Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 9 Sep 2019 21:04:26 +0100 Subject: [PATCH 414/545] Don't use `gensym_if_underscore` to resolve `_` bindings Instead add a disambiguator to the keys used for distinguishing resolutions. --- src/librustc_resolve/build_reduced_graph.rs | 16 ++-- src/librustc_resolve/diagnostics.rs | 6 +- src/librustc_resolve/lib.rs | 38 +++++++-- src/librustc_resolve/resolve_imports.rs | 94 ++++++++++----------- 4 files changed, 91 insertions(+), 63 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 030f9b97eb8b..d1c2fa77c016 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -93,7 +93,8 @@ impl<'a> Resolver<'a> { where T: ToNameBinding<'a>, { let binding = def.to_name_binding(self.arenas); - if let Err(old_binding) = self.try_define(parent, ident, ns, binding) { + let key = self.new_key(ident, ns); + if let Err(old_binding) = self.try_define(parent, key, binding) { self.report_conflict(parent, ident, ns, old_binding, &binding); } } @@ -349,9 +350,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.indeterminate_imports.push(directive); match directive.subclass { + // Don't add unresolved underscore imports to modules + SingleImport { target: Ident { name: kw::Underscore, .. }, .. } => {} SingleImport { target, type_ns_only, .. } => { self.r.per_ns(|this, ns| if !type_ns_only || ns == TypeNS { - let mut resolution = this.resolution(current_module, target, ns).borrow_mut(); + let key = this.new_key(target, ns); + let mut resolution = this.resolution(current_module, key).borrow_mut(); resolution.add_single_import(directive); }); } @@ -407,7 +411,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }; match use_tree.kind { ast::UseTreeKind::Simple(rename, ..) => { - let mut ident = use_tree.ident().gensym_if_underscore(); + let mut ident = use_tree.ident(); let mut module_path = prefix; let mut source = module_path.pop().unwrap(); let mut type_ns_only = false; @@ -585,7 +589,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let parent_scope = &self.parent_scope; let parent = parent_scope.module; let expansion = parent_scope.expansion; - let ident = item.ident.gensym_if_underscore(); + let ident = item.ident; let sp = item.span; let vis = self.resolve_visibility(&item.vis); @@ -850,10 +854,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) { let parent = self.parent_scope.module; let Export { ident, res, vis, span } = child; - // FIXME: We shouldn't create the gensym here, it should come from metadata, - // but metadata cannot encode gensyms currently, so we create it here. - // This is only a guess, two equivalent idents may incorrectly get different gensyms here. - let ident = ident.gensym_if_underscore(); let expansion = ExpnId::root(); // FIXME(jseyfried) intercrate hygiene // Record primary definitions. match res { diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index d713315decbe..de8758086709 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -80,11 +80,11 @@ impl<'a> Resolver<'a> { names: &mut Vec, filter_fn: &impl Fn(Res) -> bool, ) { - for (&(ident, _), resolution) in self.resolutions(module).borrow().iter() { + for (key, resolution) in self.resolutions(module).borrow().iter() { if let Some(binding) = resolution.borrow().binding { let res = binding.res(); if filter_fn(res) { - names.push(TypoSuggestion::from_res(ident.name, res)); + names.push(TypoSuggestion::from_res(key.ident.name, res)); } } } @@ -849,7 +849,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } let resolutions = self.r.resolutions(crate_module).borrow(); - let resolution = resolutions.get(&(ident, MacroNS))?; + let resolution = resolutions.get(&self.r.new_key(ident, MacroNS))?; let binding = resolution.borrow().binding()?; if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { let module_name = crate_module.kind.name().unwrap(); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e0ff15390091..e86d2231fa19 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -431,7 +431,22 @@ impl ModuleKind { } } -type Resolutions<'a> = RefCell>>>; +/// A key that identifies a binding in a given `Module`. +/// +/// Multiple bindings in the same module can have the same key (in a valid +/// 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 + /// identifier. + ident: Ident, + ns: Namespace, + /// 0 if ident is not `_`, otherwise a value that's unique to the specific + /// `_` in the expanded AST that introduced this binding. + disambiguator: u32, +} + +type Resolutions<'a> = RefCell>>>; /// One node in the tree of modules. pub struct ModuleData<'a> { @@ -491,8 +506,8 @@ impl<'a> ModuleData<'a> { fn for_each_child(&'a self, resolver: &mut R, mut f: F) where R: AsMut>, F: FnMut(&mut R, Ident, Namespace, &'a NameBinding<'a>) { - for (&(ident, ns), name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { - name_resolution.borrow().binding.map(|binding| f(resolver, ident, ns, binding)); + for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { + name_resolution.borrow().binding.map(|binding| f(resolver, key.ident, key.ns, binding)); } } @@ -879,6 +894,7 @@ pub struct Resolver<'a> { module_map: FxHashMap>, extern_module_map: FxHashMap<(DefId, bool /* MacrosOnly? */), Module<'a>>, binding_parent_modules: FxHashMap>, Module<'a>>, + underscore_disambiguator: u32, /// Maps glob imports to the names of items actually imported. pub glob_map: GlobMap, @@ -1156,6 +1172,7 @@ impl<'a> Resolver<'a> { label_res_map: Default::default(), export_map: FxHashMap::default(), trait_map: Default::default(), + underscore_disambiguator: 0, empty_module, module_map, block_map: Default::default(), @@ -1280,6 +1297,17 @@ impl<'a> Resolver<'a> { self.arenas.alloc_module(module) } + fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey { + let ident = ident.modern(); + let disambiguator = if ident.name == kw::Underscore { + self.underscore_disambiguator += 1; + self.underscore_disambiguator + } else { + 0 + }; + BindingKey { ident, ns, disambiguator } + } + fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> { if module.populate_on_access.get() { module.populate_on_access.set(false); @@ -1288,9 +1316,9 @@ impl<'a> Resolver<'a> { &module.lazy_resolutions } - fn resolution(&mut self, module: Module<'a>, ident: Ident, ns: Namespace) + fn resolution(&mut self, module: Module<'a>, key: BindingKey) -> &'a RefCell> { - *self.resolutions(module).borrow_mut().entry((ident.modern(), ns)) + *self.resolutions(module).borrow_mut().entry(key) .or_insert_with(|| self.arenas.alloc_name_resolution()) } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 360343169bc3..56fd2da2576f 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -7,7 +7,7 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, PerNS, ScopeSet, ParentScope use crate::Determinacy::{self, *}; use crate::Namespace::{self, TypeNS, MacroNS}; use crate::{NameBinding, NameBindingKind, ToNameBinding, PathResult, PrivacyError}; -use crate::{Resolver, ResolutionError, Segment, ModuleKind}; +use crate::{Resolver, ResolutionError, BindingKey, Segment, ModuleKind}; use crate::{names_to_string, module_to_string}; use crate::diagnostics::Suggestion; @@ -235,7 +235,8 @@ impl<'a> Resolver<'a> { } }; - let resolution = self.resolution(module, ident, ns) + let key = self.new_key(ident, ns); + let resolution = self.resolution(module, key) .try_borrow_mut() .map_err(|_| (Determined, Weak::No))?; // This happens when there is a cycle of imports. @@ -447,17 +448,16 @@ impl<'a> Resolver<'a> { } // Define the name or return the existing binding if there is a collision. - pub fn try_define( + crate fn try_define( &mut self, module: Module<'a>, - ident: Ident, - ns: Namespace, + key: BindingKey, binding: &'a NameBinding<'a>, ) -> Result<(), &'a NameBinding<'a>> { let res = binding.res(); - self.check_reserved_macro_name(ident, res); + self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); - self.update_resolution(module, ident, ns, |this, resolution| { + self.update_resolution(module, key, |this, resolution| { if let Some(old_binding) = resolution.binding { if res == Res::Err { // Do not override real bindings with `Res::Err`s from error recovery. @@ -479,8 +479,9 @@ impl<'a> Resolver<'a> { } else { (binding, old_binding) }; - if glob_binding.res() != nonglob_binding.res() && - ns == MacroNS && nonglob_binding.expansion != ExpnId::root() { + if glob_binding.res() != nonglob_binding.res() + && key.ns == MacroNS && nonglob_binding.expansion != ExpnId::root() + { resolution.binding = Some(this.ambiguity( AmbiguityKind::GlobVsExpanded, nonglob_binding, @@ -499,9 +500,9 @@ impl<'a> Resolver<'a> { DUPLICATE_MACRO_EXPORTS, CRATE_NODE_ID, binding.span, - &format!("a macro named `{}` has already been exported", ident), + &format!("a macro named `{}` has already been exported", key.ident), BuiltinLintDiagnostics::DuplicatedMacroExports( - ident, old_binding.span, binding.span)); + key.ident, old_binding.span, binding.span)); resolution.binding = Some(binding); } else { @@ -531,9 +532,9 @@ impl<'a> Resolver<'a> { // Use `f` to mutate the resolution of the name in the module. // If the resolution becomes a success, define it in the module's glob importers. fn update_resolution( - &mut self, module: Module<'a>, - ident: Ident, - ns: Namespace, + &mut self, + module: Module<'a>, + key: BindingKey, f: F, ) -> T where F: FnOnce(&mut Resolver<'a>, &mut NameResolution<'a>) -> T @@ -541,7 +542,7 @@ impl<'a> Resolver<'a> { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. let (binding, t) = { - let resolution = &mut *self.resolution(module, ident, ns).borrow_mut(); + let resolution = &mut *self.resolution(module, key).borrow_mut(); let old_binding = resolution.binding(); let t = f(self, resolution); @@ -558,7 +559,7 @@ impl<'a> Resolver<'a> { // Define `binding` in `module`s glob importers. for directive in module.glob_importers.borrow_mut().iter() { - let mut ident = ident.modern(); + let mut ident = key.ident; let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) { Some(Some(def)) => self.macro_def_scope(def), Some(None) => directive.parent_scope.module, @@ -566,7 +567,8 @@ impl<'a> Resolver<'a> { }; if self.is_accessible_from(binding.vis, scope) { let imported_binding = self.import(binding, directive); - let _ = self.try_define(directive.parent_scope.module, ident, ns, imported_binding); + let key = BindingKey { ident, ..key }; + let _ = self.try_define(directive.parent_scope.module, key, imported_binding); } } @@ -580,7 +582,8 @@ impl<'a> Resolver<'a> { let dummy_binding = self.dummy_binding; let dummy_binding = self.import(dummy_binding, directive); self.per_ns(|this, ns| { - let _ = this.try_define(directive.parent_scope.module, target, ns, dummy_binding); + let key = this.new_key(target, ns); + let _ = this.try_define(directive.parent_scope.module, key, dummy_binding); // Consider erroneous imports used to avoid duplicate diagnostics. this.record_use(target, ns, dummy_binding, false); }); @@ -820,8 +823,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let parent = directive.parent_scope.module; match source_bindings[ns].get() { Err(Undetermined) => indeterminate = true, + // Don't update the resolution, because it was never added. + Err(Determined) if target.name == kw::Underscore => {} Err(Determined) => { - this.update_resolution(parent, target, ns, |_, resolution| { + let key = this.new_key(target, ns); + this.update_resolution(parent, key, |_, resolution| { resolution.single_imports.remove(&PtrKey(directive)); }); } @@ -1052,7 +1058,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { _ => None, }; let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter()); - let names = resolutions.filter_map(|(&(ref i, _), resolution)| { + let names = resolutions.filter_map(|(BindingKey { ident: i, .. }, resolution)| { if *i == ident { return None; } // Never suggest the same name match *resolution.borrow() { NameResolution { binding: Some(name_binding), .. } => { @@ -1301,19 +1307,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. - let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(ident, resolution)| { - resolution.borrow().binding().map(|binding| (*ident, binding)) + let bindings = self.r.resolutions(module).borrow().iter().filter_map(|(key, resolution)| { + resolution.borrow().binding().map(|binding| (*key, binding)) }).collect::>(); - for ((mut ident, ns), binding) in bindings { - let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) { + for (mut key, binding) in bindings { + let scope = match key.ident.span.reverse_glob_adjust(module.expansion, directive.span) { Some(Some(def)) => self.r.macro_def_scope(def), Some(None) => directive.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, ident, ns, imported_binding); + let _ = self.r.try_define(directive.parent_scope.module, key, imported_binding); } } @@ -1329,29 +1334,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut reexports = Vec::new(); - for (&(ident, ns), resolution) in self.r.resolutions(module).borrow().iter() { - let resolution = &mut *resolution.borrow_mut(); - let binding = match resolution.binding { - Some(binding) => binding, - None => continue, - }; - + module.for_each_child(self.r, |this, ident, ns, binding| { // Filter away ambiguous imports and anything that has def-site // hygiene. // FIXME: Implement actual cross-crate hygiene. let is_good_import = binding.is_import() && !binding.is_ambiguity() - && !ident.span.modern().from_expansion(); + && !ident.span.from_expansion(); if is_good_import || binding.is_macro_def() { let res = binding.res(); if res != Res::Err { if let Some(def_id) = res.opt_def_id() { if !def_id.is_local() { - self.r.cstore.export_macros_untracked(def_id.krate); + this.cstore.export_macros_untracked(def_id.krate); } } reexports.push(Export { - ident: ident.modern(), - res: res, + ident, + res, span: binding.span, vis: binding.vis, }); @@ -1360,7 +1359,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind { if ns == TypeNS && orig_binding.is_variant() && - !orig_binding.vis.is_at_least(binding.vis, &*self) { + !orig_binding.vis.is_at_least(binding.vis, &*this) { let msg = match directive.subclass { ImportDirectiveSubclass::SingleImport { .. } => { format!("variant `{}` is private and cannot be re-exported", @@ -1372,33 +1371,34 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let error_id = (DiagnosticMessageId::ErrorId(0), // no code?! Some(binding.span), msg.clone()); - let fresh = self.r.session.one_time_diagnostics + let fresh = this.session.one_time_diagnostics .borrow_mut().insert(error_id); if !fresh { - continue; + return; } msg }, ref s @ _ => bug!("unexpected import subclass {:?}", s) }; - let mut err = self.r.session.struct_span_err(binding.span, &msg); + let mut err = this.session.struct_span_err(binding.span, &msg); let imported_module = match directive.imported_module.get() { Some(ModuleOrUniformRoot::Module(module)) => module, _ => bug!("module should exist"), }; let parent_module = imported_module.parent.expect("parent should exist"); - let resolutions = self.r.resolutions(parent_module).borrow(); + 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_resolution = resolutions.get(&(enum_ident, TypeNS)) + let key = this.new_key(enum_ident, TypeNS); + let enum_resolution = resolutions.get(&key) .expect("resolution should exist"); let enum_span = enum_resolution.borrow() .binding.expect("binding should exist") .span; - let enum_def_span = self.r.session.source_map().def_span(enum_span); - let enum_def_snippet = self.r.session.source_map() + let enum_def_span = this.session.source_map().def_span(enum_span); + let enum_def_snippet = this.session.source_map() .span_to_snippet(enum_def_span).expect("snippet should exist"); // potentially need to strip extant `crate`/`pub(path)` for suggestion let after_vis_index = enum_def_snippet.find("enum") @@ -1406,7 +1406,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let suggestion = format!("pub {}", &enum_def_snippet[after_vis_index..]); - self.r.session + this.session .diag_span_suggestion_once(&mut err, DiagnosticMessageId::ErrorId(0), enum_def_span, @@ -1415,7 +1415,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { err.emit(); } } - } + }); if reexports.len() > 0 { if let Some(def_id) = module.def_id() { From 94967f23f793ca7849fd59239d4526acb93b913a Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 16:40:20 +0100 Subject: [PATCH 415/545] Remove gensyms --- src/libsyntax_pos/symbol.rs | 90 ++++--------------------------- src/libsyntax_pos/symbol/tests.rs | 7 --- 2 files changed, 9 insertions(+), 88 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 2b005c3fc421..d17e909c4d53 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -807,25 +807,13 @@ impl Ident { Ident::new(self.name, self.span.modern_and_legacy()) } - /// Transforms an underscore identifier into one with the same name, but - /// gensymed. Leaves non-underscore identifiers unchanged. - pub fn gensym_if_underscore(self) -> Ident { - if self.name == kw::Underscore { - let name = with_interner(|interner| interner.gensymed(self.name)); - Ident::new(name, self.span) - } else { - self - } - } - /// Convert the name to a `LocalInternedString`. This is a slowish /// operation because it requires locking the symbol interner. pub fn as_str(self) -> LocalInternedString { self.name.as_str() } - /// Convert the name to an `InternedString`. This is a slowish operation - /// because it requires locking the symbol interner. + /// Convert the name to an `InternedString`. pub fn as_interned_str(self) -> InternedString { self.name.as_interned_str() } @@ -880,26 +868,9 @@ impl UseSpecializedDecodable for Ident { } } -/// A symbol is an interned or gensymed string. A gensym is a symbol that is -/// never equal to any other symbol. +/// An interned string. /// -/// Conceptually, a gensym can be thought of as a normal symbol with an -/// invisible unique suffix. Gensyms are useful when creating new identifiers -/// that must not match any existing identifiers, e.g. during macro expansion -/// and syntax desugaring. Because gensyms should always be identifiers, all -/// gensym operations are on `Ident` rather than `Symbol`. (Indeed, in the -/// future the gensym-ness may be moved from `Symbol` to hygiene data.) -/// -/// Examples: -/// ``` -/// assert_eq!(Ident::from_str("_"), Ident::from_str("_")) -/// assert_ne!(Ident::from_str("_").gensym_if_underscore(), Ident::from_str("_")) -/// assert_ne!( -/// Ident::from_str("_").gensym_if_underscore(), -/// Ident::from_str("_").gensym_if_underscore(), -/// ) -/// ``` -/// Internally, a symbol is implemented as an index, and all operations +/// Internally, a `Symbol` is implemented as an index, and all operations /// (including hashing, equality, and ordering) operate on that index. The use /// of `rustc_index::newtype_index!` means that `Option` only takes up 4 bytes, /// because `rustc_index::newtype_index!` reserves the last 256 values for tagging purposes. @@ -950,12 +921,9 @@ impl Symbol { }) } - /// Convert to an `InternedString`. This is a slowish operation because it - /// requires locking the symbol interner. + /// Convert to an `InternedString`. pub fn as_interned_str(self) -> InternedString { - with_interner(|interner| InternedString { - symbol: interner.interned(self) - }) + InternedString { symbol: self } } pub fn as_u32(self) -> u32 { @@ -965,12 +933,7 @@ impl Symbol { impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let is_gensymed = with_interner(|interner| interner.is_gensymed(*self)); - if is_gensymed { - write!(f, "{}({:?})", self, self.0) - } else { - write!(f, "{}", self) - } + fmt::Display::fmt(self, f) } } @@ -993,15 +956,11 @@ impl Decodable for Symbol { } // The `&'static str`s in this type actually point into the arena. -// -// Note that normal symbols are indexed upward from 0, and gensyms are indexed -// downward from SymbolIndex::MAX_AS_U32. #[derive(Default)] pub struct Interner { arena: DroplessArena, names: FxHashMap<&'static str, Symbol>, strings: Vec<&'static str>, - gensyms: Vec, } impl Interner { @@ -1034,34 +993,10 @@ impl Interner { self.names.insert(string, name); name } - - fn interned(&self, symbol: Symbol) -> Symbol { - if (symbol.0.as_usize()) < self.strings.len() { - symbol - } else { - self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize] - } - } - - fn gensymed(&mut self, symbol: Symbol) -> Symbol { - self.gensyms.push(symbol); - Symbol::new(SymbolIndex::MAX_AS_U32 - self.gensyms.len() as u32 + 1) - } - - fn is_gensymed(&mut self, symbol: Symbol) -> bool { - symbol.0.as_usize() >= self.strings.len() - } - // Get the symbol as a string. `Symbol::as_str()` should be used in // preference to this function. pub fn get(&self, symbol: Symbol) -> &str { - match self.strings.get(symbol.0.as_usize()) { - Some(string) => string, - None => { - let symbol = self.gensyms[(SymbolIndex::MAX_AS_U32 - symbol.0.as_u32()) as usize]; - self.strings[symbol.0.as_usize()] - } - } + self.strings[symbol.0.as_usize()] } } @@ -1246,19 +1181,12 @@ impl fmt::Display for LocalInternedString { } } -/// An alternative to `Symbol` that is focused on string contents. It has two -/// main differences to `Symbol`. +/// An alternative to `Symbol` that is focused on string contents. /// -/// First, its implementations of `Hash`, `PartialOrd` and `Ord` work with the +/// Its implementations of `Hash`, `PartialOrd` and `Ord` work with the /// string chars rather than the symbol integer. This is useful when hash /// stability is required across compile sessions, or a guaranteed sort /// ordering is required. -/// -/// Second, gensym-ness is irrelevant. E.g.: -/// ``` -/// assert_ne!(Symbol::gensym("x"), Symbol::gensym("x")) -/// assert_eq!(Symbol::gensym("x").as_interned_str(), Symbol::gensym("x").as_interned_str()) -/// ``` #[derive(Clone, Copy, PartialEq, Eq)] pub struct InternedString { symbol: Symbol, diff --git a/src/libsyntax_pos/symbol/tests.rs b/src/libsyntax_pos/symbol/tests.rs index 1b91c9bb845a..f74b9a0cd1d1 100644 --- a/src/libsyntax_pos/symbol/tests.rs +++ b/src/libsyntax_pos/symbol/tests.rs @@ -14,13 +14,6 @@ fn interner_tests() { assert_eq!(i.intern("cat"), Symbol::new(1)); // dog is still at zero assert_eq!(i.intern("dog"), Symbol::new(0)); - let z = i.intern("zebra"); - assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32)); - // gensym of same string gets new number: - assert_eq!(i.gensymed(z), Symbol::new(SymbolIndex::MAX_AS_U32 - 1)); - // gensym of *existing* string gets new number: - let d = i.intern("dog"); - assert_eq!(i.gensymed(d), Symbol::new(SymbolIndex::MAX_AS_U32 - 2)); } #[test] From 4198df1f4be969747bc92254185ae4983e8f3c5c Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 31 Aug 2019 16:41:13 +0100 Subject: [PATCH 416/545] Remove some mentions of gensyms --- src/librustc/ty/print/pretty.rs | 2 +- src/libsyntax/ext/proc_macro_server.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index c4967f8d66da..363109a0582d 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1483,7 +1483,7 @@ impl FmtPrinter<'_, 'tcx, F> { } // Replace any anonymous late-bound regions with named - // variants, using gensym'd identifiers, so that we can + // variants, using new unique identifiers, so that we can // clearly differentiate between named and unnamed regions in // the output. We'll probably want to tweak this over time to // decide just how much information to give. diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax/ext/proc_macro_server.rs index 021ec46d987c..63e974e323ab 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax/ext/proc_macro_server.rs @@ -332,8 +332,7 @@ impl Ident { if !Self::is_valid(&string) { panic!("`{:?}` is not a valid identifier", string) } - // Get rid of gensyms to conservatively check rawness on the string contents only. - if is_raw && !sym.as_interned_str().as_symbol().can_be_raw() { + if is_raw && !sym.can_be_raw() { panic!("`{}` cannot be a raw identifier", string); } Ident { sym, is_raw, span } From 33543ed1222898a63cca907ec91492c39fa2732e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 15 Oct 2019 13:52:34 -0700 Subject: [PATCH 417/545] Update clippy --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 5cb983338e92..52cebb1f8f87 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 5cb983338e924ec85898880d60e65f2a1291b7be +Subproject commit 52cebb1f8f8789b97d243c07bf4c961ca0017f7b From 190589f8a732393047bd0dc10b27a9aae4410944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 7 Oct 2019 14:23:56 -0700 Subject: [PATCH 418/545] Use structured suggestion for restricting bounds When a trait bound is not met and restricting a type parameter would make the restriction hold, use a structured suggestion pointing at an appropriate place (type param in param list or `where` clause). Account for opaque parameters where instead of suggesting extending the `where` clause, we suggest appending the new restriction: `fn foo(impl Trait + UnmetTrait)`. --- src/librustc/traits/error_reporting.rs | 97 ++++++++++++++++++- ...iated-const-type-parameter-arrays-2.stderr | 4 +- ...ociated-const-type-parameter-arrays.stderr | 4 +- ...types-invalid-trait-ref-issue-18865.stderr | 4 +- .../ui/bad/bad-method-typaram-kind.stderr | 3 +- .../ui/closures/closure-bounds-subtype.stderr | 4 +- .../dst/dst-object-from-unsized-type.stderr | 6 +- ...igher-ranker-supertraits-transitive.stderr | 5 +- .../hrtb-higher-ranker-supertraits.stderr | 10 +- .../ui/kindck/kindck-impl-type-params.stderr | 16 ++- src/test/ui/phantom-oibit.stderr | 8 +- .../ui/suggestions/restrict-type-argument.rs | 31 ++++++ .../suggestions/restrict-type-argument.stderr | 83 ++++++++++++++++ .../traits/trait-suggest-where-clause.stderr | 8 +- .../traits-repeated-supertrait-ambig.stderr | 8 +- .../generic_underconstrained.stderr | 4 +- .../generic_underconstrained2.stderr | 8 +- ...ypeck-default-trait-impl-send-param.stderr | 3 +- .../ui/unsized/unsized-bare-typaram.stderr | 5 +- src/test/ui/unsized/unsized-enum.stderr | 5 +- src/test/ui/unsized/unsized-struct.stderr | 10 +- src/test/ui/unsized3.stderr | 18 ++-- src/test/ui/unsized6.stderr | 51 +++++++--- .../wf/wf-impl-associated-type-trait.stderr | 4 +- ...f-inherent-impl-method-where-clause.stderr | 4 +- 25 files changed, 335 insertions(+), 68 deletions(-) create mode 100644 src/test/ui/suggestions/restrict-type-argument.rs create mode 100644 src/test/ui/suggestions/restrict-type-argument.stderr diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 9eb91569ed5c..b7c7fd4729f0 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -715,8 +715,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // these notes will often be of the form // "the type `T` can't be frobnicated" // which is somewhat confusing. - err.help(&format!("consider adding a `where {}` bound", - trait_ref.to_predicate())); + 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. @@ -960,6 +963,96 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.emit(); } + fn suggest_restricting_param_bound( + &self, + err: &mut DiagnosticBuilder<'_>, + trait_ref: &ty::PolyTraitRef<'_>, + body_id: hir::HirId, + ) { + let node = self.tcx.hir().find(self.tcx.hir().get_parent_item(body_id)); + if let ty::Param(param_ty) = &trait_ref.self_ty().kind { + let restrict_msg = "consider further restricting this bound"; + let param_name = param_ty.name.as_str(); + + if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Struct(_, generics), span, .. + })) | + Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Enum(_, generics), span, .. + })) | + Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Union(_, generics), span, .. + })) | + Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Trait(_, _, generics, ..), span, .. + })) | + Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, .. + })) | + Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(_, _, generics, _), span, .. + })) = &node { + for param in &generics.params { + if param_name == param.name.ident().as_str() { + if param_name.starts_with("impl ") { + err.span_suggestion( + param.span, + restrict_msg, + // `impl CurrentTrait + MissingTrait` + format!("{} + {}", param.name.ident(), trait_ref), + Applicability::MachineApplicable, + ); + } else { + if generics.where_clause.predicates.is_empty() && + param.bounds.is_empty() + { + err.span_suggestion( + param.span, + "consider restricting this bound", + format!("{}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } else if !generics.where_clause.predicates.is_empty() { + err.span_suggestion( + generics.where_clause.span().unwrap().shrink_to_hi(), + &format!( + "consider further restricting type parameter `{}`", + param_ty, + ), + format!(", {}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } else { + let sp = param.span.with_hi(span.hi()); + let span = self.tcx.sess.source_map().span_through_char(sp, ':'); + if sp != param.span && sp != span { + // Only suggest if we have high certainty that the span covers + // the colon in `foo`. + err.span_suggestion(span, restrict_msg, format!( + "{} + ", + trait_ref.to_predicate(), + ), Applicability::MachineApplicable); + } else { + err.span_label(param.span, &format!( + "consider adding a `where {}` bound", + trait_ref.to_predicate(), + )); + } + } + } + return; + } + } + } + } + // FIXME: Add special check for `?Sized` so we don't suggest `T: Sized + ?Sized`. + + // Fallback in case we didn't find the type argument. Can happen on associated types + // bounds and when `Self` needs to be restricted, like in the ui test + // `associated-types-projection-to-unrelated-trait-in-method-without-default.rs`. + err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate())); + } + /// 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. fn suggest_borrow_on_unsized_slice( diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr index 30b6b4f3909b..c258892057bf 100644 --- a/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr +++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays-2.stderr @@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: Foo` is not satisfied LL | const Y: usize; | --------------- required by `Foo::Y` ... +LL | pub fn test() { + | -- help: consider further restricting this bound: `A: Foo +` LL | let _array = [4; ::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` - | - = help: consider adding a `where A: Foo` bound error: aborting due to previous error diff --git a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr index 30fa9891a13e..f6c8e99e27a8 100644 --- a/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr +++ b/src/test/ui/associated-const/associated-const-type-parameter-arrays.stderr @@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: Foo` is not satisfied LL | const Y: usize; | --------------- required by `Foo::Y` ... +LL | pub fn test() { + | -- help: consider further restricting this bound: `A: Foo +` LL | let _array: [u32; ::Y]; | ^^^^^^^^^^^^^ the trait `Foo` is not implemented for `A` - | - = help: consider adding a `where A: Foo` bound error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr b/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr index 01f66a18d25b..0b8b7fab1359 100644 --- a/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr +++ b/src/test/ui/associated-types/associated-types-invalid-trait-ref-issue-18865.stderr @@ -1,10 +1,10 @@ error[E0277]: the trait bound `T: Foo` is not satisfied --> $DIR/associated-types-invalid-trait-ref-issue-18865.rs:10:12 | +LL | fn f>(t: &T) { + | -- help: consider further restricting this bound: `T: Foo +` LL | let u: >::Bar = t.get_bar(); | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` - | - = help: consider adding a `where T: Foo` bound error: aborting due to previous error diff --git a/src/test/ui/bad/bad-method-typaram-kind.stderr b/src/test/ui/bad/bad-method-typaram-kind.stderr index c72b96523600..740667f14668 100644 --- a/src/test/ui/bad/bad-method-typaram-kind.stderr +++ b/src/test/ui/bad/bad-method-typaram-kind.stderr @@ -1,11 +1,12 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/bad-method-typaram-kind.rs:2:7 | +LL | fn foo() { + | -- help: consider further restricting this bound: `T: std::marker::Send +` LL | 1.bar::(); | ^^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` - = help: consider adding a `where T: std::marker::Send` bound error: aborting due to previous error diff --git a/src/test/ui/closures/closure-bounds-subtype.stderr b/src/test/ui/closures/closure-bounds-subtype.stderr index 4b703eded69c..05d5bb1e8d5a 100644 --- a/src/test/ui/closures/closure-bounds-subtype.stderr +++ b/src/test/ui/closures/closure-bounds-subtype.stderr @@ -4,11 +4,13 @@ error[E0277]: `F` cannot be shared between threads safely LL | fn take_const_owned(_: F) where F: FnOnce() + Sync + Send { | ---------------- ---- required by this bound in `take_const_owned` ... +LL | fn give_owned(f: F) where F: FnOnce() + Send { + | - help: consider further restricting type parameter `F`: `, F: std::marker::Sync` +LL | take_any(f); LL | take_const_owned(f); | ^ `F` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `F` - = help: consider adding a `where F: std::marker::Sync` bound error: aborting due to previous error diff --git a/src/test/ui/dst/dst-object-from-unsized-type.stderr b/src/test/ui/dst/dst-object-from-unsized-type.stderr index 55ac625fc985..40db575eabd3 100644 --- a/src/test/ui/dst/dst-object-from-unsized-type.stderr +++ b/src/test/ui/dst/dst-object-from-unsized-type.stderr @@ -1,23 +1,25 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/dst-object-from-unsized-type.rs:8:23 | +LL | fn test1(t: &T) { + | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | let u: &dyn Foo = t; | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound = note: required for the cast to the object type `dyn Foo` error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/dst-object-from-unsized-type.rs:13:23 | +LL | fn test2(t: &T) { + | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | let v: &dyn Foo = t as &dyn Foo; | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound = note: required for the cast to the object type `dyn Foo` error[E0277]: the size for values of type `str` cannot be known at compilation time diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr index c2cc8ebad272..afcb467ad471 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits-transitive.stderr @@ -6,10 +6,11 @@ LL | fn want_bar_for_any_ccx(b: &B) LL | where B : for<'ccx> Bar<'ccx> | ------------------- required by this bound in `want_bar_for_any_ccx` ... +LL | where B : Qux + | - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>` +... LL | want_bar_for_any_ccx(b); | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` - | - = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound error: aborting due to previous error diff --git a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr index a93814ad4c25..20913b4f28c8 100644 --- a/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr +++ b/src/test/ui/hrtb/hrtb-higher-ranker-supertraits.stderr @@ -1,6 +1,9 @@ error[E0277]: the trait bound `for<'tcx> F: Foo<'tcx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:18:26 | +LL | where F : Foo<'x> + | - help: consider further restricting type parameter `F`: `, for<'tcx> F: Foo<'tcx>` +... LL | want_foo_for_any_tcx(f); | ^ the trait `for<'tcx> Foo<'tcx>` is not implemented for `F` ... @@ -8,12 +11,13 @@ LL | fn want_foo_for_any_tcx(f: &F) | -------------------- LL | where F : for<'tcx> Foo<'tcx> | ------------------- required by this bound in `want_foo_for_any_tcx` - | - = help: consider adding a `where for<'tcx> F: Foo<'tcx>` bound error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26 | +LL | where B : Bar<'x> + | - help: consider further restricting type parameter `B`: `, for<'ccx> B: Bar<'ccx>` +... LL | want_bar_for_any_ccx(b); | ^ the trait `for<'ccx> Bar<'ccx>` is not implemented for `B` ... @@ -21,8 +25,6 @@ LL | fn want_bar_for_any_ccx(b: &B) | -------------------- LL | where B : for<'ccx> Bar<'ccx> | ------------------- required by this bound in `want_bar_for_any_ccx` - | - = help: consider adding a `where for<'ccx> B: Bar<'ccx>` bound error: aborting due to 2 previous errors diff --git a/src/test/ui/kindck/kindck-impl-type-params.stderr b/src/test/ui/kindck/kindck-impl-type-params.stderr index e6f7088bd463..777a553c2a58 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.stderr @@ -1,42 +1,50 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:18:13 | +LL | fn f(val: T) { + | - help: consider restricting this bound: `T: std::marker::Send` +LL | let t: S = S(marker::PhantomData); LL | let a = &t as &dyn Gettable; | ^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` - = help: consider adding a `where T: std::marker::Send` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:18:13 | +LL | fn f(val: T) { + | - help: consider restricting this bound: `T: std::marker::Copy` +LL | let t: S = S(marker::PhantomData); LL | let a = &t as &dyn Gettable; | ^^ the trait `std::marker::Copy` is not implemented for `T` | - = help: consider adding a `where T: std::marker::Copy` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:25:31 | +LL | fn g(val: T) { + | - help: consider restricting this bound: `T: std::marker::Send` +LL | let t: S = S(marker::PhantomData); LL | let a: &dyn Gettable = &t; | ^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` - = help: consider adding a `where T: std::marker::Send` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:25:31 | +LL | fn g(val: T) { + | - help: consider restricting this bound: `T: std::marker::Copy` +LL | let t: S = S(marker::PhantomData); LL | let a: &dyn Gettable = &t; | ^^ the trait `std::marker::Copy` is not implemented for `T` | - = help: consider adding a `where T: std::marker::Copy` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` diff --git a/src/test/ui/phantom-oibit.stderr b/src/test/ui/phantom-oibit.stderr index ac48ee0cb0fe..4d9d06b8986d 100644 --- a/src/test/ui/phantom-oibit.stderr +++ b/src/test/ui/phantom-oibit.stderr @@ -3,12 +3,13 @@ error[E0277]: `T` cannot be shared between threads safely | LL | fn is_zen(_: T) {} | ------ --- required by this bound in `is_zen` -... +LL | +LL | fn not_sync(x: Guard) { + | - help: consider restricting this bound: `T: std::marker::Sync` LL | is_zen(x) | ^ `T` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `T` - = help: consider adding a `where T: std::marker::Sync` bound = note: required because of the requirements on the impl of `Zen` for `&T` = note: required because it appears within the type `std::marker::PhantomData<&T>` = note: required because it appears within the type `Guard<'_, T>` @@ -19,11 +20,12 @@ error[E0277]: `T` cannot be shared between threads safely LL | fn is_zen(_: T) {} | ------ --- required by this bound in `is_zen` ... +LL | fn nested_not_sync(x: Nested>) { + | - help: consider restricting this bound: `T: std::marker::Sync` LL | is_zen(x) | ^ `T` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `T` - = help: consider adding a `where T: std::marker::Sync` bound = note: required because of the requirements on the impl of `Zen` for `&T` = note: required because it appears within the type `std::marker::PhantomData<&T>` = note: required because it appears within the type `Guard<'_, T>` diff --git a/src/test/ui/suggestions/restrict-type-argument.rs b/src/test/ui/suggestions/restrict-type-argument.rs new file mode 100644 index 000000000000..c4ebfbe922c0 --- /dev/null +++ b/src/test/ui/suggestions/restrict-type-argument.rs @@ -0,0 +1,31 @@ +fn is_send(val: T) {} + +fn use_impl_sync(val: impl Sync) { + is_send(val); //~ ERROR `impl Sync` cannot be sent between threads safely +} + +fn use_where(val: S) where S: Sync { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_bound(val: S) { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_bound_2< + S // Make sure we can synthezise a correct suggestion span for this case + : + Sync +>(val: S) { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_bound_and_where(val: S) where S: std::fmt::Debug { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn use_unbound(val: S) { + is_send(val); //~ ERROR `S` cannot be sent between threads safely +} + +fn main() {} diff --git a/src/test/ui/suggestions/restrict-type-argument.stderr b/src/test/ui/suggestions/restrict-type-argument.stderr new file mode 100644 index 000000000000..d6840ca4d726 --- /dev/null +++ b/src/test/ui/suggestions/restrict-type-argument.stderr @@ -0,0 +1,83 @@ +error[E0277]: `impl Sync` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:4:13 + | +LL | fn is_send(val: T) {} + | ------- ---- required by this bound in `is_send` +LL | +LL | fn use_impl_sync(val: impl Sync) { + | --------- help: consider further restricting this bound: `impl Sync + std::marker::Send` +LL | is_send(val); + | ^^^ `impl Sync` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `impl Sync` + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:8:13 + | +LL | fn is_send(val: T) {} + | ------- ---- required by this bound in `is_send` +... +LL | fn use_where(val: S) where S: Sync { + | - help: consider further restricting type parameter `S`: `, S: std::marker::Send` +LL | is_send(val); + | ^^^ `S` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `S` + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:12:13 + | +LL | fn is_send(val: T) {} + | ------- ---- required by this bound in `is_send` +... +LL | fn use_bound(val: S) { + | -- help: consider further restricting this bound: `S: std::marker::Send +` +LL | is_send(val); + | ^^^ `S` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `S` + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:20:13 + | +LL | fn is_send(val: T) {} + | ------- ---- required by this bound in `is_send` +... +LL | / S // Make sure we can synthezise a correct suggestion span for this case +LL | | : + | |_____- help: consider further restricting this bound: `S: std::marker::Send +` +... +LL | is_send(val); + | ^^^ `S` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `S` + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:24:13 + | +LL | fn is_send(val: T) {} + | ------- ---- required by this bound in `is_send` +... +LL | fn use_bound_and_where(val: S) where S: std::fmt::Debug { + | - help: consider further restricting type parameter `S`: `, S: std::marker::Send` +LL | is_send(val); + | ^^^ `S` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `S` + +error[E0277]: `S` cannot be sent between threads safely + --> $DIR/restrict-type-argument.rs:28:13 + | +LL | fn is_send(val: T) {} + | ------- ---- required by this bound in `is_send` +... +LL | fn use_unbound(val: S) { + | - help: consider restricting this bound: `S: std::marker::Send` +LL | is_send(val); + | ^^^ `S` cannot be sent between threads safely + | + = help: the trait `std::marker::Send` is not implemented for `S` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/traits/trait-suggest-where-clause.stderr b/src/test/ui/traits/trait-suggest-where-clause.stderr index d15edaa9c814..bc9948064a30 100644 --- a/src/test/ui/traits/trait-suggest-where-clause.stderr +++ b/src/test/ui/traits/trait-suggest-where-clause.stderr @@ -1,6 +1,9 @@ error[E0277]: the size for values of type `U` cannot be known at compilation time --> $DIR/trait-suggest-where-clause.rs:9:20 | +LL | fn check() { + | -- help: consider further restricting this bound: `U: std::marker::Sized +` +LL | // suggest a where-clause, if needed LL | mem::size_of::(); | ^ doesn't have a size known at compile-time | @@ -11,11 +14,13 @@ LL | pub const fn size_of() -> usize { | = help: the trait `std::marker::Sized` is not implemented for `U` = note: to learn more, visit - = help: consider adding a `where U: std::marker::Sized` bound error[E0277]: the size for values of type `U` cannot be known at compilation time --> $DIR/trait-suggest-where-clause.rs:12:5 | +LL | fn check() { + | -- help: consider further restricting this bound: `U: std::marker::Sized +` +... LL | mem::size_of::>(); | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | @@ -26,7 +31,6 @@ LL | pub const fn size_of() -> usize { | = help: within `Misc`, the trait `std::marker::Sized` is not implemented for `U` = note: to learn more, visit - = help: consider adding a `where U: std::marker::Sized` bound = note: required because it appears within the type `Misc` error[E0277]: the trait bound `u64: std::convert::From` is not satisfied diff --git a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr index db77e82adbd0..85c7a55c3137 100644 --- a/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr +++ b/src/test/ui/traits/traits-repeated-supertrait-ambig.stderr @@ -7,10 +7,10 @@ LL | c.same_as(22) error[E0277]: the trait bound `C: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:30:7 | +LL | fn with_trait(c: &C) -> bool { + | -- help: consider further restricting this bound: `C: CompareTo +` LL | c.same_as(22) | ^^^^^^^ the trait `CompareTo` is not implemented for `C` - | - = help: consider adding a `where C: CompareTo` bound error[E0277]: the trait bound `dyn CompareToInts: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:34:5 @@ -27,10 +27,10 @@ error[E0277]: the trait bound `C: CompareTo` is not satisfied LL | fn same_as(&self, t: T) -> bool; | -------------------------------- required by `CompareTo::same_as` ... +LL | fn with_ufcs2(c: &C) -> bool { + | -- help: consider further restricting this bound: `C: CompareTo +` LL | CompareTo::same_as(c, 22) | ^^^^^^^^^^^^^^^^^^ the trait `CompareTo` is not implemented for `C` - | - = help: consider adding a `where C: CompareTo` bound error[E0277]: the trait bound `i64: CompareTo` is not satisfied --> $DIR/traits-repeated-supertrait-ambig.rs:42:23 diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr index dd90dd1b06fe..63c07224353e 100644 --- a/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained.stderr @@ -9,8 +9,10 @@ error[E0277]: the trait bound `T: Trait` is not satisfied | LL | type Underconstrained = impl 'static; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` +... +LL | fn underconstrain(_: T) -> Underconstrained { + | - help: consider restricting this bound: `T: Trait` | - = help: consider adding a `where T: Trait` bound = note: the return type of a function must have a statically known size error: aborting due to 2 previous errors diff --git a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr index 574432bdcf6d..ba892f6ed7c7 100644 --- a/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_underconstrained2.stderr @@ -15,9 +15,11 @@ error[E0277]: `U` doesn't implement `std::fmt::Debug` | LL | type Underconstrained = impl 'static; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` +... +LL | fn underconstrained(_: U) -> Underconstrained { + | - help: consider restricting this bound: `U: std::fmt::Debug` | = help: the trait `std::fmt::Debug` is not implemented for `U` - = help: consider adding a `where U: std::fmt::Debug` bound = note: the return type of a function must have a statically known size error[E0277]: `V` doesn't implement `std::fmt::Debug` @@ -25,9 +27,11 @@ error[E0277]: `V` doesn't implement `std::fmt::Debug` | LL | type Underconstrained2 = impl 'static; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `std::fmt::Debug` +... +LL | fn underconstrained2(_: U, _: V) -> Underconstrained2 { + | - help: consider restricting this bound: `V: std::fmt::Debug` | = help: the trait `std::fmt::Debug` is not implemented for `V` - = help: consider adding a `where V: std::fmt::Debug` bound = note: the return type of a function must have a statically known size error: aborting due to 4 previous errors diff --git a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr index b3139083b1ac..a84aef5fdbdb 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-send-param.stderr @@ -1,6 +1,8 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/typeck-default-trait-impl-send-param.rs:5:15 | +LL | fn foo() { + | - help: consider restricting this bound: `T: std::marker::Send` LL | is_send::() | ^ `T` cannot be sent between threads safely ... @@ -8,7 +10,6 @@ LL | fn is_send() { | ------- ---- required by this bound in `is_send` | = help: the trait `std::marker::Send` is not implemented for `T` - = help: consider adding a `where T: std::marker::Send` bound error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-bare-typaram.stderr b/src/test/ui/unsized/unsized-bare-typaram.stderr index e56176690a11..bd97b0203b51 100644 --- a/src/test/ui/unsized/unsized-bare-typaram.stderr +++ b/src/test/ui/unsized/unsized-bare-typaram.stderr @@ -4,11 +4,12 @@ error[E0277]: the size for values of type `T` cannot be known at compilation tim LL | fn bar() { } | --- - required by this bound in `bar` LL | fn foo() { bar::() } - | ^ doesn't have a size known at compile-time + | -- ^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `T: std::marker::Sized +` | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-enum.stderr b/src/test/ui/unsized/unsized-enum.stderr index dff934834ef2..341d3e4cc2df 100644 --- a/src/test/ui/unsized/unsized-enum.stderr +++ b/src/test/ui/unsized/unsized-enum.stderr @@ -5,11 +5,12 @@ LL | enum Foo { FooSome(U), FooNone } | ----------- required by `Foo` LL | fn foo1() { not_sized::>() } // Hunky dory. LL | fn foo2() { not_sized::>() } - | ^^^^^^ doesn't have a size known at compile-time + | -- ^^^^^^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `T: std::marker::Sized +` | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr index 0d4776ff6c25..2894d5d56710 100644 --- a/src/test/ui/unsized/unsized-struct.stderr +++ b/src/test/ui/unsized/unsized-struct.stderr @@ -5,11 +5,12 @@ LL | struct Foo { data: T } | ------------- required by `Foo` LL | fn foo1() { not_sized::>() } // Hunky dory. LL | fn foo2() { not_sized::>() } - | ^^^^^^ doesn't have a size known at compile-time + | -- ^^^^^^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `T: std::marker::Sized +` | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/unsized-struct.rs:13:24 @@ -18,11 +19,12 @@ LL | fn is_sized() { } | -------- - required by this bound in `is_sized` ... LL | fn bar2() { is_sized::>() } - | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | -- ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `T: std::marker::Sized +` | = help: within `Bar`, the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound = note: required because it appears within the type `Bar` error: aborting due to 2 previous errors diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized3.stderr index c821a08f6b58..232296ad0912 100644 --- a/src/test/ui/unsized3.stderr +++ b/src/test/ui/unsized3.stderr @@ -1,6 +1,8 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:7:13 | +LL | fn f1(x: &X) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f2::(x); | ^ doesn't have a size known at compile-time ... @@ -9,11 +11,12 @@ LL | fn f2(x: &X) { | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:18:13 | +LL | fn f3(x: &X) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f4::(x); | ^ doesn't have a size known at compile-time ... @@ -22,7 +25,6 @@ LL | fn f4(x: &X) { | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:33:8 @@ -30,35 +32,38 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn f5(x: &Y) {} | -- - required by this bound in `f5` ... +LL | fn f8(x1: &S, x2: &S) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f5(x1); | ^^ doesn't have a size known at compile-time | = help: within `S`, the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: required because it appears within the type `S` error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:40:8 | +LL | fn f9(x1: Box>) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f5(&(*x1, 34)); | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `S`, the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: required because it appears within the type `S` = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:45:9 | +LL | fn f10(x1: Box>) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f5(&(32, *x1)); | ^^^^^^^^^ doesn't have a size known at compile-time | = help: within `({integer}, S)`, the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: required because it appears within the type `S` = note: required because it appears within the type `({integer}, S)` = note: tuples must have a statically known size to be initialized @@ -69,12 +74,13 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim LL | fn f5(x: &Y) {} | -- - required by this bound in `f5` ... +LL | fn f10(x1: Box>) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f5(&(32, *x1)); | ^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `({integer}, S)`, the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: required because it appears within the type `S` = note: required because it appears within the type `({integer}, S)` diff --git a/src/test/ui/unsized6.stderr b/src/test/ui/unsized6.stderr index a6a26573e7c5..95acd987a5a2 100644 --- a/src/test/ui/unsized6.stderr +++ b/src/test/ui/unsized6.stderr @@ -1,129 +1,148 @@ error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized6.rs:9:9 | +LL | fn f1(x: &X) { + | -- help: consider further restricting this bound: `Y: std::marker::Sized +` +... LL | let y: Y; | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Y` = note: to learn more, visit - = help: consider adding a `where Y: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:7:12 | +LL | fn f1(x: &X) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` +LL | let _: W; // <-- this is OK, no bindings created, no initializer. LL | let _: (isize, (X, isize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `Z` cannot be known at compilation time --> $DIR/unsized6.rs:11:12 | +LL | fn f1(x: &X) { + | -- help: consider further restricting this bound: `Z: std::marker::Sized +` +... LL | let y: (isize, (Z, usize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Z` = note: to learn more, visit - = help: consider adding a `where Z: std::marker::Sized` bound = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:15:9 | +LL | fn f2(x: &X) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | let y: X; | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized6.rs:17:12 | +LL | fn f2(x: &X) { + | -- help: consider further restricting this bound: `Y: std::marker::Sized +` +... LL | let y: (isize, (Y, isize)); | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Y` = note: to learn more, visit - = help: consider adding a `where Y: std::marker::Sized` bound = note: only the last element of a tuple may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:22:9 | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | let y: X = *x1; | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:24:9 | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` +... LL | let y = *x2; | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:26:10 | +LL | fn f3(x1: Box, x2: Box, x3: Box) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` +... LL | let (y, z) = (*x3, 4); | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:30:9 | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | let y: X = *x1; | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:32:9 | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` +... LL | let y = *x2; | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized6.rs:34:10 | +LL | fn f4(x1: Box, x2: Box, x3: Box) { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` +... LL | let (y, z) = (*x3, 4); | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature @@ -131,11 +150,12 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:38:18 | LL | fn g1(x: X) {} - | ^ doesn't have a size known at compile-time + | -- ^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `X: std::marker::Sized +` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature @@ -143,11 +163,12 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized6.rs:40:22 | LL | fn g2(x: X) {} - | ^ doesn't have a size known at compile-time + | -- ^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `X: std::marker::Sized +` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature diff --git a/src/test/ui/wf/wf-impl-associated-type-trait.stderr b/src/test/ui/wf/wf-impl-associated-type-trait.stderr index ceafb4f61578..6d71670e6a84 100644 --- a/src/test/ui/wf/wf-impl-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-impl-associated-type-trait.stderr @@ -4,10 +4,10 @@ error[E0277]: the trait bound `T: MyHash` is not satisfied LL | pub struct MySet { | -------------------------- required by `MySet` ... +LL | impl Foo for T { + | - help: consider restricting this bound: `T: MyHash` LL | type Bar = MySet; | ^^^^^^^^^^^^^^^^^^^^ the trait `MyHash` is not implemented for `T` - | - = help: consider adding a `where T: MyHash` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr index 1e258864d036..21f825ac9ef9 100644 --- a/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr +++ b/src/test/ui/wf/wf-inherent-impl-method-where-clause.stderr @@ -4,11 +4,11 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` ... +LL | impl Foo { + | - help: consider restricting this bound: `U: std::marker::Copy` LL | / fn foo(self) where T: ExtraCopy LL | | {} | |______^ the trait `std::marker::Copy` is not implemented for `U` - | - = help: consider adding a `where U: std::marker::Copy` bound error: aborting due to previous error From 5b7ffd93330142d433ed3035ef838638dc6afa3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Oct 2019 11:03:35 -0700 Subject: [PATCH 419/545] Handle more cases --- src/librustc/traits/error_reporting.rs | 11 ++++++++++- .../builtin-superkinds-double-superkind.stderr | 10 ++++++---- .../builtin-superkinds-in-metadata.stderr | 5 +++-- .../builtin-superkinds-typaram-not-send.stderr | 5 +++-- ...ounds-cant-promote-superkind-in-struct.stderr | 6 ++++-- src/test/ui/issues/issue-21837.stderr | 6 +++--- src/test/ui/issues/issue-27060-2.stderr | 3 ++- .../ui/issues/issue-43784-associated-type.stderr | 6 +++--- src/test/ui/issues/issue-43784-supertrait.stderr | 6 +++--- .../defaultimpl/specialization-wfcheck.stderr | 6 +++--- .../trait-bounds-on-structs-and-enums.stderr | 14 +++++++------- src/test/ui/type/type-check-defaults.stderr | 7 ++++--- src/test/ui/union/union-sized-field.stderr | 9 ++++++--- src/test/ui/unsized/unsized-enum2.stderr | 16 ++++++++++++---- .../unsized-inherent-impl-self-type.stderr | 5 +++-- .../unsized/unsized-trait-impl-self-type.stderr | 5 +++-- .../unsized/unsized-trait-impl-trait-arg.stderr | 5 +++-- src/test/ui/unsized5.stderr | 13 +++++++++---- src/test/ui/unsized7.stderr | 5 +++-- src/test/ui/wf/wf-enum-bound.stderr | 3 +-- .../ui/wf/wf-enum-fields-struct-variant.stderr | 5 +++-- src/test/ui/wf/wf-enum-fields.stderr | 4 ++-- src/test/ui/wf/wf-fn-where-clause.stderr | 7 ++++--- src/test/ui/wf/wf-in-fn-arg.stderr | 7 ++++--- src/test/ui/wf/wf-in-fn-ret.stderr | 7 ++++--- src/test/ui/wf/wf-in-fn-type-arg.stderr | 5 +++-- src/test/ui/wf/wf-in-fn-type-ret.stderr | 5 +++-- src/test/ui/wf/wf-in-fn-where-clause.stderr | 3 +-- src/test/ui/wf/wf-in-obj-type-trait.stderr | 5 +++-- .../ui/wf/wf-inherent-impl-where-clause.stderr | 7 ++++--- src/test/ui/wf/wf-struct-bound.stderr | 3 +-- src/test/ui/wf/wf-struct-field.stderr | 4 ++-- .../ui/wf/wf-trait-associated-type-bound.stderr | 7 ++++--- src/test/ui/wf/wf-trait-bound.stderr | 3 +-- src/test/ui/wf/wf-trait-superbound.stderr | 7 ++++--- 35 files changed, 134 insertions(+), 91 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b7c7fd4729f0..a717fb7f7c0f 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -969,7 +969,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_ref: &ty::PolyTraitRef<'_>, body_id: hir::HirId, ) { - let node = self.tcx.hir().find(self.tcx.hir().get_parent_item(body_id)); + let node = self.tcx.hir() + .find(self.tcx.hir().get_parent_item(body_id)) + .or_else(|| self.tcx.hir().find(body_id)); + debug!( + "suggest_restricting_param_bound node={:?} - trait_ref={:?} ty={:?} ({:?})", + node, + trait_ref, + trait_ref.self_ty(), + trait_ref.self_ty().kind, + ); if let ty::Param(param_ty) = &trait_ref.self_ty().kind { let restrict_msg = "consider further restricting this bound"; let param_name = param_ty.name.as_str(); diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr index 9771436d167d..5be6ab05d660 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-double-superkind.stderr @@ -2,20 +2,22 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/builtin-superkinds-double-superkind.rs:6:24 | LL | impl Foo for (T,) { } - | ^^^ `T` cannot be sent between threads safely + | -- ^^^ `T` cannot be sent between threads safely + | | + | help: consider further restricting this bound: `T: std::marker::Send +` | = help: within `(T,)`, the trait `std::marker::Send` is not implemented for `T` - = help: consider adding a `where T: std::marker::Send` bound = note: required because it appears within the type `(T,)` error[E0277]: `T` cannot be shared between threads safely --> $DIR/builtin-superkinds-double-superkind.rs:9:16 | LL | impl Foo for (T,T) { } - | ^^^ `T` cannot be shared between threads safely + | -- ^^^ `T` cannot be shared between threads safely + | | + | help: consider further restricting this bound: `T: std::marker::Sync +` | = help: within `(T, T)`, the trait `std::marker::Sync` is not implemented for `T` - = help: consider adding a `where T: std::marker::Sync` bound = note: required because it appears within the type `(T, T)` error: aborting due to 2 previous errors diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr index 61c18a24fb0c..8cce9bfdf52a 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -2,10 +2,11 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/builtin-superkinds-in-metadata.rs:13:23 | LL | impl RequiresRequiresShareAndSend for X { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely + | -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `T` cannot be sent between threads safely + | | + | help: consider further restricting this bound: `T: std::marker::Send +` | = help: within `X`, the trait `std::marker::Send` is not implemented for `T` - = help: consider adding a `where T: std::marker::Send` bound = note: required because it appears within the type `X` error: aborting due to previous error diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr index dc5479e5e2da..4381a5b86826 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-typaram-not-send.stderr @@ -2,10 +2,11 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/builtin-superkinds-typaram-not-send.rs:5:24 | LL | impl Foo for T { } - | ^^^ `T` cannot be sent between threads safely + | -- ^^^ `T` cannot be sent between threads safely + | | + | help: consider further restricting this bound: `T: std::marker::Send +` | = help: the trait `std::marker::Send` is not implemented for `T` - = help: consider adding a `where T: std::marker::Send` bound error: aborting due to previous error diff --git a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr index 51077b1b2922..3c8f637e1336 100644 --- a/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr +++ b/src/test/ui/closures/closure-bounds-cant-promote-superkind-in-struct.stderr @@ -4,14 +4,16 @@ error[E0277]: `F` cannot be sent between threads safely LL | struct X where F: FnOnce() + 'static + Send { | ---------------------------------------------- required by `X` ... -LL | / fn foo(blk: F) -> X where F: FnOnce() + 'static { +LL | fn foo(blk: F) -> X where F: FnOnce() + 'static { + | ^ - help: consider further restricting type parameter `F`: `, F: std::marker::Send` + | _| + | | LL | | LL | | return X { field: blk }; LL | | } | |_^ `F` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `F` - = help: consider adding a `where F: std::marker::Send` bound error: aborting due to previous error diff --git a/src/test/ui/issues/issue-21837.stderr b/src/test/ui/issues/issue-21837.stderr index 20d02a90315d..50fdf2d6185b 100644 --- a/src/test/ui/issues/issue-21837.stderr +++ b/src/test/ui/issues/issue-21837.stderr @@ -5,9 +5,9 @@ LL | pub struct Foo(T); | ---------------------------- required by `Foo` ... LL | impl Trait2 for Foo {} - | ^^^^^^ the trait `Bound` is not implemented for `T` - | - = help: consider adding a `where T: Bound` bound + | - ^^^^^^ the trait `Bound` is not implemented for `T` + | | + | help: consider restricting this bound: `T: Bound` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-27060-2.stderr b/src/test/ui/issues/issue-27060-2.stderr index f7227c341014..553041c5106c 100644 --- a/src/test/ui/issues/issue-27060-2.stderr +++ b/src/test/ui/issues/issue-27060-2.stderr @@ -1,12 +1,13 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/issue-27060-2.rs:3:5 | +LL | pub struct Bad { + | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | data: T, | ^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound = note: the last field of a packed struct may only have a dynamically sized type if it does not need drop to be run error: aborting due to previous error diff --git a/src/test/ui/issues/issue-43784-associated-type.stderr b/src/test/ui/issues/issue-43784-associated-type.stderr index fc05d280693b..e91e53499ce6 100644 --- a/src/test/ui/issues/issue-43784-associated-type.stderr +++ b/src/test/ui/issues/issue-43784-associated-type.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-43784-associated-type.rs:13:9 | LL | impl Complete 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 previous error diff --git a/src/test/ui/issues/issue-43784-supertrait.stderr b/src/test/ui/issues/issue-43784-supertrait.stderr index 4c423f2e77fe..5ac32041bce4 100644 --- a/src/test/ui/issues/issue-43784-supertrait.stderr +++ b/src/test/ui/issues/issue-43784-supertrait.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-43784-supertrait.rs:8:9 | LL | impl Complete 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 previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr index 45951561e726..5275b7b1ddfa 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `U: std::cmp::Eq` is not satisfied --> $DIR/specialization-wfcheck.rs:7:17 | LL | default impl Foo<'static, U> for () {} - | ^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `U` - | - = help: consider adding a `where U: std::cmp::Eq` bound + | - ^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `U` + | | + | help: consider restricting this bound: `U: std::cmp::Eq` error: aborting due to previous error diff --git a/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr index bd76df8071a5..96bbd1f3e4f1 100644 --- a/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr +++ b/src/test/ui/traits/trait-bounds-on-structs-and-enums.stderr @@ -5,9 +5,9 @@ LL | struct Foo { | ------------------- required by `Foo` ... LL | impl Foo { - | ^^^^^^ the trait `Trait` is not implemented for `T` - | - = help: consider adding a `where T: Trait` bound + | - ^^^^^^ the trait `Trait` is not implemented for `T` + | | + | help: consider restricting this bound: `T: Trait` error[E0277]: the trait bound `isize: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:19:5 @@ -33,10 +33,10 @@ error[E0277]: the trait bound `U: Trait` is not satisfied LL | struct Foo { | ------------------- required by `Foo` ... +LL | struct Badness { + | - help: consider restricting this bound: `U: Trait` LL | b: Foo, | ^^^^^^^^^ the trait `Trait` is not implemented for `U` - | - = help: consider adding a `where U: Trait` bound error[E0277]: the trait bound `V: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:31:21 @@ -44,10 +44,10 @@ error[E0277]: the trait bound `V: Trait` is not satisfied LL | enum Bar { | ----------------- required by `Bar` ... +LL | enum MoreBadness { + | - help: consider restricting this bound: `V: Trait` LL | EvenMoreBadness(Bar), | ^^^^^^ the trait `Trait` is not implemented for `V` - | - = help: consider adding a `where V: Trait` bound error[E0277]: the trait bound `i32: Trait` is not satisfied --> $DIR/trait-bounds-on-structs-and-enums.rs:35:5 diff --git a/src/test/ui/type/type-check-defaults.stderr b/src/test/ui/type/type-check-defaults.stderr index 742a709958fa..6802bc38b89c 100644 --- a/src/test/ui/type/type-check-defaults.stderr +++ b/src/test/ui/type/type-check-defaults.stderr @@ -52,9 +52,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | trait Super { } | -------------------- required by `Super` LL | trait Base: Super { } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound + | ^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | help: consider restricting this bound: `T: std::marker::Copy` + | the trait `std::marker::Copy` is not implemented for `T` error[E0277]: cannot add `u8` to `i32` --> $DIR/type-check-defaults.rs:24:66 diff --git a/src/test/ui/union/union-sized-field.stderr b/src/test/ui/union/union-sized-field.stderr index 891400306838..c9fec1d21d15 100644 --- a/src/test/ui/union/union-sized-field.stderr +++ b/src/test/ui/union/union-sized-field.stderr @@ -1,34 +1,37 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/union-sized-field.rs:4:5 | +LL | union Foo { + | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | value: T, | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound = note: no field of a union may have a dynamically sized type error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/union-sized-field.rs:9:5 | +LL | struct Foo2 { + | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | value: T, | ^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound = note: only the last field of a struct may have a dynamically sized type error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/union-sized-field.rs:15:11 | +LL | enum Foo3 { + | -- help: consider further restricting this bound: `T: std::marker::Sized +` LL | Value(T), | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `T` = note: to learn more, visit - = help: consider adding a `where T: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error: aborting due to 3 previous errors diff --git a/src/test/ui/unsized/unsized-enum2.stderr b/src/test/ui/unsized/unsized-enum2.stderr index cdd5747d86b0..e85b6d662f9d 100644 --- a/src/test/ui/unsized/unsized-enum2.stderr +++ b/src/test/ui/unsized/unsized-enum2.stderr @@ -1,45 +1,53 @@ error[E0277]: the size for values of type `W` cannot be known at compilation time --> $DIR/unsized-enum2.rs:23:8 | +LL | enum E { + | -- help: consider further restricting this bound: `W: std::marker::Sized +` +LL | // parameter LL | VA(W), | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `W` = note: to learn more, visit - = help: consider adding a `where W: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized-enum2.rs:25:8 | +LL | enum E { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` +... LL | VB{x: X}, | ^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `Y` cannot be known at compilation time --> $DIR/unsized-enum2.rs:27:15 | +LL | enum E { + | -- help: consider further restricting this bound: `Y: std::marker::Sized +` +... LL | VC(isize, Y), | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Y` = note: to learn more, visit - = help: consider adding a `where Y: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `Z` cannot be known at compilation time --> $DIR/unsized-enum2.rs:29:18 | +LL | enum E { + | -- help: consider further restricting this bound: `Z: std::marker::Sized +` +... LL | VD{u: isize, x: Z}, | ^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Z` = note: to learn more, visit - = help: consider adding a `where Z: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `[u8]` cannot be known at compilation time diff --git a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr index 1a726bb089f6..280b8fd43cab 100644 --- a/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-inherent-impl-self-type.stderr @@ -5,11 +5,12 @@ LL | struct S5(Y); | ---------------- required by `S5` LL | LL | impl S5 { - | ^^^^^ doesn't have a size known at compile-time + | -- ^^^^^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `X: std::marker::Sized +` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr index f399f8ded108..ba1550439c0d 100644 --- a/src/test/ui/unsized/unsized-trait-impl-self-type.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-self-type.stderr @@ -5,11 +5,12 @@ LL | struct S5(Y); | ---------------- required by `S5` LL | LL | impl T3 for S5 { - | ^^^^^ doesn't have a size known at compile-time + | -- ^^^^^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `X: std::marker::Sized +` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound error: aborting due to previous error diff --git a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr index ee0d5ccccfe1..41371d63f9e5 100644 --- a/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr +++ b/src/test/ui/unsized/unsized-trait-impl-trait-arg.stderr @@ -2,11 +2,12 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized-trait-impl-trait-arg.rs:8:17 | LL | impl T2 for S4 { - | ^^^^^ doesn't have a size known at compile-time + | -- ^^^^^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `X: std::marker::Sized +` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound error: aborting due to previous error diff --git a/src/test/ui/unsized5.stderr b/src/test/ui/unsized5.stderr index 6dce9a046066..bfd3f4aa691e 100644 --- a/src/test/ui/unsized5.stderr +++ b/src/test/ui/unsized5.stderr @@ -1,23 +1,26 @@ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized5.rs:4:5 | +LL | struct S1 { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | f1: X, | ^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: only the last field of a struct may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized5.rs:10:5 | +LL | struct S2 { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` +LL | f: isize, LL | g: X, | ^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: only the last field of a struct may have a dynamically sized type error[E0277]: the size for values of type `str` cannot be known at compilation time @@ -43,23 +46,25 @@ LL | f: [u8], error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized5.rs:25:8 | +LL | enum E { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | V1(X, isize), | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized5.rs:29:8 | +LL | enum F { + | -- help: consider further restricting this bound: `X: std::marker::Sized +` LL | V2{f1: X, f: isize}, | ^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound = note: no field of an enum variant may have a dynamically sized type error: aborting due to 6 previous errors diff --git a/src/test/ui/unsized7.stderr b/src/test/ui/unsized7.stderr index bb83b1811844..c77503a6f87a 100644 --- a/src/test/ui/unsized7.stderr +++ b/src/test/ui/unsized7.stderr @@ -2,11 +2,12 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim --> $DIR/unsized7.rs:12:21 | LL | impl T1 for S3 { - | ^^^^^ doesn't have a size known at compile-time + | -- ^^^^^ doesn't have a size known at compile-time + | | + | help: consider further restricting this bound: `X: std::marker::Sized +` | = help: the trait `std::marker::Sized` is not implemented for `X` = note: to learn more, visit - = help: consider adding a `where X: std::marker::Sized` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-bound.stderr b/src/test/ui/wf/wf-enum-bound.stderr index d5632f4a9c24..eaacd6b6881e 100644 --- a/src/test/ui/wf/wf-enum-bound.stderr +++ b/src/test/ui/wf/wf-enum-bound.stderr @@ -6,12 +6,11 @@ LL | trait ExtraCopy { } LL | LL | / enum SomeEnum LL | | where T: ExtraCopy + | | - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` LL | | { LL | | SomeVariant(T,U) LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` - | - = help: consider adding a `where U: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr index 51ee23fc5aa6..52882c460d22 100644 --- a/src/test/ui/wf/wf-enum-fields-struct-variant.stderr +++ b/src/test/ui/wf/wf-enum-fields-struct-variant.stderr @@ -4,10 +4,11 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied LL | struct IsCopy { | --------------------- required by `IsCopy` ... +LL | enum AnotherEnum { + | - help: consider restricting this bound: `A: std::marker::Copy` +LL | AnotherVariant { LL | f: IsCopy | ^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` - | - = help: consider adding a `where A: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-enum-fields.stderr b/src/test/ui/wf/wf-enum-fields.stderr index 5f4e7c66f54c..0fea35d68ea6 100644 --- a/src/test/ui/wf/wf-enum-fields.stderr +++ b/src/test/ui/wf/wf-enum-fields.stderr @@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied LL | struct IsCopy { | --------------------- required by `IsCopy` ... +LL | enum SomeEnum { + | - help: consider restricting this bound: `A: std::marker::Copy` LL | SomeVariant(IsCopy) | ^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` - | - = help: consider adding a `where A: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-fn-where-clause.stderr b/src/test/ui/wf/wf-fn-where-clause.stderr index 4bc2e370f29f..9b8b04a7b86a 100644 --- a/src/test/ui/wf/wf-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-fn-where-clause.stderr @@ -4,12 +4,13 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` LL | -LL | / fn foo() where T: ExtraCopy +LL | fn foo() where T: ExtraCopy + | ^ - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` + | _| + | | LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` - | - = help: consider adding a `where U: std::marker::Copy` bound error[E0277]: the size for values of type `(dyn std::marker::Copy + 'static)` cannot be known at compilation time --> $DIR/wf-fn-where-clause.rs:12:1 diff --git a/src/test/ui/wf/wf-in-fn-arg.stderr b/src/test/ui/wf/wf-in-fn-arg.stderr index e7432f819873..3798ba1ec6e7 100644 --- a/src/test/ui/wf/wf-in-fn-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-arg.stderr @@ -4,12 +4,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... -LL | / fn bar(_: &MustBeCopy) +LL | fn bar(_: &MustBeCopy) + | ^ - help: consider restricting this bound: `T: std::marker::Copy` + | _| + | | LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-ret.stderr b/src/test/ui/wf/wf-in-fn-ret.stderr index 005ffe84502d..2e46ce490003 100644 --- a/src/test/ui/wf/wf-in-fn-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-ret.stderr @@ -4,12 +4,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... -LL | / fn bar() -> MustBeCopy +LL | fn bar() -> MustBeCopy + | ^ - help: consider restricting this bound: `T: std::marker::Copy` + | _| + | | LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-arg.stderr b/src/test/ui/wf/wf-in-fn-type-arg.stderr index b4cd92104022..db4fb9f97f52 100644 --- a/src/test/ui/wf/wf-in-fn-type-arg.stderr +++ b/src/test/ui/wf/wf-in-fn-type-arg.stderr @@ -4,10 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... +LL | struct Bar { + | - help: consider restricting this bound: `T: std::marker::Copy` +LL | // needs T: Copy LL | x: fn(MustBeCopy) | ^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-type-ret.stderr b/src/test/ui/wf/wf-in-fn-type-ret.stderr index 988fbed8e910..09f8aa2a2018 100644 --- a/src/test/ui/wf/wf-in-fn-type-ret.stderr +++ b/src/test/ui/wf/wf-in-fn-type-ret.stderr @@ -4,10 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... +LL | struct Foo { + | - help: consider restricting this bound: `T: std::marker::Copy` +LL | // needs T: 'static LL | x: fn() -> MustBeCopy | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-fn-where-clause.stderr b/src/test/ui/wf/wf-in-fn-where-clause.stderr index 0af38ddcffea..979802dec499 100644 --- a/src/test/ui/wf/wf-in-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-in-fn-where-clause.stderr @@ -6,11 +6,10 @@ LL | trait MustBeCopy { ... LL | / fn bar() LL | | where T: MustBeCopy + | | - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` - | - = help: consider adding a `where U: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-in-obj-type-trait.stderr b/src/test/ui/wf/wf-in-obj-type-trait.stderr index 0f4b4e417ca4..2711820d82c6 100644 --- a/src/test/ui/wf/wf-in-obj-type-trait.stderr +++ b/src/test/ui/wf/wf-in-obj-type-trait.stderr @@ -4,10 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | struct MustBeCopy { | ------------------------- required by `MustBeCopy` ... +LL | struct Bar { + | - help: consider restricting this bound: `T: std::marker::Copy` +LL | // needs T: Copy LL | x: dyn Object> | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr index 4c389b3ef3ef..35b909338132 100644 --- a/src/test/ui/wf/wf-inherent-impl-where-clause.stderr +++ b/src/test/ui/wf/wf-inherent-impl-where-clause.stderr @@ -4,12 +4,13 @@ error[E0277]: the trait bound `U: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` ... -LL | / impl Foo where T: ExtraCopy +LL | impl Foo where T: ExtraCopy + | ^ - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` + | _| + | | LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` - | - = help: consider adding a `where U: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-struct-bound.stderr b/src/test/ui/wf/wf-struct-bound.stderr index 2028a0baa17f..215597734925 100644 --- a/src/test/ui/wf/wf-struct-bound.stderr +++ b/src/test/ui/wf/wf-struct-bound.stderr @@ -6,12 +6,11 @@ LL | trait ExtraCopy { } LL | LL | / struct SomeStruct LL | | where T: ExtraCopy + | | - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` LL | | { LL | | data: (T,U) LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` - | - = help: consider adding a `where U: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-struct-field.stderr b/src/test/ui/wf/wf-struct-field.stderr index d2bff253678e..6ac4f1e2da8d 100644 --- a/src/test/ui/wf/wf-struct-field.stderr +++ b/src/test/ui/wf/wf-struct-field.stderr @@ -4,10 +4,10 @@ error[E0277]: the trait bound `A: std::marker::Copy` is not satisfied LL | struct IsCopy { | --------------------- required by `IsCopy` ... +LL | struct SomeStruct { + | - help: consider restricting this bound: `A: std::marker::Copy` LL | data: IsCopy | ^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `A` - | - = help: consider adding a `where A: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-associated-type-bound.stderr b/src/test/ui/wf/wf-trait-associated-type-bound.stderr index d5b2b5762a43..af0433fd22f6 100644 --- a/src/test/ui/wf/wf-trait-associated-type-bound.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-bound.stderr @@ -4,12 +4,13 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` LL | -LL | / trait SomeTrait { +LL | trait SomeTrait { + | ^ - help: consider restricting this bound: `T: std::marker::Copy` + | _| + | | LL | | type Type1: ExtraCopy; LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-bound.stderr b/src/test/ui/wf/wf-trait-bound.stderr index 85f12b2de548..13e2f8f59014 100644 --- a/src/test/ui/wf/wf-trait-bound.stderr +++ b/src/test/ui/wf/wf-trait-bound.stderr @@ -6,11 +6,10 @@ LL | trait ExtraCopy { } LL | LL | / trait SomeTrait LL | | where T: ExtraCopy + | | - help: consider further restricting type parameter `U`: `, U: std::marker::Copy` LL | | { LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `U` - | - = help: consider adding a `where U: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-superbound.stderr b/src/test/ui/wf/wf-trait-superbound.stderr index 377ca640536c..a61b8dd3a384 100644 --- a/src/test/ui/wf/wf-trait-superbound.stderr +++ b/src/test/ui/wf/wf-trait-superbound.stderr @@ -4,11 +4,12 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | trait ExtraCopy { } | ----------------------- required by `ExtraCopy` LL | -LL | / trait SomeTrait: ExtraCopy { +LL | trait SomeTrait: ExtraCopy { + | ^ - help: consider restricting this bound: `T: std::marker::Copy` + | _| + | | LL | | } | |_^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error From dbd75c8c40a06ac682251b67a548a8252c5d4b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Oct 2019 15:22:27 -0700 Subject: [PATCH 420/545] Handle more cases involving `impl` and `trait` --- src/librustc/traits/error_reporting.rs | 145 ++++++++++-------- .../associated-types-no-suitable-bound.stderr | 7 +- .../ui/consts/too_generic_eval_ice.stderr | 8 +- src/test/ui/impl-trait/issue-55872-1.stderr | 7 +- ...traints-are-local-for-inherent-impl.stderr | 5 +- ...onstraints-are-local-for-trait-impl.stderr | 5 +- 6 files changed, 100 insertions(+), 77 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index a717fb7f7c0f..c8baafef50a7 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -969,90 +969,103 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_ref: &ty::PolyTraitRef<'_>, body_id: hir::HirId, ) { - let node = self.tcx.hir() - .find(self.tcx.hir().get_parent_item(body_id)) - .or_else(|| self.tcx.hir().find(body_id)); debug!( - "suggest_restricting_param_bound node={:?} - trait_ref={:?} ty={:?} ({:?})", - node, + "suggest_restricting_param_bound trait_ref={:?} ty={:?} ({:?})", trait_ref, trait_ref.self_ty(), trait_ref.self_ty().kind, ); - if let ty::Param(param_ty) = &trait_ref.self_ty().kind { - let restrict_msg = "consider further restricting this bound"; - let param_name = param_ty.name.as_str(); + let param_ty = if let ty::Param(param_ty) = &trait_ref.self_ty().kind { + param_ty + } else { + err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate())); + return; + }; - if let Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Struct(_, generics), span, .. - })) | - Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Enum(_, generics), span, .. - })) | - Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Union(_, generics), span, .. - })) | - Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, generics, ..), span, .. - })) | - Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, .. - })) | - Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(_, _, generics, _), span, .. - })) = &node { - for param in &generics.params { - if param_name == param.name.ident().as_str() { - if param_name.starts_with("impl ") { - err.span_suggestion( - param.span, - restrict_msg, - // `impl CurrentTrait + MissingTrait` - format!("{} + {}", param.name.ident(), trait_ref), - Applicability::MachineApplicable, - ); - } else { - if generics.where_clause.predicates.is_empty() && - param.bounds.is_empty() - { + let mut hir_id = body_id; + while let Some(node) = self.tcx.hir().find(hir_id) { + debug!("suggest_restricting_param_bound node={:?}", node); + match node { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) | + hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) | + hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) | + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Trait(_, _, generics, ..), span, .. + }) | + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(_, _, _, generics, ..), span, .. + }) | + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(_, _, generics, _), span, .. + }) | + hir::Node::Item(hir::Item { + kind: hir::ItemKind::TyAlias(_, generics), span, .. + }) | + hir::Node::Item(hir::Item { + kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), span, .. + }) | + hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) | + hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) => { + let restrict_msg = "consider further restricting this bound"; + let param_name = param_ty.name.as_str(); + for param in &generics.params { + if param_name == param.name.ident().as_str() { + if param_name.starts_with("impl ") { err.span_suggestion( param.span, - "consider restricting this bound", - format!("{}", trait_ref.to_predicate()), - Applicability::MachineApplicable, - ); - } else if !generics.where_clause.predicates.is_empty() { - err.span_suggestion( - generics.where_clause.span().unwrap().shrink_to_hi(), - &format!( - "consider further restricting type parameter `{}`", - param_ty, - ), - format!(", {}", trait_ref.to_predicate()), + restrict_msg, + // `impl CurrentTrait + MissingTrait` + format!("{} + {}", param.name.ident(), trait_ref), Applicability::MachineApplicable, ); } else { - let sp = param.span.with_hi(span.hi()); - let span = self.tcx.sess.source_map().span_through_char(sp, ':'); - if sp != param.span && sp != span { - // Only suggest if we have high certainty that the span covers - // the colon in `foo`. - err.span_suggestion(span, restrict_msg, format!( - "{} + ", - trait_ref.to_predicate(), - ), Applicability::MachineApplicable); + if generics.where_clause.predicates.is_empty() && + param.bounds.is_empty() + { + err.span_suggestion( + param.span, + "consider restricting this bound", + format!("{}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } else if !generics.where_clause.predicates.is_empty() { + err.span_suggestion( + generics.where_clause.span().unwrap().shrink_to_hi(), + &format!( + "consider further restricting type parameter `{}`", + param_ty, + ), + format!(", {}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); } else { - err.span_label(param.span, &format!( - "consider adding a `where {}` bound", - trait_ref.to_predicate(), - )); + let sp = param.span.with_hi(span.hi()); + let span = self.tcx.sess.source_map() + .span_through_char(sp, ':'); + if sp != param.span && sp != span { + // Only suggest if we have high certainty that the span + // covers the colon in `foo`. + err.span_suggestion(span, restrict_msg, format!( + "{} + ", + trait_ref.to_predicate(), + ), Applicability::MachineApplicable); + } else { + err.span_label(param.span, &format!( + "consider adding a `where {}` bound", + trait_ref.to_predicate(), + )); + } } } + return; } - return; } } + hir::Node::Crate => return, + _ => {} } + + hir_id = self.tcx.hir().get_parent_item(hir_id); } // FIXME: Add special check for `?Sized` so we don't suggest `T: Sized + ?Sized`. diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr index ada9cacbee52..78198322913c 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr @@ -2,9 +2,10 @@ error[E0277]: the trait bound `T: Get` is not satisfied --> $DIR/associated-types-no-suitable-bound.rs:11:5 | LL | fn uhoh(foo: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T` - | - = help: consider adding a `where T: Get` bound + | ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | help: consider restricting this bound: `T: Get` + | the trait `Get` is not implemented for `T` error: aborting due to previous error diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index 0733a51233e3..2fb9977f4d70 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -16,26 +16,30 @@ error[E0277]: the size for values of type `A` cannot be known at compilation tim | LL | pub struct Foo(A, B); | --------------------------- required by `Foo` +LL | +LL | impl Foo { + | - help: consider restricting this bound: `A: std::marker::Sized` ... LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `A` = note: to learn more, visit - = help: consider adding a `where A: std::marker::Sized` bound error[E0277]: the size for values of type `B` cannot be known at compilation time --> $DIR/too_generic_eval_ice.rs:7:13 | LL | pub struct Foo(A, B); | --------------------------- required by `Foo` +LL | +LL | impl Foo { + | - help: consider restricting this bound: `B: std::marker::Sized` ... LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `B` = note: to learn more, visit - = help: consider adding a `where B: std::marker::Sized` bound error: aborting due to 3 previous errors diff --git a/src/test/ui/impl-trait/issue-55872-1.stderr b/src/test/ui/impl-trait/issue-55872-1.stderr index d5756c015596..0d8ee61b5ba1 100644 --- a/src/test/ui/impl-trait/issue-55872-1.stderr +++ b/src/test/ui/impl-trait/issue-55872-1.stderr @@ -1,10 +1,11 @@ error[E0277]: the trait bound `S: std::marker::Copy` is not satisfied in `(S, T)` --> $DIR/issue-55872-1.rs:12:5 | +LL | impl Bar for S { + | -- help: consider further restricting this bound: `S: std::marker::Copy +` LL | type E = impl Copy; | ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `S` | - = help: consider adding a `where S: std::marker::Copy` bound = note: required because it appears within the type `(S, T)` = note: the return type of a function must have a statically known size @@ -13,8 +14,10 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied in `(S, T) | LL | type E = impl Copy; | ^^^^^^^^^^^^^^^^^^^ within `(S, T)`, the trait `std::marker::Copy` is not implemented for `T` +... +LL | fn foo() -> Self::E { + | -- help: consider further restricting this bound: `T: std::marker::Copy +` | - = help: consider adding a `where T: std::marker::Copy` bound = note: required because it appears within the type `(S, T)` = note: the return type of a function must have a statically known size diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr index 727c9b8e0672..995b54460038 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-inherent-impl.stderr @@ -4,10 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | fn require_copy(x: T) {} | ------------ ---- required by this bound in `require_copy` ... +LL | impl Foo { + | - help: consider restricting this bound: `T: std::marker::Copy` +... LL | require_copy(self.x); | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr index 1c1937c3074d..fe575f3a28a9 100644 --- a/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr +++ b/src/test/ui/where-clauses/where-clause-constraints-are-local-for-trait-impl.stderr @@ -4,10 +4,11 @@ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied LL | fn require_copy(x: T) {} | ------------ ---- required by this bound in `require_copy` ... +LL | impl Foo for Bar { + | - help: consider restricting this bound: `T: std::marker::Copy` +... LL | require_copy(self.x); | ^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound error: aborting due to previous error From 99ab45b91de9fc6c07903dbe3075757f0e5e9071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Oct 2019 16:03:38 -0700 Subject: [PATCH 421/545] Handle `Self` restriction needed --- src/librustc/traits/error_reporting.rs | 28 +++++++++++++++++++ .../associated-types-for-unimpl-trait.stderr | 7 +++-- ...ated-types-no-suitable-supertrait-2.stderr | 7 +++-- ...ciated-types-no-suitable-supertrait.stderr | 7 +++-- ...ted-trait-in-method-without-default.stderr | 7 +++-- src/test/ui/issues/issue-20005.stderr | 2 +- src/test/ui/issues/issue-27078.stderr | 5 ++-- .../type-params-in-different-spaces-2.stderr | 8 +++--- src/test/ui/wf/wf-trait-default-fn-arg.stderr | 7 +++-- src/test/ui/wf/wf-trait-default-fn-ret.stderr | 7 +++-- .../wf-trait-default-fn-where-clause.stderr | 7 +++-- src/test/ui/wf/wf-trait-fn-arg.stderr | 7 +++-- src/test/ui/wf/wf-trait-fn-ret.stderr | 7 +++-- .../ui/wf/wf-trait-fn-where-clause.stderr | 7 +++-- 14 files changed, 76 insertions(+), 37 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c8baafef50a7..6e111089d06d 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -986,6 +986,34 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { while let Some(node) = self.tcx.hir().find(hir_id) { debug!("suggest_restricting_param_bound node={:?}", node); match node { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(decl, _, generics, _), .. + }) | + hir::Node::TraitItem(hir::TraitItem { + generics, + kind: hir::TraitItemKind::Method(hir::MethodSig { decl, .. }, _), .. + }) | + hir::Node::ImplItem(hir::ImplItem { + generics, + kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), .. + }) if param_ty.name.as_str() == "Self" => { + if !generics.where_clause.predicates.is_empty() { + err.span_suggestion( + generics.where_clause.span().unwrap().shrink_to_hi(), + "consider further restricting `Self`", + format!(", {}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } else { + err.span_suggestion( + decl.output.span().shrink_to_hi(), + "consider further restricting `Self`", + format!(" where {}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } + return; + } hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) | diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index 9f033687a007..79525e6362f1 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-for-unimpl-trait.rs:7:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` - | - = help: consider adding a `where Self: Get` bound + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | | + | | help: consider further restricting `Self`: `where Self: Get` + | the trait `Get` is not implemented for `Self` error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index 56cd6d09cadd..43950defc7cb 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` - | - = help: consider adding a `where Self: Get` bound + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | | + | | help: consider further restricting `Self`: `where Self: Get` + | the trait `Get` is not implemented for `Self` error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index 71175d36f645..82e366dbea4b 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` - | - = help: consider adding a `where Self: Get` bound + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | | + | | help: consider further restricting `Self`: `where Self: Get` + | the trait `Get` is not implemented for `Self` error[E0277]: the trait bound `(T, U): Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait.rs:22:5 diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index a260e3791825..54daeca42520 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -2,9 +2,10 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:9:5 | LL | fn okay(&self, foo: U, bar: ::Value); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` - | - = help: consider adding a `where Self: Get` bound + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | | + | | help: consider further restricting `Self`: `where Self: Get` + | the trait `Get` is not implemented for `Self` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr index 2754d6bdd830..31376f2d1be0 100644 --- a/src/test/ui/issues/issue-20005.stderr +++ b/src/test/ui/issues/issue-20005.stderr @@ -7,13 +7,13 @@ LL | trait From { LL | / fn to( LL | | self LL | | ) -> >::Result where Dst: From { + | | - help: consider further restricting `Self`: `, Self: std::marker::Sized` LL | | From::from(self) LL | | } | |_____^ 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 error: aborting due to previous error diff --git a/src/test/ui/issues/issue-27078.stderr b/src/test/ui/issues/issue-27078.stderr index 76cc3e7b0a36..fbc72d063f37 100644 --- a/src/test/ui/issues/issue-27078.stderr +++ b/src/test/ui/issues/issue-27078.stderr @@ -2,11 +2,12 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation --> $DIR/issue-27078.rs:5:12 | LL | fn foo(self) -> &'static i32 { - | ^^^^ doesn't have a size known at compile-time + | ^^^^ - help: consider further restricting `Self`: `where Self: std::marker::Sized` + | | + | 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: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr index 7d4bbc813c09..7ce249a60b85 100644 --- a/src/test/ui/type/type-params-in-different-spaces-2.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr @@ -4,10 +4,10 @@ error[E0277]: the trait bound `Self: Tr` is not satisfied LL | fn op(_: T) -> Self; | -------------------- required by `Tr::op` ... +LL | fn test(u: U) -> Self { + | - help: consider further restricting `Self`: `where Self: Tr` LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` - | - = help: consider adding a `where Self: Tr` bound error[E0277]: the trait bound `Self: Tr` is not satisfied --> $DIR/type-params-in-different-spaces-2.rs:16:9 @@ -15,10 +15,10 @@ error[E0277]: the trait bound `Self: Tr` is not satisfied LL | fn op(_: T) -> Self; | -------------------- required by `Tr::op` ... +LL | fn test(u: U) -> Self { + | - help: consider further restricting `Self`: `where Self: Tr` LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` - | - = help: consider adding a `where Self: Tr` bound error: aborting due to 2 previous errors diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr index 4d0e1f2f0f4c..3efcdf72eee3 100644 --- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr @@ -4,14 +4,15 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... -LL | / fn bar(&self, x: &Bar) { +LL | fn bar(&self, x: &Bar) { + | ^ - help: consider further restricting `Self`: `where Self: std::cmp::Eq` + | _____| + | | LL | | LL | | // LL | | // Here, Eq ought to be implemented. LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` - | - = help: consider adding a `where Self: std::cmp::Eq` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-ret.stderr b/src/test/ui/wf/wf-trait-default-fn-ret.stderr index e82b76b61c4a..e32630a5a4a4 100644 --- a/src/test/ui/wf/wf-trait-default-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-ret.stderr @@ -4,15 +4,16 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... -LL | / fn bar(&self) -> Bar { +LL | fn bar(&self) -> Bar { + | ^ - help: consider further restricting `Self`: `where Self: std::cmp::Eq` + | _____| + | | LL | | LL | | // LL | | // Here, Eq ought to be implemented. LL | | loop { } LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` - | - = help: consider adding a `where Self: std::cmp::Eq` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr index 6504f6698d9b..a443ff1bb639 100644 --- a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr @@ -4,14 +4,15 @@ error[E0277]: the trait bound `Self: std::cmp::Eq` is not satisfied LL | trait Bar { } | ---------------------- required by `Bar` ... -LL | / fn bar(&self) where A: Bar { +LL | fn bar(&self) where A: Bar { + | ^ - help: consider further restricting `Self`: `, Self: std::cmp::Eq` + | _____| + | | LL | | LL | | // LL | | // Here, Eq ought to be implemented. LL | | } | |_____^ the trait `std::cmp::Eq` is not implemented for `Self` - | - = help: consider adding a `where Self: std::cmp::Eq` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr index 0887d4b2fcda..42a28ee67637 100644 --- a/src/test/ui/wf/wf-trait-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-fn-arg.stderr @@ -5,9 +5,10 @@ LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... LL | fn bar(&self, x: &Bar); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` - | - = help: consider adding a `where Self: std::cmp::Eq` bound + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | | + | | help: consider further restricting `Self`: `where Self: std::cmp::Eq` + | the trait `std::cmp::Eq` is not implemented for `Self` error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-ret.stderr b/src/test/ui/wf/wf-trait-fn-ret.stderr index 5555081498c6..7ec4dbe0056b 100644 --- a/src/test/ui/wf/wf-trait-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-fn-ret.stderr @@ -5,9 +5,10 @@ LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... LL | fn bar(&self) -> &Bar; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` - | - = help: consider adding a `where Self: std::cmp::Eq` bound + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | | + | | help: consider further restricting `Self`: `where Self: std::cmp::Eq` + | the trait `std::cmp::Eq` is not implemented for `Self` error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-fn-where-clause.stderr index 5e8fd8982390..256edb5b2ca1 100644 --- a/src/test/ui/wf/wf-trait-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-trait-fn-where-clause.stderr @@ -5,9 +5,10 @@ LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... LL | fn bar(&self) where Self: Sized, Bar: Copy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` - | - = help: consider adding a `where Self: std::cmp::Eq` bound + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | | + | | help: consider further restricting `Self`: `, Self: std::cmp::Eq` + | the trait `std::cmp::Eq` is not implemented for `Self` error: aborting due to previous error From ca1885de4178abe554f89a1d4556c2a4e742b03a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Oct 2019 16:13:05 -0700 Subject: [PATCH 422/545] Update some tests involving `Self` --- .../associated-types-for-unimpl-trait.fixed | 15 ++++++++++ .../associated-types-for-unimpl-trait.rs | 3 ++ .../associated-types-for-unimpl-trait.stderr | 2 +- ...ated-trait-in-method-without-default.fixed | 30 +++++++++++++++++++ ...related-trait-in-method-without-default.rs | 1 + ...ted-trait-in-method-without-default.stderr | 2 +- 6 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed create mode 100644 src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed b/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed new file mode 100644 index 000000000000..b27d58018c29 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed @@ -0,0 +1,15 @@ +// run-rustfix +#![allow(unused_variables)] + +trait Get { + type Value; + fn get(&self) -> ::Value; +} + +trait Other { + fn uhoh(&self, foo: U, bar: ::Value) where Self: Get{} + //~^ ERROR the trait bound `Self: Get` is not satisfied +} + +fn main() { +} diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs b/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs index 5b10d1dc2fdb..0f6cea8e69fc 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.rs @@ -1,3 +1,6 @@ +// run-rustfix +#![allow(unused_variables)] + trait Get { type Value; fn get(&self) -> ::Value; diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index 79525e6362f1..f8fc2b37e730 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-for-unimpl-trait.rs:7:5 + --> $DIR/associated-types-for-unimpl-trait.rs:10:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed new file mode 100644 index 000000000000..9bc308465ebd --- /dev/null +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed @@ -0,0 +1,30 @@ +// run-rustfix +// Check that we get an error when you use `::Value` in +// the trait definition even if there is no default method. + +trait Get { + type Value; +} + +trait Other { + fn okay(&self, foo: U, bar: ::Value) where Self: Get; + //~^ ERROR E0277 +} + +impl Get for () { + type Value = f32; +} + +impl Get for f64 { + type Value = u32; +} + +impl Other for () { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +impl Other for f64 { + fn okay(&self, _foo: U, _bar: ::Value) { } +} + +fn main() { } diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs index fc38b26f50b6..549fc8fc618e 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.rs @@ -1,3 +1,4 @@ +// run-rustfix // Check that we get an error when you use `::Value` in // the trait definition even if there is no default method. diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index 54daeca42520..cb01488fa34d 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: Get` is not satisfied - --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:9:5 + --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5 | LL | fn okay(&self, foo: U, bar: ::Value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- From b81df6b739c14a2e5d5e1cad2c7ca7952ba947c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Oct 2019 16:13:20 -0700 Subject: [PATCH 423/545] Consider trait aliases --- src/librustc/traits/error_reporting.rs | 3 +++ src/test/ui/traits/trait-alias/trait-alias-wf.stderr | 7 ++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 6e111089d06d..77d4e10d4f4e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1029,6 +1029,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(_, generics), span, .. }) | + hir::Node::Item(hir::Item { + kind: hir::ItemKind::TraitAlias(generics, _), span, .. + }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), span, .. }) | diff --git a/src/test/ui/traits/trait-alias/trait-alias-wf.stderr b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr index ca6d05847166..4355a517bd72 100644 --- a/src/test/ui/traits/trait-alias/trait-alias-wf.stderr +++ b/src/test/ui/traits/trait-alias/trait-alias-wf.stderr @@ -4,9 +4,10 @@ error[E0277]: the trait bound `T: Foo` is not satisfied LL | trait A {} | --------------- required by `A` LL | trait B = A; - | ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `T` - | - = help: consider adding a `where T: Foo` bound + | ^^^^^^^^-^^^^^^^^^ + | | | + | | help: consider restricting this bound: `T: Foo` + | the trait `Foo` is not implemented for `T` error: aborting due to previous error From daa8491648d742085bf071169624d99d542a044f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 8 Oct 2019 16:19:39 -0700 Subject: [PATCH 424/545] Update NLL tests --- .../ui/kindck/kindck-impl-type-params.nll.stderr | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr index 25d0e74187f7..82efa8399055 100644 --- a/src/test/ui/kindck/kindck-impl-type-params.nll.stderr +++ b/src/test/ui/kindck/kindck-impl-type-params.nll.stderr @@ -1,42 +1,50 @@ error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:18:13 | +LL | fn f(val: T) { + | - help: consider restricting this bound: `T: std::marker::Send` +LL | let t: S = S(marker::PhantomData); LL | let a = &t as &dyn Gettable; | ^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` - = help: consider adding a `where T: std::marker::Send` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:18:13 | +LL | fn f(val: T) { + | - help: consider restricting this bound: `T: std::marker::Copy` +LL | let t: S = S(marker::PhantomData); LL | let a = &t as &dyn Gettable; | ^^ the trait `std::marker::Copy` is not implemented for `T` | - = help: consider adding a `where T: std::marker::Copy` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: `T` cannot be sent between threads safely --> $DIR/kindck-impl-type-params.rs:25:31 | +LL | fn g(val: T) { + | - help: consider restricting this bound: `T: std::marker::Send` +LL | let t: S = S(marker::PhantomData); LL | let a: &dyn Gettable = &t; | ^^ `T` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `T` - = help: consider adding a `where T: std::marker::Send` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/kindck-impl-type-params.rs:25:31 | +LL | fn g(val: T) { + | - help: consider restricting this bound: `T: std::marker::Copy` +LL | let t: S = S(marker::PhantomData); LL | let a: &dyn Gettable = &t; | ^^ the trait `std::marker::Copy` is not implemented for `T` | - = help: consider adding a `where T: std::marker::Copy` bound = note: required because of the requirements on the impl of `Gettable` for `S` = note: required for the cast to the object type `dyn Gettable` From 5cc99eed04005108797fbba82eaf8ef7918051db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 9 Oct 2019 15:07:22 -0700 Subject: [PATCH 425/545] Handle missing projection restriction --- src/librustc/traits/error_reporting.rs | 49 +++++++++++++++---- .../bad-bounds-on-assoc-in-trait.stderr | 18 ++++--- .../associated-types-bound-failure.fixed | 29 +++++++++++ .../associated-types-bound-failure.rs | 2 + .../associated-types-bound-failure.stderr | 7 +-- .../associated-types-unsized.fixed | 14 ++++++ .../associated-types-unsized.rs | 3 ++ .../associated-types-unsized.stderr | 5 +- src/test/ui/issues/issue-22872.stderr | 3 +- src/test/ui/issues/issue-42312.stderr | 5 +- ...typeck-default-trait-impl-assoc-type.fixed | 17 +++++++ .../typeck-default-trait-impl-assoc-type.rs | 2 + ...ypeck-default-trait-impl-assoc-type.stderr | 5 +- 13 files changed, 134 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/associated-types/associated-types-bound-failure.fixed create mode 100644 src/test/ui/associated-types/associated-types-unsized.fixed create mode 100644 src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 77d4e10d4f4e..2ac691b47aca 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -975,11 +975,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_ref.self_ty(), trait_ref.self_ty().kind, ); - let param_ty = if let ty::Param(param_ty) = &trait_ref.self_ty().kind { - param_ty - } else { - err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate())); - return; + let (param_ty, projection) = match &trait_ref.self_ty().kind { + ty::Param(param_ty) => (Some(param_ty), None), + ty::Projection(projection) => (None, Some(projection)), + _ => { + err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate())); + return; + } }; let mut hir_id = body_id; @@ -996,7 +998,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { hir::Node::ImplItem(hir::ImplItem { generics, kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), .. - }) if param_ty.name.as_str() == "Self" => { + }) if param_ty.map(|p| p.name.as_str() == "Self").unwrap_or(false) => { if !generics.where_clause.predicates.is_empty() { err.span_suggestion( generics.where_clause.span().unwrap().shrink_to_hi(), @@ -1014,6 +1016,34 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } return; } + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(decl, _, generics, _), .. + }) | + hir::Node::TraitItem(hir::TraitItem { + generics, + kind: hir::TraitItemKind::Method(hir::MethodSig { decl, .. }, _), .. + }) | + hir::Node::ImplItem(hir::ImplItem { + generics, + kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), .. + }) if projection.is_some() => { + if !generics.where_clause.predicates.is_empty() { + err.span_suggestion( + generics.where_clause.span().unwrap().shrink_to_hi(), + "consider further restricting the associated type", + format!(", {}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } else { + err.span_suggestion( + decl.output.span().shrink_to_hi(), + "consider further restricting the associated type", + format!(" where {}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } + return; + } hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) | @@ -1036,9 +1066,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), span, .. }) | hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) | - hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) => { + hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) + if param_ty.is_some() => { let restrict_msg = "consider further restricting this bound"; - let param_name = param_ty.name.as_str(); + let param_name = param_ty.unwrap().name.as_str(); for param in &generics.params { if param_name == param.name.ident().as_str() { if param_name.starts_with("impl ") { @@ -1064,7 +1095,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { generics.where_clause.span().unwrap().shrink_to_hi(), &format!( "consider further restricting type parameter `{}`", - param_ty, + param_name, ), format!(", {}", trait_ref.to_predicate()), Applicability::MachineApplicable, diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index 06e8230aa158..1795fb5acebe 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -9,7 +9,10 @@ LL | impl Case1 for S1 { error[E0277]: `<::C as std::iter::Iterator>::Item` is not an iterator --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 | -LL | / fn assume_case1() { +LL | fn assume_case1() { + | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::iter::Iterator` + | _| + | | LL | | LL | | LL | | @@ -19,7 +22,6 @@ LL | | } | |_^ `<::C as std::iter::Iterator>::Item` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `<::C as std::iter::Iterator>::Item` - = help: consider adding a `where <::C as std::iter::Iterator>::Item: std::iter::Iterator` bound error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 @@ -27,7 +29,10 @@ error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be sent be LL | trait Case1 { | ----------- required by `Case1` ... -LL | / fn assume_case1() { +LL | fn assume_case1() { + | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Send` + | _| + | | LL | | LL | | LL | | @@ -37,7 +42,6 @@ LL | | } | |_^ `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `<::C as std::iter::Iterator>::Item` - = help: consider adding a `where <::C as std::iter::Iterator>::Item: std::marker::Send` bound error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 @@ -45,7 +49,10 @@ error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be shared LL | trait Case1 { | ----------- required by `Case1` ... -LL | / fn assume_case1() { +LL | fn assume_case1() { + | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Sync` + | _| + | | LL | | LL | | LL | | @@ -55,7 +62,6 @@ LL | | } | |_^ `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `<::C as std::iter::Iterator>::Item` - = help: consider adding a `where <::C as std::iter::Iterator>::Item: std::marker::Sync` bound error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `std::fmt::Debug` --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 diff --git a/src/test/ui/associated-types/associated-types-bound-failure.fixed b/src/test/ui/associated-types/associated-types-bound-failure.fixed new file mode 100644 index 000000000000..68ee38d16b3f --- /dev/null +++ b/src/test/ui/associated-types/associated-types-bound-failure.fixed @@ -0,0 +1,29 @@ +// run-rustfix +// Test equality constraints on associated types in a where clause. +#![allow(dead_code)] + +pub trait ToInt { + fn to_int(&self) -> isize; +} + +pub trait GetToInt +{ + type R; + + fn get(&self) -> ::R; +} + +fn foo(g: G) -> isize + where G : GetToInt, ::R: ToInt +{ + ToInt::to_int(&g.get()) //~ ERROR E0277 +} + +fn bar(g: G) -> isize + where G::R : ToInt +{ + ToInt::to_int(&g.get()) // OK +} + +pub fn main() { +} diff --git a/src/test/ui/associated-types/associated-types-bound-failure.rs b/src/test/ui/associated-types/associated-types-bound-failure.rs index 883ac363b44e..31e073cc7a8b 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.rs +++ b/src/test/ui/associated-types/associated-types-bound-failure.rs @@ -1,4 +1,6 @@ +// run-rustfix // Test equality constraints on associated types in a where clause. +#![allow(dead_code)] pub trait ToInt { fn to_int(&self) -> isize; diff --git a/src/test/ui/associated-types/associated-types-bound-failure.stderr b/src/test/ui/associated-types/associated-types-bound-failure.stderr index 85acf134d51d..c420c86a2758 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.stderr +++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr @@ -1,13 +1,14 @@ error[E0277]: the trait bound `::R: ToInt` is not satisfied - --> $DIR/associated-types-bound-failure.rs:17:19 + --> $DIR/associated-types-bound-failure.rs:19:19 | LL | fn to_int(&self) -> isize; | -------------------------- required by `ToInt::to_int` ... +LL | where G : GetToInt + | - help: consider further restricting the associated type: `, ::R: ToInt` +LL | { LL | ToInt::to_int(&g.get()) | ^^^^^^^^ the trait `ToInt` is not implemented for `::R` - | - = help: consider adding a `where ::R: ToInt` bound error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-unsized.fixed b/src/test/ui/associated-types/associated-types-unsized.fixed new file mode 100644 index 000000000000..385de541e560 --- /dev/null +++ b/src/test/ui/associated-types/associated-types-unsized.fixed @@ -0,0 +1,14 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + +trait Get { + type Value: ?Sized; + fn get(&self) -> ::Value; +} + +fn foo(t: T) where ::Value: std::marker::Sized{ + let x = t.get(); //~ ERROR the size for values of type +} + +fn main() { +} diff --git a/src/test/ui/associated-types/associated-types-unsized.rs b/src/test/ui/associated-types/associated-types-unsized.rs index a9bc24e44d16..bdba4c7ff16a 100644 --- a/src/test/ui/associated-types/associated-types-unsized.rs +++ b/src/test/ui/associated-types/associated-types-unsized.rs @@ -1,3 +1,6 @@ +// run-rustfix +#![allow(dead_code, unused_variables)] + trait Get { type Value: ?Sized; fn get(&self) -> ::Value; diff --git a/src/test/ui/associated-types/associated-types-unsized.stderr b/src/test/ui/associated-types/associated-types-unsized.stderr index b5db9743932e..18595721bcee 100644 --- a/src/test/ui/associated-types/associated-types-unsized.stderr +++ b/src/test/ui/associated-types/associated-types-unsized.stderr @@ -1,12 +1,13 @@ error[E0277]: the size for values of type `::Value` cannot be known at compilation time - --> $DIR/associated-types-unsized.rs:7:9 + --> $DIR/associated-types-unsized.rs:10:9 | +LL | fn foo(t: T) { + | - help: consider further restricting the associated type: `where ::Value: std::marker::Sized` LL | let x = t.get(); | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `::Value` = note: to learn more, visit - = help: consider adding a `where ::Value: std::marker::Sized` bound = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr index fc5de23752b3..283a5e04a8b6 100644 --- a/src/test/ui/issues/issue-22872.stderr +++ b/src/test/ui/issues/issue-22872.stderr @@ -1,11 +1,12 @@ error[E0277]: `

>::Item` is not an iterator --> $DIR/issue-22872.rs:20:40 | +LL | fn push_process

(process: P) where P: Process<'static> { + | - help: consider further restricting the associated type: `,

>::Item: std::iter::Iterator` LL | let _: Box Wrap<'b>> = Box::new(Wrapper(process)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `

>::Item` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `

>::Item` - = help: consider adding a `where

>::Item: std::iter::Iterator` bound = note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper

` = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` diff --git a/src/test/ui/issues/issue-42312.stderr b/src/test/ui/issues/issue-42312.stderr index bfdc4272fb30..6688203147ea 100644 --- a/src/test/ui/issues/issue-42312.stderr +++ b/src/test/ui/issues/issue-42312.stderr @@ -2,11 +2,12 @@ error[E0277]: the size for values of type `::Target` ca --> $DIR/issue-42312.rs:4:29 | LL | fn baz(_: Self::Target) where Self: Deref {} - | ^ doesn't have a size known at compile-time + | ^ - help: consider further restricting the associated type: `, ::Target: std::marker::Sized` + | | + | doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `::Target` = note: to learn more, visit - = help: consider adding a `where ::Target: std::marker::Sized` bound = note: all function arguments must have a statically known size = help: unsized locals are gated as an unstable feature diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed new file mode 100644 index 000000000000..757d8b8a235a --- /dev/null +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed @@ -0,0 +1,17 @@ +// run-rustfix +// Test that we do not consider associated types to be sendable without +// some applicable trait bound (and we don't ICE). +#![allow(dead_code)] + +trait Trait { + type AssocType; + fn dummy(&self) { } +} +fn bar() where ::AssocType: std::marker::Send{ + is_send::(); //~ ERROR E0277 +} + +fn is_send() { +} + +fn main() { } diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs index d64835393867..bafc1657737f 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.rs @@ -1,5 +1,7 @@ +// run-rustfix // Test that we do not consider associated types to be sendable without // some applicable trait bound (and we don't ICE). +#![allow(dead_code)] trait Trait { type AssocType; diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr index b842d0ae1a24..dd6dcbe2ef57 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr @@ -1,6 +1,8 @@ error[E0277]: `::AssocType` cannot be sent between threads safely - --> $DIR/typeck-default-trait-impl-assoc-type.rs:9:5 + --> $DIR/typeck-default-trait-impl-assoc-type.rs:11:5 | +LL | fn bar() { + | - help: consider further restricting the associated type: `where ::AssocType: std::marker::Send` LL | is_send::(); | ^^^^^^^^^^^^^^^^^^^^^^^ `::AssocType` cannot be sent between threads safely ... @@ -8,7 +10,6 @@ LL | fn is_send() { | ------- ---- required by this bound in `is_send` | = help: the trait `std::marker::Send` is not implemented for `::AssocType` - = help: consider adding a `where ::AssocType: std::marker::Send` bound error: aborting due to previous error From bc744bca9063cd9145fceed4ba7ef14cab0ecdd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 9 Oct 2019 15:54:23 -0700 Subject: [PATCH 426/545] Suggest associated bound restrictions in `impl`s --- src/librustc/hir/mod.rs | 6 +++ src/librustc/traits/error_reporting.rs | 18 ++++++++ src/test/ui/issues/issue-38821.stderr | 5 ++- .../missing-assoc-type-bound-restriction.rs | 25 +++++++++++ ...issing-assoc-type-bound-restriction.stderr | 43 +++++++++++++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs create mode 100644 src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 7350f89018be..fa0f620530de 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -669,6 +669,12 @@ impl WhereClause { Some(self.span) } } + + /// The `WhereClause` under normal circumstances points at either the predicates or the empty + /// space where the `where` clause should be. Only of use for diagnostic suggestions. + pub fn span_for_predicates_or_empty_place(&self) -> Span { + self.span + } } /// A single predicate in a where-clause. diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 2ac691b47aca..91106d35a7ee 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1044,6 +1044,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } return; } + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl(_, _, _, generics, ..), .. + }) if projection.is_some() => { + err.span_suggestion( + generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(), + "consider further restricting the associated type", + format!( + "{} {}", if generics.where_clause.predicates.is_empty() { + " where" + } else { + " ," + }, + trait_ref.to_predicate(), + ), + Applicability::MachineApplicable, + ); + return; + } hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) | diff --git a/src/test/ui/issues/issue-38821.stderr b/src/test/ui/issues/issue-38821.stderr index dbd204ec299d..3e2af7c44e4a 100644 --- a/src/test/ui/issues/issue-38821.stderr +++ b/src/test/ui/issues/issue-38821.stderr @@ -2,9 +2,10 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ^^^^- help: consider further restricting the associated type: `, ::SqlType: NotNull` + | | + | the trait `NotNull` is not implemented for `::SqlType` | - = help: consider adding a `where ::SqlType: NotNull` bound = note: required because of the requirements on the impl of `IntoNullable` for `::SqlType` error: aborting due to previous error diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs new file mode 100644 index 000000000000..265ccb3125ca --- /dev/null +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.rs @@ -0,0 +1,25 @@ +// Running rustfix would cause the same suggestion to be applied multiple times, which results in +// invalid code. + +trait Parent { + type Ty; + type Assoc: Child; +} + +trait Child {} + +struct ChildWrapper(T); + +impl Child for ChildWrapper where T: Child {} + +struct ParentWrapper(T); + +impl> Parent for ParentWrapper { + //~^ ERROR the trait bound `::Assoc: Child` is not satisfied + //~| ERROR the trait bound `::Assoc: Child` is not satisfied + type Ty = A; + type Assoc = ChildWrapper; + //~^ ERROR the trait bound `::Assoc: Child` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr new file mode 100644 index 000000000000..bdea8ab97e5b --- /dev/null +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr @@ -0,0 +1,43 @@ +error[E0277]: the trait bound `::Assoc: Child` is not satisfied + --> $DIR/missing-assoc-type-bound-restriction.rs:17:1 + | +LL | trait Parent { + | ------------ required by `Parent` +... +LL | impl> Parent for ParentWrapper { + | ^ - help: consider further restricting the associated type: `where ::Assoc: Child` + | _| + | | +LL | | +LL | | +LL | | type Ty = A; +LL | | type Assoc = ChildWrapper; +LL | | +LL | | } + | |_^ the trait `Child` is not implemented for `::Assoc` + +error[E0277]: the trait bound `::Assoc: Child` is not satisfied + --> $DIR/missing-assoc-type-bound-restriction.rs:17:28 + | +LL | impl> Parent for ParentWrapper { + | ^^^^^^ - help: consider further restricting the associated type: `where ::Assoc: Child` + | | + | the trait `Child` is not implemented for `::Assoc` + | + = note: required because of the requirements on the impl of `Child` for `ChildWrapper<::Assoc>` + +error[E0277]: the trait bound `::Assoc: Child` is not satisfied + --> $DIR/missing-assoc-type-bound-restriction.rs:21:5 + | +LL | trait Parent { + | ------------ required by `Parent` +... +LL | impl> Parent for ParentWrapper { + | - help: consider further restricting the associated type: `where ::Assoc: Child` +... +LL | type Assoc = ChildWrapper; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. From ab7d8f0f5a8624d583989b76015254fff2f59cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Oct 2019 09:50:45 -0700 Subject: [PATCH 427/545] Deduplicate some code and apply review comments --- src/librustc/traits/error_reporting.rs | 195 +++++++++--------- .../bad-bounds-on-assoc-in-trait.stderr | 6 +- .../associated-types-bound-failure.fixed | 2 +- .../associated-types-for-unimpl-trait.fixed | 2 +- .../associated-types-for-unimpl-trait.stderr | 6 +- ...ated-types-no-suitable-supertrait-2.stderr | 6 +- ...ciated-types-no-suitable-supertrait.stderr | 6 +- ...ated-trait-in-method-without-default.fixed | 2 +- .../associated-types-unsized.fixed | 2 +- .../associated-types-unsized.stderr | 2 +- ...typeck-default-trait-impl-assoc-type.fixed | 2 +- ...ypeck-default-trait-impl-assoc-type.stderr | 2 +- .../wf/wf-trait-associated-type-trait.stderr | 7 +- src/test/ui/wf/wf-trait-default-fn-arg.stderr | 2 +- 14 files changed, 117 insertions(+), 125 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 91106d35a7ee..abf265be7c50 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -984,84 +984,66 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } }; + let mut suggest_restriction = |generics: &hir::Generics, msg| { + err.span_suggestion( + generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(), + &format!("consider further restricting {}", msg), + format!( + "{} {} ", + if !generics.where_clause.predicates.is_empty() { + "," + } else { + " where" + }, + trait_ref.to_predicate(), + ), + Applicability::MachineApplicable, + ); + }; + + // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we + // don't suggest `T: Sized + ?Sized`. let mut hir_id = body_id; while let Some(node) = self.tcx.hir().find(hir_id) { - debug!("suggest_restricting_param_bound node={:?}", node); match node { hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(decl, _, generics, _), .. + kind: hir::ItemKind::Fn(_, _, generics, _), .. }) | hir::Node::TraitItem(hir::TraitItem { generics, - kind: hir::TraitItemKind::Method(hir::MethodSig { decl, .. }, _), .. + kind: hir::TraitItemKind::Method(..), .. }) | hir::Node::ImplItem(hir::ImplItem { generics, - kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), .. - }) if param_ty.map(|p| p.name.as_str() == "Self").unwrap_or(false) => { - if !generics.where_clause.predicates.is_empty() { - err.span_suggestion( - generics.where_clause.span().unwrap().shrink_to_hi(), - "consider further restricting `Self`", - format!(", {}", trait_ref.to_predicate()), - Applicability::MachineApplicable, - ); - } else { - err.span_suggestion( - decl.output.span().shrink_to_hi(), - "consider further restricting `Self`", - format!(" where {}", trait_ref.to_predicate()), - Applicability::MachineApplicable, - ); - } + kind: hir::ImplItemKind::Method(..), .. + }) if param_ty.map_or(false, |p| p.name.as_str() == "Self") => { + // Restricting `Self` for a single method. + suggest_restriction(&generics, "`Self`"); return; } + hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(decl, _, generics, _), .. + kind: hir::ItemKind::Fn(_, _, generics, _), .. }) | hir::Node::TraitItem(hir::TraitItem { generics, - kind: hir::TraitItemKind::Method(hir::MethodSig { decl, .. }, _), .. + kind: hir::TraitItemKind::Method(..), .. }) | hir::Node::ImplItem(hir::ImplItem { generics, - kind: hir::ImplItemKind::Method(hir::MethodSig { decl, .. }, _), .. - }) if projection.is_some() => { - if !generics.where_clause.predicates.is_empty() { - err.span_suggestion( - generics.where_clause.span().unwrap().shrink_to_hi(), - "consider further restricting the associated type", - format!(", {}", trait_ref.to_predicate()), - Applicability::MachineApplicable, - ); - } else { - err.span_suggestion( - decl.output.span().shrink_to_hi(), - "consider further restricting the associated type", - format!(" where {}", trait_ref.to_predicate()), - Applicability::MachineApplicable, - ); - } - return; - } + kind: hir::ImplItemKind::Method(..), .. + }) | + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Trait(_, _, generics, _, _), .. + }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(_, _, _, generics, ..), .. }) if projection.is_some() => { - err.span_suggestion( - generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(), - "consider further restricting the associated type", - format!( - "{} {}", if generics.where_clause.predicates.is_empty() { - " where" - } else { - " ," - }, - trait_ref.to_predicate(), - ), - Applicability::MachineApplicable, - ); + // Missing associated type bound. + suggest_restriction(&generics, "the associated type"); return; } + hir::Node::Item(hir::Item { kind: hir::ItemKind::Struct(_, generics), span, .. }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(_, generics), span, .. }) | hir::Node::Item(hir::Item { kind: hir::ItemKind::Union(_, generics), span, .. }) | @@ -1086,73 +1068,82 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) | hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) if param_ty.is_some() => { + // Missing generic type parameter bound. let restrict_msg = "consider further restricting this bound"; let param_name = param_ty.unwrap().name.as_str(); - for param in &generics.params { - if param_name == param.name.ident().as_str() { - if param_name.starts_with("impl ") { + for param in generics.params.iter().filter(|p| { + param_name == p.name.ident().as_str() + }) { + if param_name.starts_with("impl ") { + // `impl Trait` in argument: + // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}` + err.span_suggestion( + param.span, + restrict_msg, + // `impl CurrentTrait + MissingTrait` + format!("{} + {}", param.name.ident(), trait_ref), + Applicability::MachineApplicable, + ); + } else { + if generics.where_clause.predicates.is_empty() && + param.bounds.is_empty() + { + // If there are no bounds whatsoever, suggest adding a constraint + // to the type parameter: + // `fn foo(t: T) {}` → `fn foo(t: T) {}` err.span_suggestion( param.span, - restrict_msg, - // `impl CurrentTrait + MissingTrait` - format!("{} + {}", param.name.ident(), trait_ref), + "consider restricting this bound", + format!("{}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } else if !generics.where_clause.predicates.is_empty() { + // There is a `where` clause, so suggest expanding it: + // `fn foo(t: T) where T: Debug {}` → + // `fn foo(t: T, x: X) {}` → `fn foo(t: T) {}` + // `fn foo(t: T) {}` → `fn foo(t: T) {}` + let sp = param.span.with_hi(span.hi()); + let span = self.tcx.sess.source_map() + .span_through_char(sp, ':'); + if sp != param.span && sp != span { + // Only suggest if we have high certainty that the span + // covers the colon in `foo`. + err.span_suggestion(span, restrict_msg, format!( + "{} + ", + trait_ref.to_predicate(), + ), Applicability::MachineApplicable); } else { - let sp = param.span.with_hi(span.hi()); - let span = self.tcx.sess.source_map() - .span_through_char(sp, ':'); - if sp != param.span && sp != span { - // Only suggest if we have high certainty that the span - // covers the colon in `foo`. - err.span_suggestion(span, restrict_msg, format!( - "{} + ", - trait_ref.to_predicate(), - ), Applicability::MachineApplicable); - } else { - err.span_label(param.span, &format!( - "consider adding a `where {}` bound", - trait_ref.to_predicate(), - )); - } + err.span_label(param.span, &format!( + "consider adding a `where {}` bound", + trait_ref.to_predicate(), + )); } } - return; } + return; } } + hir::Node::Crate => return, + _ => {} } hir_id = self.tcx.hir().get_parent_item(hir_id); } - // FIXME: Add special check for `?Sized` so we don't suggest `T: Sized + ?Sized`. - - // Fallback in case we didn't find the type argument. Can happen on associated types - // bounds and when `Self` needs to be restricted, like in the ui test - // `associated-types-projection-to-unrelated-trait-in-method-without-default.rs`. - err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate())); } /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index 1795fb5acebe..9f6a73cfe391 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -10,7 +10,7 @@ error[E0277]: `<::C as std::iter::Iterator>::Item` is not an iterato --> $DIR/bad-bounds-on-assoc-in-trait.rs:37:1 | LL | fn assume_case1() { - | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::iter::Iterator` + | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::iter::Iterator` | _| | | LL | | @@ -30,7 +30,7 @@ LL | trait Case1 { | ----------- required by `Case1` ... LL | fn assume_case1() { - | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Send` + | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Send` | _| | | LL | | @@ -50,7 +50,7 @@ LL | trait Case1 { | ----------- required by `Case1` ... LL | fn assume_case1() { - | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Sync` + | ^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Sync` | _| | | LL | | diff --git a/src/test/ui/associated-types/associated-types-bound-failure.fixed b/src/test/ui/associated-types/associated-types-bound-failure.fixed index 68ee38d16b3f..cc47f31d0045 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.fixed +++ b/src/test/ui/associated-types/associated-types-bound-failure.fixed @@ -14,7 +14,7 @@ pub trait GetToInt } fn foo(g: G) -> isize - where G : GetToInt, ::R: ToInt + where G : GetToInt, ::R: ToInt { ToInt::to_int(&g.get()) //~ ERROR E0277 } diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed b/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed index b27d58018c29..aa23326506f6 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed @@ -7,7 +7,7 @@ trait Get { } trait Other { - fn uhoh(&self, foo: U, bar: ::Value) where Self: Get{} + fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} //~^ ERROR the trait bound `Self: Get` is not satisfied } diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index f8fc2b37e730..83d5390417e7 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-for-unimpl-trait.rs:10:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ - | | | - | | help: consider further restricting `Self`: `where Self: Get` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ + | | | + | | help: consider further restricting `Self`: `where Self: Get` | the trait `Get` is not implemented for `Self` error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index 43950defc7cb..6aa0403088d3 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ - | | | - | | help: consider further restricting `Self`: `where Self: Get` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ + | | | + | | help: consider further restricting `Self`: `where Self: Get` | the trait `Get` is not implemented for `Self` error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index 82e366dbea4b..8c242be97961 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -2,9 +2,9 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ - | | | - | | help: consider further restricting `Self`: `where Self: Get` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ + | | | + | | help: consider further restricting `Self`: `where Self: Get` | the trait `Get` is not implemented for `Self` error[E0277]: the trait bound `(T, U): Get` is not satisfied diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed index 9bc308465ebd..f357045a456e 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed @@ -7,7 +7,7 @@ trait Get { } trait Other { - fn okay(&self, foo: U, bar: ::Value) where Self: Get; + fn okay(&self, foo: U, bar: ::Value) where Self: Get ; //~^ ERROR E0277 } diff --git a/src/test/ui/associated-types/associated-types-unsized.fixed b/src/test/ui/associated-types/associated-types-unsized.fixed index 385de541e560..f780d171fee8 100644 --- a/src/test/ui/associated-types/associated-types-unsized.fixed +++ b/src/test/ui/associated-types/associated-types-unsized.fixed @@ -6,7 +6,7 @@ trait Get { fn get(&self) -> ::Value; } -fn foo(t: T) where ::Value: std::marker::Sized{ +fn foo(t: T) where ::Value: std::marker::Sized { let x = t.get(); //~ ERROR the size for values of type } diff --git a/src/test/ui/associated-types/associated-types-unsized.stderr b/src/test/ui/associated-types/associated-types-unsized.stderr index 18595721bcee..2352ac4ad382 100644 --- a/src/test/ui/associated-types/associated-types-unsized.stderr +++ b/src/test/ui/associated-types/associated-types-unsized.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `::Value` cannot be known at --> $DIR/associated-types-unsized.rs:10:9 | LL | fn foo(t: T) { - | - help: consider further restricting the associated type: `where ::Value: std::marker::Sized` + | - help: consider further restricting the associated type: `where ::Value: std::marker::Sized` LL | let x = t.get(); | ^ doesn't have a size known at compile-time | diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed index 757d8b8a235a..7a108d880bed 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed @@ -7,7 +7,7 @@ trait Trait { type AssocType; fn dummy(&self) { } } -fn bar() where ::AssocType: std::marker::Send{ +fn bar() where ::AssocType: std::marker::Send { is_send::(); //~ ERROR E0277 } diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr index dd6dcbe2ef57..2e54cdf01320 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr @@ -2,7 +2,7 @@ error[E0277]: `::AssocType` cannot be sent between threads safely --> $DIR/typeck-default-trait-impl-assoc-type.rs:11:5 | LL | fn bar() { - | - help: consider further restricting the associated type: `where ::AssocType: std::marker::Send` + | - help: consider further restricting the associated type: `where ::AssocType: std::marker::Send` LL | is_send::(); | ^^^^^^^^^^^^^^^^^^^^^^^ `::AssocType` cannot be sent between threads safely ... diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.stderr b/src/test/ui/wf/wf-trait-associated-type-trait.stderr index d8ab95504823..93cb948cdbfc 100644 --- a/src/test/ui/wf/wf-trait-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-trait.stderr @@ -3,11 +3,12 @@ error[E0277]: the trait bound `::Type1: std::marker::Copy` is | LL | struct IsCopy { x: T } | --------------------- required by `IsCopy` -... +LL | +LL | trait SomeTrait { + | - help: consider further restricting the associated type: `where ::Type1: std::marker::Copy` +LL | type Type1; LL | type Type2 = IsCopy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `::Type1` - | - = help: consider adding a `where ::Type1: std::marker::Copy` bound error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr index 3efcdf72eee3..9f3545b9c6a6 100644 --- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr @@ -5,7 +5,7 @@ LL | struct Bar { value: Box } | ----------------------- required by `Bar` ... LL | fn bar(&self, x: &Bar) { - | ^ - help: consider further restricting `Self`: `where Self: std::cmp::Eq` + | ^ - help: consider further restricting `Self`: `where Self: std::cmp::Eq` | _____| | | LL | | From 39a9e2ecba1797ef196725c25f48746834d8ac8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Oct 2019 13:17:51 -0700 Subject: [PATCH 428/545] Remove useless `help` --- src/librustc/traits/error_reporting.rs | 11 +---------- src/test/ui/partialeq_help.stderr | 1 - src/test/ui/traits/trait-suggest-where-clause.stderr | 2 -- 3 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index abf265be7c50..9931a2517f11 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -969,19 +969,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_ref: &ty::PolyTraitRef<'_>, body_id: hir::HirId, ) { - debug!( - "suggest_restricting_param_bound trait_ref={:?} ty={:?} ({:?})", - trait_ref, - trait_ref.self_ty(), - trait_ref.self_ty().kind, - ); let (param_ty, projection) = match &trait_ref.self_ty().kind { ty::Param(param_ty) => (Some(param_ty), None), ty::Projection(projection) => (None, Some(projection)), - _ => { - err.help(&format!("consider adding a `where {}` bound", trait_ref.to_predicate())); - return; - } + _ => return, }; let mut suggest_restriction = |generics: &hir::Generics, msg| { diff --git a/src/test/ui/partialeq_help.stderr b/src/test/ui/partialeq_help.stderr index 9021bd30a778..6acc09b62c81 100644 --- a/src/test/ui/partialeq_help.stderr +++ b/src/test/ui/partialeq_help.stderr @@ -5,7 +5,6 @@ LL | a == b; | ^^ no implementation for `&T == T` | = help: the trait `std::cmp::PartialEq` is not implemented for `&T` - = help: consider adding a `where &T: std::cmp::PartialEq` bound error: aborting due to previous error diff --git a/src/test/ui/traits/trait-suggest-where-clause.stderr b/src/test/ui/traits/trait-suggest-where-clause.stderr index bc9948064a30..f1004ea9dc6e 100644 --- a/src/test/ui/traits/trait-suggest-where-clause.stderr +++ b/src/test/ui/traits/trait-suggest-where-clause.stderr @@ -39,7 +39,6 @@ error[E0277]: the trait bound `u64: std::convert::From` is not satisfied LL | >::from; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From` is not implemented for `u64` | - = help: consider adding a `where u64: std::convert::From` bound = note: required by `std::convert::From::from` error[E0277]: the trait bound `u64: std::convert::From<::Item>` is not satisfied @@ -48,7 +47,6 @@ error[E0277]: the trait bound `u64: std::convert::From<::Item>>::from; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<::Item>` is not implemented for `u64` | - = help: consider adding a `where u64: std::convert::From<::Item>` bound = note: required by `std::convert::From::from` error[E0277]: the trait bound `Misc<_>: std::convert::From` is not satisfied From 8cabb425415028e3abad56034e7daef6f05343bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 10 Oct 2019 13:22:05 -0700 Subject: [PATCH 429/545] Remove trailing whitespace --- src/librustc/traits/error_reporting.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 9931a2517f11..66d844ee808e 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1066,7 +1066,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { param_name == p.name.ident().as_str() }) { if param_name.starts_with("impl ") { - // `impl Trait` in argument: + // `impl Trait` in argument: // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}` err.span_suggestion( param.span, From 9c525ee95bcc99730003e2d4bbb58520337bdefc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 13:16:33 -0700 Subject: [PATCH 430/545] review comments --- src/librustc/traits/error_reporting.rs | 110 ++++++++++++------------- 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 66d844ee808e..8e9a350030c4 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -969,9 +969,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { trait_ref: &ty::PolyTraitRef<'_>, body_id: hir::HirId, ) { - let (param_ty, projection) = match &trait_ref.self_ty().kind { - ty::Param(param_ty) => (Some(param_ty), None), - ty::Projection(projection) => (None, Some(projection)), + let self_ty = trait_ref.self_ty(); + let (param_ty, projection) = match &self_ty.kind { + ty::Param(_) => (true, None), + ty::Projection(projection) => (false, Some(projection)), _ => return, }; @@ -997,17 +998,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut hir_id = body_id; while let Some(node) = self.tcx.hir().find(hir_id) { match node { - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(_, _, generics, _), .. - }) | hir::Node::TraitItem(hir::TraitItem { generics, kind: hir::TraitItemKind::Method(..), .. - }) | - hir::Node::ImplItem(hir::ImplItem { - generics, - kind: hir::ImplItemKind::Method(..), .. - }) if param_ty.map_or(false, |p| p.name.as_str() == "Self") => { + }) if param_ty && self_ty == self.tcx.types.self_param => { // Restricting `Self` for a single method. suggest_restriction(&generics, "`Self`"); return; @@ -1058,12 +1052,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) | hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) | hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) - if param_ty.is_some() => { + if param_ty => { // Missing generic type parameter bound. let restrict_msg = "consider further restricting this bound"; - let param_name = param_ty.unwrap().name.as_str(); + let param_name = self_ty.to_string(); for param in generics.params.iter().filter(|p| { - param_name == p.name.ident().as_str() + ¶m_name == p.name.ident().as_str() }) { if param_name.starts_with("impl ") { // `impl Trait` in argument: @@ -1075,53 +1069,51 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { format!("{} + {}", param.name.ident(), trait_ref), Applicability::MachineApplicable, ); - } else { - if generics.where_clause.predicates.is_empty() && + } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() - { - // If there are no bounds whatsoever, suggest adding a constraint - // to the type parameter: - // `fn foo(t: T) {}` → `fn foo(t: T) {}` - err.span_suggestion( - param.span, - "consider restricting this bound", - format!("{}", trait_ref.to_predicate()), - Applicability::MachineApplicable, - ); - } else if !generics.where_clause.predicates.is_empty() { - // There is a `where` clause, so suggest expanding it: - // `fn foo(t: T) where T: Debug {}` → - // `fn foo(t: T) {}` → `fn foo(t: T) {}` + err.span_suggestion( + param.span, + "consider restricting this bound", + format!("{}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } else if !generics.where_clause.predicates.is_empty() { + // There is a `where` clause, so suggest expanding it: + // `fn foo(t: T) where T: Debug {}` → + // `fn foo(t: T) where T: Debug, T: Trait {}` + err.span_suggestion( + generics.where_clause.span().unwrap().shrink_to_hi(), + &format!( + "consider further restricting type parameter `{}`", + param_name, + ), + format!(", {}", trait_ref.to_predicate()), + Applicability::MachineApplicable, + ); + } else { + // If there is no `where` clause lean towards constraining to the + // type parameter: + // `fn foo(t: T, x: X) {}` → `fn foo(t: T) {}` + // `fn foo(t: T) {}` → `fn foo(t: T) {}` + let sp = param.span.with_hi(span.hi()); + let span = self.tcx.sess.source_map() + .span_through_char(sp, ':'); + if sp != param.span && sp != span { + // Only suggest if we have high certainty that the span + // covers the colon in `foo`. + err.span_suggestion(span, restrict_msg, format!( + "{} + ", + trait_ref.to_predicate(), + ), Applicability::MachineApplicable); } else { - // If there is no `where` clause lean towards constraining to the - // type parameter: - // `fn foo(t: T, x: X) {}` → `fn foo(t: T) {}` - // `fn foo(t: T) {}` → `fn foo(t: T) {}` - let sp = param.span.with_hi(span.hi()); - let span = self.tcx.sess.source_map() - .span_through_char(sp, ':'); - if sp != param.span && sp != span { - // Only suggest if we have high certainty that the span - // covers the colon in `foo`. - err.span_suggestion(span, restrict_msg, format!( - "{} + ", - trait_ref.to_predicate(), - ), Applicability::MachineApplicable); - } else { - err.span_label(param.span, &format!( - "consider adding a `where {}` bound", - trait_ref.to_predicate(), - )); - } + err.span_label(param.span, &format!( + "consider adding a `where {}` bound", + trait_ref.to_predicate(), + )); } } return; From 9ed463a7404f7f3ecf65ca270f360b2da90b467a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 13:29:07 -0700 Subject: [PATCH 431/545] Do not suggest restriction on spans originating in macros --- src/librustc/traits/error_reporting.rs | 31 ++++++++++++++------------ src/test/ui/issues/issue-38821.stderr | 4 +--- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 8e9a350030c4..d5f22afa9afc 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -977,20 +977,23 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }; let mut suggest_restriction = |generics: &hir::Generics, msg| { - err.span_suggestion( - generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(), - &format!("consider further restricting {}", msg), - format!( - "{} {} ", - if !generics.where_clause.predicates.is_empty() { - "," - } else { - " where" - }, - trait_ref.to_predicate(), - ), - Applicability::MachineApplicable, - ); + let span = generics.where_clause.span_for_predicates_or_empty_place(); + if !span.from_expansion() && span.desugaring_kind().is_none() { + err.span_suggestion( + generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(), + &format!("consider further restricting {}", msg), + format!( + "{} {} ", + if !generics.where_clause.predicates.is_empty() { + "," + } else { + " where" + }, + trait_ref.to_predicate(), + ), + Applicability::MachineApplicable, + ); + } }; // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we diff --git a/src/test/ui/issues/issue-38821.stderr b/src/test/ui/issues/issue-38821.stderr index 3e2af7c44e4a..0687fc940dec 100644 --- a/src/test/ui/issues/issue-38821.stderr +++ b/src/test/ui/issues/issue-38821.stderr @@ -2,9 +2,7 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not sat --> $DIR/issue-38821.rs:23:17 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^- help: consider further restricting the associated type: `, ::SqlType: NotNull` - | | - | the trait `NotNull` is not implemented for `::SqlType` + | ^^^^ the trait `NotNull` is not implemented for `::SqlType` | = note: required because of the requirements on the impl of `IntoNullable` for `::SqlType` From 9ecd1d276732b301fff85a1e660771691db23dbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 13:29:26 -0700 Subject: [PATCH 432/545] Simplify code --- src/librustc_typeck/check/demand.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index d92ea7fd49a7..677e2ea35662 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -350,11 +350,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the span is from a macro, then it's hard to extract the text // and make a good suggestion, so don't bother. - let is_desugaring = match sp.desugaring_kind() { - Some(k) => sp.is_desugaring(k), - None => false - }; - let is_macro = sp.from_expansion() && !is_desugaring; + let is_macro = sp.from_expansion() && sp.desugaring_kind().is_none(); // `ExprKind::DropTemps` is semantically irrelevant for these suggestions. let expr = expr.peel_drop_temps(); From c6dce7802dc49a2e4b6049ad8971ba6f18252e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Oct 2019 14:07:32 -0700 Subject: [PATCH 433/545] Fix comparison after rebase --- src/librustc/traits/error_reporting.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index d5f22afa9afc..daa4a215a238 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1060,7 +1060,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let restrict_msg = "consider further restricting this bound"; let param_name = self_ty.to_string(); for param in generics.params.iter().filter(|p| { - ¶m_name == p.name.ident().as_str() + ¶m_name == std::convert::AsRef::::as_ref(&p.name.ident().as_str()) }) { if param_name.starts_with("impl ") { // `impl Trait` in argument: From 247df6e13492d7d9ffed3de49aa59067ef8267f1 Mon Sep 17 00:00:00 2001 From: boyned//Kampfkarren Date: Wed, 16 Oct 2019 00:06:01 -0700 Subject: [PATCH 434/545] Don't recommend ONCE_INIT in std::sync::Once ONCE_INIT is deprecated, and so suggesting it as not only being on par with, but before `Once::new` is a bad idea. --- src/libstd/sync/once.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index e529b8c4227f..e28fbca7fa1c 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -60,10 +60,9 @@ use crate::thread::{self, Thread}; /// A synchronization primitive which can be used to run a one-time global /// initialization. Useful for one-time initialization for FFI or related -/// functionality. This type can only be constructed with the [`ONCE_INIT`] -/// value or the equivalent [`Once::new`] constructor. +/// functionality. This type can only be constructed with the [`Once::new`] +/// constructor. /// -/// [`ONCE_INIT`]: constant.ONCE_INIT.html /// [`Once::new`]: struct.Once.html#method.new /// /// # Examples From 9dba03f6cd8b51db9423f1d2fc9c94acd72b6183 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 07:39:29 +0200 Subject: [PATCH 435/545] move parse::attr -> parse::parser::attr --- src/libsyntax/parse/mod.rs | 1 - src/libsyntax/parse/parser.rs | 1 + src/libsyntax/parse/{ => parser}/attr.rs | 0 3 files changed, 1 insertion(+), 1 deletion(-) rename src/libsyntax/parse/{ => parser}/attr.rs (100%) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index cb90caab77a8..6bcd9cd9b638 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -24,7 +24,6 @@ mod tests; #[macro_use] pub mod parser; -pub mod attr; pub mod lexer; pub mod token; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 86383761484d..b710fcff65b7 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1,3 +1,4 @@ +mod attr; mod expr; mod pat; mod item; diff --git a/src/libsyntax/parse/attr.rs b/src/libsyntax/parse/parser/attr.rs similarity index 100% rename from src/libsyntax/parse/attr.rs rename to src/libsyntax/parse/parser/attr.rs From 7d7969d065c438399cde2ebdcd411e5225a31b88 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 09:06:07 +0200 Subject: [PATCH 436/545] syntax: extract parse_derive_paths --- src/libsyntax/attr/mod.rs | 18 +++--------------- src/libsyntax/ext/proc_macro.rs | 4 +--- src/libsyntax/parse/parser/path.rs | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index d291e502c255..965d4597430f 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -298,24 +298,12 @@ impl Attribute { Ok(result) } - pub fn parse_list<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, Vec> - where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, - { + pub fn parse_derive_paths<'a>(&self, sess: &'a ParseSess) -> PResult<'a, Vec> { if self.tokens.is_empty() { return Ok(Vec::new()); } - self.parse(sess, |parser| { - parser.expect(&token::OpenDelim(token::Paren))?; - let mut list = Vec::new(); - while !parser.eat(&token::CloseDelim(token::Paren)) { - list.push(f(parser)?); - if !parser.eat(&token::Comma) { - parser.expect(&token::CloseDelim(token::Paren))?; - break - } - } - Ok(list) - }) + + self.parse(sess, |p| p.parse_derive_paths()) } pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { diff --git a/src/libsyntax/ext/proc_macro.rs b/src/libsyntax/ext/proc_macro.rs index e17bbf79fd5e..72062d2ffbf5 100644 --- a/src/libsyntax/ext/proc_macro.rs +++ b/src/libsyntax/ext/proc_macro.rs @@ -4,7 +4,6 @@ use crate::errors::{Applicability, FatalError}; use crate::ext::base::{self, *}; use crate::ext::proc_macro_server; use crate::parse::{self, token}; -use crate::parse::parser::PathStyle; use crate::symbol::sym; use crate::tokenstream::{self, TokenStream}; use crate::visit::Visitor; @@ -205,8 +204,7 @@ crate fn collect_derives(cx: &mut ExtCtxt<'_>, attrs: &mut Vec) return false; } - match attr.parse_list(cx.parse_sess, - |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) { + match attr.parse_derive_paths(cx.parse_sess) { Ok(traits) => { result.extend(traits); true diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs index ca823991a2e5..1f48cc753048 100644 --- a/src/libsyntax/parse/parser/path.rs +++ b/src/libsyntax/parse/parser/path.rs @@ -111,7 +111,7 @@ impl<'a> Parser<'a> { /// Like `parse_path`, but also supports parsing `Word` meta items into paths for /// backwards-compatibility. This is used when parsing derive macro paths in `#[derive]` /// attributes. - pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> { + fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> { let meta_ident = match self.token.kind { token::Interpolated(ref nt) => match **nt { token::NtMeta(ref item) => match item.tokens.is_empty() { @@ -129,6 +129,21 @@ impl<'a> Parser<'a> { self.parse_path(style) } + /// Parse a list of paths inside `#[derive(path_0, ..., path_n)]`. + crate fn parse_derive_paths(&mut self) -> PResult<'a, Vec> { + self.expect(&token::OpenDelim(token::Paren))?; + let mut list = Vec::new(); + while !self.eat(&token::CloseDelim(token::Paren)) { + let path = self.parse_path_allowing_meta(PathStyle::Mod)?; + list.push(path); + if !self.eat(&token::Comma) { + self.expect(&token::CloseDelim(token::Paren))?; + break + } + } + Ok(list) + } + crate fn parse_path_segments( &mut self, segments: &mut Vec, From 41bfe94d404c69f0f2e7ebad7383940cf0ac1cb3 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 09:14:07 +0200 Subject: [PATCH 437/545] syntax: extract parse_cfg_attr --- src/libsyntax/attr/mod.rs | 1 - src/libsyntax/config.rs | 21 +-------------------- src/libsyntax/parse/parser/attr.rs | 21 +++++++++++++++++++++ 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 965d4597430f..9c1e0bcaa4a1 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -302,7 +302,6 @@ impl Attribute { if self.tokens.is_empty() { return Ok(Vec::new()); } - self.parse(sess, |p| p.parse_derive_paths()) } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 2099d018b7b3..ee5a4eeb3a31 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -10,7 +10,6 @@ use crate::attr; use crate::ast; use crate::edition::Edition; use crate::mut_visit::*; -use crate::parse::token; use crate::ptr::P; use crate::sess::ParseSess; use crate::symbol::sym; @@ -112,25 +111,7 @@ impl<'a> StripUnconfigured<'a> { return vec![]; } - let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |parser| { - parser.expect(&token::OpenDelim(token::Paren))?; - - let cfg_predicate = parser.parse_meta_item()?; - parser.expect(&token::Comma)?; - - // Presumably, the majority of the time there will only be one attr. - let mut expanded_attrs = Vec::with_capacity(1); - - while !parser.check(&token::CloseDelim(token::Paren)) { - let lo = parser.token.span.lo(); - let item = parser.parse_attr_item()?; - expanded_attrs.push((item, parser.prev_span.with_lo(lo))); - parser.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?; - } - - parser.expect(&token::CloseDelim(token::Paren))?; - Ok((cfg_predicate, expanded_attrs)) - }) { + let (cfg_predicate, expanded_attrs) = match attr.parse(self.sess, |p| p.parse_cfg_attr()) { Ok(result) => result, Err(mut e) => { e.emit(); diff --git a/src/libsyntax/parse/parser/attr.rs b/src/libsyntax/parse/parser/attr.rs index 0963efcfc8ac..07689df389c2 100644 --- a/src/libsyntax/parse/parser/attr.rs +++ b/src/libsyntax/parse/parser/attr.rs @@ -260,6 +260,27 @@ impl<'a> Parser<'a> { Ok(lit) } + /// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited. + crate fn parse_cfg_attr(&mut self) -> PResult<'a, (ast::MetaItem, Vec<(ast::AttrItem, Span)>)> { + self.expect(&token::OpenDelim(token::Paren))?; + + let cfg_predicate = self.parse_meta_item()?; + self.expect(&token::Comma)?; + + // Presumably, the majority of the time there will only be one attr. + let mut expanded_attrs = Vec::with_capacity(1); + + while !self.check(&token::CloseDelim(token::Paren)) { + let lo = self.token.span.lo(); + let item = self.parse_attr_item()?; + expanded_attrs.push((item, self.prev_span.with_lo(lo))); + self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?; + } + + self.expect(&token::CloseDelim(token::Paren))?; + Ok((cfg_predicate, expanded_attrs)) + } + /// Matches the following grammar (per RFC 1559). /// /// meta_item : PATH ( '=' UNSUFFIXED_LIT | '(' meta_item_inner? ')' )? ; From 98017ca53a0c3ac6a10f60b47462bd3546baaaa1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 09:46:06 +0200 Subject: [PATCH 438/545] move diagnostics.rs into parser/ --- src/libsyntax/parse/mod.rs | 1 - src/libsyntax/parse/parser.rs | 3 ++- src/libsyntax/parse/{ => parser}/diagnostics.rs | 0 src/libsyntax/parse/parser/expr.rs | 2 +- src/libsyntax/parse/parser/item.rs | 3 ++- src/libsyntax/parse/parser/module.rs | 2 +- src/libsyntax/parse/parser/stmt.rs | 2 +- 7 files changed, 7 insertions(+), 6 deletions(-) rename src/libsyntax/parse/{ => parser}/diagnostics.rs (100%) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 6bcd9cd9b638..1eaee46a3c22 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -28,7 +28,6 @@ pub mod lexer; pub mod token; crate mod classify; -crate mod diagnostics; crate mod literal; crate mod unescape_error_reporting; diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b710fcff65b7..6f55fd23e6e1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -10,7 +10,8 @@ mod path; pub use path::PathStyle; mod stmt; mod generics; -use super::diagnostics::Error; +mod diagnostics; +use diagnostics::Error; use crate::ast::{ self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/parser/diagnostics.rs similarity index 100% rename from src/libsyntax/parse/diagnostics.rs rename to src/libsyntax/parse/parser/diagnostics.rs diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index dd0fd834fb0c..6e52a07c61d8 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1,6 +1,7 @@ use super::{Parser, PResult, Restrictions, PrevTokenKind, TokenType, PathStyle, BlockMode}; use super::{SemiColonMode, SeqSep, TokenExpectType}; use super::pat::{GateOr, PARAM_EXPECTED}; +use super::diagnostics::Error; use crate::parse::literal::LitError; @@ -12,7 +13,6 @@ use crate::ast::{ use crate::maybe_recover_from_interpolated_ty_qpath; use crate::parse::classify; use crate::parse::token::{self, Token, TokenKind}; -use crate::parse::diagnostics::Error; use crate::print::pprust; use crate::ptr::P; use crate::source_map::{self, Span}; diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 08c624b5539d..90517d4d7708 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -1,4 +1,6 @@ use super::{Parser, PResult, PathStyle, SemiColonMode, BlockMode}; +use super::diagnostics::{Error, dummy_arg}; + use crate::maybe_whole; use crate::ptr::P; use crate::ast::{self, DUMMY_NODE_ID, Ident, Attribute, AttrStyle, AnonConst, Item, ItemKind}; @@ -10,7 +12,6 @@ use crate::ast::{Mac, MacDelimiter, Block, BindingMode, FnDecl, MethodSig, SelfK use crate::ext::base::DummyResult; use crate::parse::token; use crate::parse::parser::maybe_append; -use crate::parse::diagnostics::{Error, dummy_arg}; use crate::tokenstream::{TokenTree, TokenStream}; use crate::symbol::{kw, sym}; use crate::source_map::{self, respan, Span}; diff --git a/src/libsyntax/parse/parser/module.rs b/src/libsyntax/parse/parser/module.rs index 2d2fb487d7df..20bd189cf8fb 100644 --- a/src/libsyntax/parse/parser/module.rs +++ b/src/libsyntax/parse/parser/module.rs @@ -1,11 +1,11 @@ use super::{Parser, PResult}; use super::item::ItemInfo; +use super::diagnostics::Error; use crate::attr; use crate::ast::{self, Ident, Attribute, ItemKind, Mod, Crate}; use crate::parse::{new_sub_parser_from_file, DirectoryOwnership}; use crate::parse::token::{self, TokenKind}; -use crate::parse::diagnostics::{Error}; use crate::source_map::{SourceMap, Span, DUMMY_SP, FileName}; use crate::symbol::sym; diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index 855b03ddd6f6..c8d6b6ff9ddc 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -2,6 +2,7 @@ use super::{Parser, PResult, Restrictions, PrevTokenKind, SemiColonMode, BlockMo use super::expr::LhsExpr; use super::path::PathStyle; use super::pat::GateOr; +use super::diagnostics::Error; use crate::ptr::P; use crate::{maybe_whole, ThinVec}; @@ -9,7 +10,6 @@ use crate::ast::{self, DUMMY_NODE_ID, Stmt, StmtKind, Local, Block, BlockCheckMo use crate::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter}; use crate::ext::base::DummyResult; use crate::parse::{classify, DirectoryOwnership}; -use crate::parse::diagnostics::Error; use crate::parse::token; use crate::source_map::{respan, Span}; use crate::symbol::{kw, sym}; From c189565edc5c9fc516170885b3a3061b936205fb Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 09:35:34 +0200 Subject: [PATCH 439/545] syntax: reduce visibilities --- src/libsyntax/attr/mod.rs | 6 +- src/libsyntax/ext/expand.rs | 2 +- src/libsyntax/parse/literal.rs | 2 +- src/libsyntax/parse/parser.rs | 60 +++++++++--------- src/libsyntax/parse/parser/attr.rs | 11 ++-- src/libsyntax/parse/parser/diagnostics.rs | 77 ++++++++++++----------- src/libsyntax/parse/parser/expr.rs | 8 +-- src/libsyntax/parse/parser/generics.rs | 2 +- src/libsyntax/parse/parser/item.rs | 6 +- src/libsyntax/parse/parser/module.rs | 10 +-- src/libsyntax/parse/parser/pat.rs | 4 +- src/libsyntax/parse/parser/path.rs | 6 +- src/libsyntax/parse/parser/stmt.rs | 6 +- src/libsyntax/parse/parser/ty.rs | 2 +- 14 files changed, 101 insertions(+), 101 deletions(-) diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 9c1e0bcaa4a1..65257c7e9855 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -280,7 +280,7 @@ impl Attribute { self.item.meta(self.span) } - pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T> + crate fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T> where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>, { let mut parser = Parser::new( @@ -298,14 +298,14 @@ impl Attribute { Ok(result) } - pub fn parse_derive_paths<'a>(&self, sess: &'a ParseSess) -> PResult<'a, Vec> { + crate fn parse_derive_paths<'a>(&self, sess: &'a ParseSess) -> PResult<'a, Vec> { if self.tokens.is_empty() { return Ok(Vec::new()); } self.parse(sess, |p| p.parse_derive_paths()) } - pub fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { + crate fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { Ok(MetaItem { path: self.path.clone(), kind: self.parse(sess, |parser| parser.parse_meta_item_kind())?, diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 2559e8747627..44a51a017104 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -838,7 +838,7 @@ impl<'a> Parser<'a> { self.this_token_to_string()); // Avoid emitting backtrace info twice. let def_site_span = self.token.span.with_ctxt(SyntaxContext::root()); - let mut err = self.diagnostic().struct_span_err(def_site_span, &msg); + let mut err = self.struct_span_err(def_site_span, &msg); err.span_label(span, "caused by the macro expansion here"); let msg = format!( "the usage of `{}!` is likely invalid in {} context", diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 14e1696610a4..54e523430e45 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -212,7 +212,7 @@ impl Lit { /// Attempts to recover an AST literal from semantic literal. /// This function is used when the original token doesn't exist (e.g. the literal is created /// by an AST-based macro) or unavailable (e.g. from HIR pretty-printing). - pub fn from_lit_kind(kind: LitKind, span: Span) -> Lit { + crate fn from_lit_kind(kind: LitKind, span: Span) -> Lit { Lit { token: kind.to_lit_token(), kind, span } } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6f55fd23e6e1..7914fdbf9788 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2,12 +2,10 @@ mod attr; mod expr; mod pat; mod item; -pub use item::AliasKind; mod module; -pub use module::{ModulePath, ModulePathSuccess}; mod ty; mod path; -pub use path::PathStyle; +crate use path::PathStyle; mod stmt; mod generics; mod diagnostics; @@ -46,14 +44,14 @@ bitflags::bitflags! { } #[derive(Clone, Copy, PartialEq, Debug)] -crate enum SemiColonMode { +enum SemiColonMode { Break, Ignore, Comma, } #[derive(Clone, Copy, PartialEq, Debug)] -crate enum BlockMode { +enum BlockMode { Break, Ignore, } @@ -126,33 +124,33 @@ pub struct Parser<'a> { prev_token_kind: PrevTokenKind, restrictions: Restrictions, /// Used to determine the path to externally loaded source files. - crate directory: Directory<'a>, + pub(super) directory: Directory<'a>, /// `true` to parse sub-modules in other files. - pub recurse_into_file_modules: bool, + pub(super) 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. - pub root_module_name: Option, - crate expected_tokens: Vec, + crate root_module_name: Option, + expected_tokens: Vec, token_cursor: TokenCursor, desugar_doc_comments: bool, /// `true` we should configure out of line modules as we parse. - pub cfg_mods: bool, + 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. /// /// See the comments in the `parse_path_segment` function for more details. - crate unmatched_angle_bracket_count: u32, - crate max_angle_bracket_count: u32, + unmatched_angle_bracket_count: u32, + max_angle_bracket_count: u32, /// A list of all unclosed delimiters found by the lexer. If an entry is used for error recovery /// it gets removed from here. Every entry left at the end gets emitted as an independent /// error. - crate unclosed_delims: Vec, - crate last_unexpected_token_span: Option, + pub(super) unclosed_delims: Vec, + last_unexpected_token_span: Option, crate last_type_ascription: Option<(Span, bool /* likely path typo */)>, /// If present, this `Parser` is not parsing Rust code but rather a macro call. - crate subparser_name: Option<&'static str>, + subparser_name: Option<&'static str>, } impl<'a> Drop for Parser<'a> { @@ -196,7 +194,7 @@ struct TokenCursorFrame { /// You can find some more example usage of this in the `collect_tokens` method /// on the parser. #[derive(Clone)] -crate enum LastToken { +enum LastToken { Collecting(Vec), Was(Option), } @@ -299,7 +297,7 @@ impl TokenCursor { } #[derive(Clone, PartialEq)] -crate enum TokenType { +enum TokenType { Token(TokenKind), Keyword(Symbol), Operator, @@ -311,7 +309,7 @@ crate enum TokenType { } impl TokenType { - crate fn to_string(&self) -> String { + fn to_string(&self) -> String { match *self { TokenType::Token(ref t) => format!("`{}`", pprust::token_kind_to_string(t)), TokenType::Keyword(kw) => format!("`{}`", kw), @@ -326,13 +324,13 @@ impl TokenType { } #[derive(Copy, Clone, Debug)] -crate enum TokenExpectType { +enum TokenExpectType { Expect, NoExpect, } impl<'a> Parser<'a> { - pub fn new( + crate fn new( sess: &'a ParseSess, tokens: TokenStream, directory: Option>, @@ -407,7 +405,7 @@ impl<'a> Parser<'a> { pprust::token_to_string(&self.token) } - crate fn token_descr(&self) -> Option<&'static str> { + fn token_descr(&self) -> Option<&'static str> { Some(match &self.token.kind { _ if self.token.is_special_ident() => "reserved identifier", _ if self.token.is_used_keyword() => "keyword", @@ -417,7 +415,7 @@ impl<'a> Parser<'a> { }) } - crate fn this_token_descr(&self) -> String { + pub(super) fn this_token_descr(&self) -> String { if let Some(prefix) = self.token_descr() { format!("{} `{}`", prefix, self.this_token_to_string()) } else { @@ -467,7 +465,7 @@ impl<'a> Parser<'a> { } } - pub fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { + fn parse_ident(&mut self) -> PResult<'a, ast::Ident> { self.parse_ident_common(true) } @@ -500,7 +498,7 @@ impl<'a> Parser<'a> { /// /// This method will automatically add `tok` to `expected_tokens` if `tok` is not /// encountered. - crate fn check(&mut self, tok: &TokenKind) -> bool { + fn check(&mut self, tok: &TokenKind) -> bool { let is_present = self.token == *tok; if !is_present { self.expected_tokens.push(TokenType::Token(tok.clone())); } is_present @@ -522,7 +520,7 @@ impl<'a> Parser<'a> { /// If the next token is the given keyword, eats it and returns `true`. /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes. - pub fn eat_keyword(&mut self, kw: Symbol) -> bool { + fn eat_keyword(&mut self, kw: Symbol) -> bool { if self.check_keyword(kw) { self.bump(); true @@ -560,7 +558,7 @@ impl<'a> Parser<'a> { } } - crate fn check_ident(&mut self) -> bool { + fn check_ident(&mut self) -> bool { self.check_or_expected(self.token.is_ident(), TokenType::Ident) } @@ -725,7 +723,7 @@ impl<'a> Parser<'a> { /// Parses a sequence, including the closing delimiter. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_seq_to_end( + fn parse_seq_to_end( &mut self, ket: &TokenKind, sep: SeqSep, @@ -741,7 +739,7 @@ impl<'a> Parser<'a> { /// Parses a sequence, not including the closing delimiter. The function /// `f` must consume tokens until reaching the next separator or /// closing bracket. - pub fn parse_seq_to_before_end( + fn parse_seq_to_before_end( &mut self, ket: &TokenKind, sep: SeqSep, @@ -759,7 +757,7 @@ impl<'a> Parser<'a> { }) } - crate fn parse_seq_to_before_tokens( + fn parse_seq_to_before_tokens( &mut self, kets: &[&TokenKind], sep: SeqSep, @@ -1101,7 +1099,7 @@ impl<'a> Parser<'a> { /// If the following element can't be a tuple (i.e., it's a function definition), then /// it's not a tuple struct field), and the contents within the parentheses isn't valid, /// so emit a proper diagnostic. - pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { + crate fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { maybe_whole!(self, NtVis, |x| x); self.expected_tokens.push(TokenType::Keyword(kw::Crate)); @@ -1325,7 +1323,7 @@ impl<'a> Parser<'a> { *t == token::BinOp(token::Star)) } - pub fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option)> { + fn parse_optional_str(&mut self) -> Option<(Symbol, ast::StrStyle, Option)> { let ret = match self.token.kind { token::Literal(token::Lit { kind: token::Str, symbol, suffix }) => (symbol, ast::StrStyle::Cooked, suffix), diff --git a/src/libsyntax/parse/parser/attr.rs b/src/libsyntax/parse/parser/attr.rs index 07689df389c2..cfd10e443e96 100644 --- a/src/libsyntax/parse/parser/attr.rs +++ b/src/libsyntax/parse/parser/attr.rs @@ -20,7 +20,7 @@ const DEFAULT_UNEXPECTED_INNER_ATTR_ERR_MSG: &str = "an inner attribute is not \ impl<'a> Parser<'a> { /// Parses attributes that appear before an item. - crate fn parse_outer_attributes(&mut self) -> PResult<'a, Vec> { + pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec> { let mut attrs: Vec = Vec::new(); let mut just_parsed_doc_comment = false; loop { @@ -66,7 +66,7 @@ impl<'a> Parser<'a> { /// /// If `permit_inner` is `true`, then a leading `!` indicates an inner /// attribute. - pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> { + fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> { debug!("parse_attribute: permit_inner={:?} self.token={:?}", permit_inner, self.token); @@ -84,9 +84,10 @@ impl<'a> Parser<'a> { /// The same as `parse_attribute`, except it takes in an `InnerAttributeParsePolicy` /// that prescribes how to handle inner attributes. - fn parse_attribute_with_inner_parse_policy(&mut self, - inner_parse_policy: InnerAttributeParsePolicy<'_>) - -> PResult<'a, ast::Attribute> { + fn parse_attribute_with_inner_parse_policy( + &mut self, + inner_parse_policy: InnerAttributeParsePolicy<'_> + ) -> PResult<'a, ast::Attribute> { debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}", inner_parse_policy, self.token); diff --git a/src/libsyntax/parse/parser/diagnostics.rs b/src/libsyntax/parse/parser/diagnostics.rs index 943838d9dda7..a6884ec2c722 100644 --- a/src/libsyntax/parse/parser/diagnostics.rs +++ b/src/libsyntax/parse/parser/diagnostics.rs @@ -17,8 +17,9 @@ use log::{debug, trace}; use std::mem; const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify type arguments"; + /// Creates a placeholder argument. -crate fn dummy_arg(ident: Ident) -> Param { +pub(super) fn dummy_arg(ident: Ident) -> Param { let pat = P(Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None), @@ -121,7 +122,7 @@ impl Error { } } -pub trait RecoverQPath: Sized + 'static { +pub(super) trait RecoverQPath: Sized + 'static { const PATH_STYLE: PathStyle = PathStyle::Expr; fn to_ty(&self) -> Option>; fn recovered(qself: Option, path: ast::Path) -> Self; @@ -169,23 +170,23 @@ impl RecoverQPath for Expr { } impl<'a> Parser<'a> { - pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { + crate fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { self.span_fatal(self.token.span, m) } - pub fn span_fatal>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { + crate fn span_fatal>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_fatal(sp, m) } - pub fn span_fatal_err>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> { + pub(super) fn span_fatal_err>(&self, sp: S, err: Error) -> DiagnosticBuilder<'a> { err.span_err(sp, self.diagnostic()) } - pub fn bug(&self, m: &str) -> ! { + pub(super) fn bug(&self, m: &str) -> ! { self.sess.span_diagnostic.span_bug(self.token.span, m) } - pub fn span_err>(&self, sp: S, m: &str) { + pub(super) fn span_err>(&self, sp: S, m: &str) { self.sess.span_diagnostic.span_err(sp, m) } @@ -197,15 +198,15 @@ impl<'a> Parser<'a> { self.sess.span_diagnostic.span_bug(sp, m) } - crate fn diagnostic(&self) -> &'a errors::Handler { + pub(super) fn diagnostic(&self) -> &'a errors::Handler { &self.sess.span_diagnostic } - crate fn span_to_snippet(&self, span: Span) -> Result { + pub(super) fn span_to_snippet(&self, span: Span) -> Result { self.sess.source_map().span_to_snippet(span) } - crate fn expected_ident_found(&self) -> DiagnosticBuilder<'a> { + pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a> { let mut err = self.struct_span_err( self.token.span, &format!("expected identifier, found {}", self.this_token_descr()), @@ -236,7 +237,7 @@ impl<'a> Parser<'a> { err } - pub fn expected_one_of_not_found( + pub(super) fn expected_one_of_not_found( &mut self, edible: &[TokenKind], inedible: &[TokenKind], @@ -423,7 +424,7 @@ impl<'a> Parser<'a> { /// Eats and discards tokens until one of `kets` is encountered. Respects token trees, /// passes through any errors encountered. Used for error recovery. - crate fn eat_to_tokens(&mut self, kets: &[&TokenKind]) { + pub(super) fn eat_to_tokens(&mut self, kets: &[&TokenKind]) { if let Err(ref mut err) = self.parse_seq_to_before_tokens( kets, SeqSep::none(), @@ -441,7 +442,7 @@ impl<'a> Parser<'a> { /// let _ = vec![1, 2, 3].into_iter().collect::>>>(); /// ^^ help: remove extra angle brackets /// ``` - crate fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) { + pub(super) fn check_trailing_angle_brackets(&mut self, segment: &PathSegment, end: TokenKind) { // This function is intended to be invoked after parsing a path segment where there are two // cases: // @@ -560,7 +561,7 @@ impl<'a> Parser<'a> { /// inner_op r2 /// / \ /// l1 r1 - crate fn check_no_chained_comparison( + pub(super) fn check_no_chained_comparison( &mut self, lhs: &Expr, outer_op: &AssocOp, @@ -695,7 +696,7 @@ impl<'a> Parser<'a> { } } - crate fn maybe_report_ambiguous_plus( + pub(super) fn maybe_report_ambiguous_plus( &mut self, allow_plus: bool, impl_dyn_multi: bool, @@ -768,7 +769,7 @@ impl<'a> Parser<'a> { /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`. /// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem` /// tail, and combines them into a `::AssocItem` expression/pattern/type. - crate fn maybe_recover_from_bad_qpath( + pub(super) fn maybe_recover_from_bad_qpath( &mut self, base: P, allow_recovery: bool, @@ -784,7 +785,7 @@ impl<'a> Parser<'a> { /// Given an already parsed `Ty`, parses the `::AssocItem` tail and /// combines them into a `::AssocItem` expression/pattern/type. - crate fn maybe_recover_from_bad_qpath_stage_2( + pub(super) fn maybe_recover_from_bad_qpath_stage_2( &mut self, ty_span: Span, ty: P, @@ -823,7 +824,7 @@ impl<'a> Parser<'a> { ))) } - crate fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { + 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 `;`"); err.span_suggestion_short( @@ -859,7 +860,7 @@ impl<'a> Parser<'a> { /// Creates a `DiagnosticBuilder` for an unexpected token `t` and tries to recover if it is a /// closing delimiter. - pub fn unexpected_try_recover( + pub(super) fn unexpected_try_recover( &mut self, t: &TokenKind, ) -> PResult<'a, bool /* recovered */> { @@ -909,7 +910,7 @@ impl<'a> Parser<'a> { Err(err) } - crate fn parse_semi_or_incorrect_foreign_fn_body( + pub(super) fn parse_semi_or_incorrect_foreign_fn_body( &mut self, ident: &Ident, extern_sp: Span, @@ -947,7 +948,7 @@ impl<'a> Parser<'a> { /// Consumes alternative await syntaxes like `await!()`, `await `, /// `await? `, `await()`, and `await { }`. - crate fn parse_incorrect_await_syntax( + pub(super) fn parse_incorrect_await_syntax( &mut self, lo: Span, await_sp: Span, @@ -999,7 +1000,7 @@ impl<'a> Parser<'a> { } /// If encountering `future.await()`, consumes and emits an error. - crate fn recover_from_await_method_call(&mut self) { + pub(super) fn recover_from_await_method_call(&mut self) { if self.token == token::OpenDelim(token::Paren) && self.look_ahead(1, |t| t == &token::CloseDelim(token::Paren)) { @@ -1022,7 +1023,7 @@ impl<'a> Parser<'a> { /// and suggest writing `for $pat in $expr` instead. /// /// This should be called before parsing the `$block`. - crate fn recover_parens_around_for_head( + pub(super) fn recover_parens_around_for_head( &mut self, pat: P, expr: &Expr, @@ -1060,7 +1061,7 @@ impl<'a> Parser<'a> { } } - crate fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool { + pub(super) fn could_ascription_be_path(&self, node: &ast::ExprKind) -> bool { self.token.is_ident() && if let ast::ExprKind::Path(..) = node { true } else { false } && !self.token.is_reserved_ident() && // v `foo:bar(baz)` @@ -1074,7 +1075,7 @@ impl<'a> Parser<'a> { self.look_ahead(2, |t| t == &token::Lt)) // `foo:bar::` } - crate fn recover_seq_parse_error( + pub(super) fn recover_seq_parse_error( &mut self, delim: token::DelimToken, lo: Span, @@ -1091,7 +1092,7 @@ impl<'a> Parser<'a> { } } - crate fn recover_closing_delimiter( + pub(super) fn recover_closing_delimiter( &mut self, tokens: &[TokenKind], mut err: DiagnosticBuilder<'a>, @@ -1142,7 +1143,7 @@ impl<'a> Parser<'a> { } /// Recovers from `pub` keyword in places where it seems _reasonable_ but isn't valid. - crate fn eat_bad_pub(&mut self) { + pub(super) fn eat_bad_pub(&mut self) { if self.token.is_keyword(kw::Pub) { match self.parse_visibility(false) { Ok(vis) => { @@ -1160,7 +1161,7 @@ impl<'a> Parser<'a> { /// statement. This is something of a best-effort heuristic. /// /// We terminate when we find an unmatched `}` (without consuming it). - crate fn recover_stmt(&mut self) { + pub(super) fn recover_stmt(&mut self) { self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore) } @@ -1171,7 +1172,7 @@ impl<'a> Parser<'a> { /// /// If `break_on_block` is `Break`, then we will stop consuming tokens /// after finding (and consuming) a brace-delimited block. - crate fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) { + pub(super) fn recover_stmt_(&mut self, break_on_semi: SemiColonMode, break_on_block: BlockMode) { let mut brace_depth = 0; let mut bracket_depth = 0; let mut in_block = false; @@ -1239,7 +1240,7 @@ impl<'a> Parser<'a> { } } - crate fn check_for_for_in_in_typo(&mut self, in_span: Span) { + 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`") @@ -1253,14 +1254,14 @@ impl<'a> Parser<'a> { } } - crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, T> { + pub(super) fn expected_semi_or_open_brace(&mut self) -> PResult<'a, T> { let token_str = self.this_token_descr(); let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str)); err.span_label(self.token.span, "expected `;` or `{`"); Err(err) } - crate fn eat_incorrect_doc_comment_for_param_type(&mut self) { + pub(super) fn eat_incorrect_doc_comment_for_param_type(&mut self) { if let token::DocComment(_) = self.token.kind { self.struct_span_err( self.token.span, @@ -1288,7 +1289,7 @@ impl<'a> Parser<'a> { } } - crate fn parameter_without_type( + pub(super) fn parameter_without_type( &mut self, err: &mut DiagnosticBuilder<'_>, pat: P, @@ -1351,7 +1352,7 @@ impl<'a> Parser<'a> { None } - crate fn recover_arg_parse(&mut self) -> PResult<'a, (P, P)> { + pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P, P)> { let pat = self.parse_pat(Some("argument name"))?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; @@ -1379,7 +1380,7 @@ impl<'a> Parser<'a> { Ok((pat, ty)) } - crate fn recover_bad_self_param( + pub(super) fn recover_bad_self_param( &mut self, mut param: ast::Param, is_trait_item: bool, @@ -1397,7 +1398,7 @@ impl<'a> Parser<'a> { Ok(param) } - crate fn consume_block(&mut self, delim: token::DelimToken) { + pub(super) fn consume_block(&mut self, delim: token::DelimToken) { let mut brace_depth = 0; loop { if self.eat(&token::OpenDelim(delim)) { @@ -1417,7 +1418,7 @@ impl<'a> Parser<'a> { } } - crate fn expected_expression_found(&self) -> DiagnosticBuilder<'a> { + pub(super) fn expected_expression_found(&self) -> DiagnosticBuilder<'a> { let (span, msg) = match (&self.token.kind, self.subparser_name) { (&token::Eof, Some(origin)) => { let sp = self.sess.source_map().next_point(self.token.span); @@ -1462,7 +1463,7 @@ impl<'a> Parser<'a> { /// the parameters are *names* (so we don't emit errors about not being able to find `b` in /// the local scope), but if we find the same name multiple times, like in `fn foo(i8, i8)`, /// we deduplicate them to not complain about duplicated parameter names. - crate fn deduplicate_recovered_params_names(&self, fn_inputs: &mut Vec) { + pub(super) fn deduplicate_recovered_params_names(&self, fn_inputs: &mut Vec) { let mut seen_inputs = FxHashSet::default(); for input in fn_inputs.iter_mut() { let opt_ident = if let (PatKind::Ident(_, ident, _), TyKind::Err) = ( diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 6e52a07c61d8..2e6b9de7693d 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1074,7 +1074,7 @@ impl<'a> Parser<'a> { } /// Matches `lit = true | false | token_lit`. - crate fn parse_lit(&mut self) -> PResult<'a, Lit> { + pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { let mut recovered = None; if self.token == token::Dot { // Attempt to recover `.4` as `0.4`. @@ -1253,7 +1253,7 @@ impl<'a> Parser<'a> { } /// Parses a block or unsafe block. - crate fn parse_block_expr( + pub(super) fn parse_block_expr( &mut self, opt_label: Option