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 @@ fn from(p: Cow<'a, Path>) -> Self { #[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 @@ fn from(s: PathBuf) -> 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 @@ fn from(s: &Path) -> 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 @@ fn from(s: PathBuf) -> 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 @@ pub fn unwrap_or_default(self) -> T { } } -#[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 @@ #![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 @@ pub fn send_to(&self, buf: &[u8], addr: A) /// # 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 @@ pub fn send_to(&self, buf: &[u8], addr: A) /// [`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::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::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 @@ pub fn __rust_begin_short_backtrace(f: F) -> T 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 @@ pub unsafe fn spawn_unchecked<'a, F, T>(self, f: F) -> io::Result> } 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 @@ pub fn send_to(&self, buf: &[u8], addr: A) /// 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 @@ macro_rules! vector_types { 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 @@ fn codegen_intrinsic_call( 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 @@ fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value { 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 @@ fn do_call<'c, 'b, Bx: BuilderMethods<'b, '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 @@ fn codegen_switchint_terminator<'b>( 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 @@ fn codegen_switchint_terminator<'b>( ); 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 @@ fn codegen_drop_terminator<'b>( 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 @@ fn codegen_drop_terminator<'b>( 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 @@ fn codegen_assert_terminator<'b>( // 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 @@ fn codegen_assert_terminator<'b>( // 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 @@ fn codegen_assert_terminator<'b>( 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 @@ fn codegen_call_terminator<'b>( 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 @@ fn codegen_call_terminator<'b>( 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 @@ fn codegen_call_terminator<'b>( 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 @@ fn codegen_call_terminator<'b>( ); } 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 @@ fn codegen_call_terminator<'b>( } 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 @@ fn codegen_call_terminator<'b>( _ => 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 @@ fn codegen_terminator( } 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 @@ pub fn codegen_rvalue_operand( }; 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 @@ fn codegen_intrinsic_call( 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 @@ fn drop(&mut self) { 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 @@ fn parse_symbol_mangling_version( "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 @@ fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value { } 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 @@ fn maybe_sideeffect<'b, 'tcx2: 'b, Bx: BuilderMethods<'b, 'tcx2>>( 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 @@ fn drop(&mut self) { 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 @@ fn codegen_intrinsic_call( 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 @@ fn codegen_drop_terminator<'b>( 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 @@ fn codegen_assert_terminator<'b>( 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 @@ fn codegen_call_terminator<'b>( 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 @@ fn codegen_call_terminator<'b>( _ => 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 @@ pub fn codegen_rvalue_operand( }; 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 @@ fn expr_as_rvalue( expr_span, scope, result, - expr.ty, ); } @@ -569,7 +568,6 @@ fn limit_capture_mutability( 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 @@ fn expr_as_temp( 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 @@ pub fn storage_live_binding( 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 @@ fn args_and_body(&mut self, // 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 @@ 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 @@ pub fn schedule_drop_storage_and_value( 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 @@ fn add_test(&mut self, test: String, config: LangString, line: usize) { // 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 @@ fn write_result( 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 @@ 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 @@ pub fn new( 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 @@ pub fn output_location(&self) -> &OutputLocation { &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 @@ pub fn write_short_result( &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 @@ pub fn write_plain>(&mut self, s: S) -> io::Result<()> { 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 @@ pub fn write_successes(&mut self, state: &ConsoleTestState) -> io::Result<()> { 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 @@ fn write_result( } 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 @@ fn write_run_finish(&mut self, state: &ConsoleTestState) -> io::Result { } 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 @@ fn write_result( ) -> 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::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 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 @@ pub fn new(opts: &TestOpts) -> io::Result { metrics: MetricMap::new(), failures: Vec::new(), not_failures: Vec::new(), + time_failures: Vec::new(), options: opts.options, }) } @@ -831,11 +1048,12 @@ pub fn write_log_result(&mut self,test: &TestDesc, 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 @@ fn callback( 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 @@ fn callback( 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 @@ fn run_test_inner( } } + 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 @@ fn run_test_inner( }; run_test_inner( desc, - opts.nocapture, - opts.report_time, strategy, monitor_ch, Box::new(move || __rust_begin_short_backtrace(f)), @@ -1548,12 +1780,10 @@ fn run_test_inner( } 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 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 @@ fn new() -> 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 @@ fn f() { ignore: true, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -81,6 +85,7 @@ fn f() {} ignore: true, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -101,6 +106,7 @@ fn f() { ignore: false, should_panic: ShouldPanic::Yes, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -121,6 +127,7 @@ fn f() { 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 f() { ignore: false, should_panic: ShouldPanic::YesWithMessage(expected), allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -161,6 +169,7 @@ fn f() {} ignore: false, should_panic: ShouldPanic::Yes, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(f)), }; @@ -178,11 +187,18 @@ fn f() {} 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 @@ fn tests() -> Vec { ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(move || {})), }) @@ -416,6 +525,7 @@ fn testfn() {} ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }, testfn: DynTestFn(Box::new(testfn)), }; @@ -492,6 +602,7 @@ fn f(_: &mut Bencher) {} ignore: false, should_panic: ShouldPanic::No, allow_fail: false, + test_type: TestType::Unknown, }; crate::bench::benchmark(desc, tx, true, f); @@ -511,6 +622,7 @@ fn f(b: &mut Bencher) { 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 @@ 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 + let mut durations = durations_str .splitn(2, ',') .map(|v| { u64::from_str(v).unwrap_or_else(|_| { @@ -499,18 +499,20 @@ pub fn from_env_var(env_var_name: &str) -> Option { 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 @@ pub fn from_env_var(env_var_name: &str) -> Option { /// 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 @@ pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsR 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 @@ fn intern_with, F: FnOnce(&[T]) -> R>(iter: I, f: F) -> S 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 @@ impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { 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 @@ pub(in crate::foo) struct Bar { // 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 @@ macro_rules! report_function { } } - 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 @@ macro_rules! report_function { } } - 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 @@ pub fn is_phantom_data(&self) -> bool { #[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 @@ macro_rules! report_function { } } - 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 @@ macro_rules! report_function { } 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 @@ 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 } + 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 @@ pub fn set(&self, features: &mut Features, span: Span) { /// 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 @@ macro_rules! gate_all { 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 @@ fn recover_incorrect_vis_restriction(&mut self) -> PResult<'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 @@ fn parse_item_implementation( } 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 @@ fn parse_item_implementation( 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 @@ fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { 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 @@ fn parse_item_foreign_mod( // 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 @@ 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 @@ pub fn into_vec(self: Box) -> Vec { /// 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 @@ fn parse_item_implementation( ); } 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, Layou }); (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::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 @@ pub fn mplace_field( 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 @@ fn check_access_permissions( 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 @@ fn start_block_effect(&self, _sets: &mut BitSet) { 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 @@ fn statement_effect(&self, } } - 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 @@ 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 @@ pub fn into_inner(self) -> T { } } +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 @@ fn from_iter>(iter: T) -> HashMap { } } +/// 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 drop(&mut self) { 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 drop(&mut self) { 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 @@ pub fn maybe_annotate_with_ascription( } /// 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 @@ pub fn maybe_annotate_with_ascription( *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 @@ pub(super) fn parse_assoc_expr_with( 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 @@ pub fn maybe_annotate_with_ascription( ); 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 @@ pub fn maybe_annotate_with_ascription( 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 @@ pub fn maybe_annotate_with_ascription( ))); } } 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: 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 @@ pub fn maybe_annotate_with_ascription( 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 @@ pub fn maybe_annotate_with_ascription( ); let snapshot = self.clone(); + self.bump(); // `(` // Consume the fn call arguments. let modifiers = vec![ @@ -608,7 +648,6 @@ pub fn maybe_annotate_with_ascription( (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 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 @@ pub fn maybe_annotate_with_ascription( /// 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 @@ pub fn maybe_annotate_with_ascription( ); 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::` - 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 @@ pub fn maybe_annotate_with_ascription( 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 @@ pub fn maybe_annotate_with_ascription( } 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: 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 @@ fn f() {} 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 @@ pub fn maybe_annotate_with_ascription( "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 @@ pub fn maybe_annotate_with_ascription( (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 @@ pub fn maybe_annotate_with_ascription( 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 @@ pub fn maybe_annotate_with_ascription( // 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 @@ pub fn maybe_annotate_with_ascription( (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 @@ pub fn maybe_annotate_with_ascription( // 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 @@ pub fn maybe_annotate_with_ascription( 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: 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 @@ pub fn tool_only_multipart_suggestion( /// * 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 @@ pub fn span_suggestion(&mut self, sp: Span, msg: &str, 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 @@ fn primary_span_formatted<'a>( // 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 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 @@ pub fn maybe_annotate_with_ascription( ); let suggest = |err: &mut DiagnosticBuilder<'_>| { - err.span_suggestion( + err.span_suggestion_verbose( op_span.shrink_to_lo(), TURBOFISH, "::".to_string(), @@ -647,29 +646,16 @@ pub fn maybe_annotate_with_ascription( // 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 @@ pub fn maybe_annotate_with_ascription( 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::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 @@ fn with_task_impl<'a, C, A, R>( // - 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 @@ fn with_task_impl<'a, C, A, R>( }) }; - 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 @@ fn parse_symbol_mangling_version( "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::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::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 @@ pub fn time_passes(&self) -> bool { 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 @@ fn encode_query_results<'a, 'tcx, Q, E>( 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::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 @@ fn default() -> 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 @@ pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob< 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 @@ pub(super) fn get_query>(self, span: Span, key: Q::Key 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 @@ pub(super) fn get_query>(self, span: Span, key: Q::Key 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 @@ pub(super) fn get_query>(self, span: Span, key: Q::Key }); drop(prof_timer); - profq_msg!(self, ProfileQueriesMsg::ProviderEnd); self.dep_graph.read_index(dep_node_index); @@ -468,7 +429,6 @@ fn load_from_disk_and_cache_in_memory>( }; 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 @@ fn force_query_with_job>( - 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 @@ fn force_query_with_job>( }); 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 @@ pub(super) fn ensure_query>(self, key: Q::Key) -> () { 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::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 @@ 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 @@ unsafe fn with_codegen<'ll, F, R>(tm: &'ll llvm::TargetMachine, 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_static_crate<'a, B: ArchiveBuilder<'a>>(cmd: &mut dyn Linker, 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 @@ pub fn run_compiler_in_existing_thread_pool(config: Config, f: F) -> R 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 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 @@ pub fn span_suggestion( 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 @@ pub fn span_suggestion( }], }], msg: msg.to_owned(), - style: SuggestionStyle::ShowCode, + style, applicability, }); self @@ -326,17 +344,13 @@ pub fn span_suggestion_verbose( 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 @@ pub fn span_suggestions( 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 @@ pub fn span_suggestion_short( 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 @@ pub fn span_suggestion_hidden( 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 @@ fn primary_span_formatted<'a>( 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 range_borders(r: IntRange<'_>) -> impl Iterator { 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 @@ fn from_ctor( ) -> 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 @@ fn from_pat( 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 @@ pub fn to_bits_or_ptr( } } + #[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 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::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 @@ pub fn try_eval_bits( 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 @@ fn is_integral(ty: Ty<'_>) -> bool { } } + #[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 @@ fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Lo }; 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 @@ fn check_call_dest( 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::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 @@ pub fn as_closure(&'a self) -> ClosureSubsts<'a> { } } + /// 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 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { // 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 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'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 @@ pub fn ty(&self, local_decls: &D, tcx: TyCtxt<'tcx>) -> Ty<'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 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Vec> { .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 @@ fn confirm_generator_candidate( )?); Ok(VtableGeneratorData { - generator_def_id: generator_def_id, - substs: substs.clone(), + generator_def_id, + substs, nested: obligations, }) } @@ -3911,9 +3912,9 @@ fn generator_trait_ref_unnormalized( &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 @@ pub fn mk_closure(self, closure_id: DefId, closure_substs: SubstsRef<'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 @@ fn add_kind(&mut self, kind: &ty::TyKind<'_>) { &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 @@ fn fn_sig_noadjust(&self, tcx: TyCtxt<'tcx>) -> PolyFnSig<'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 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 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, Layou 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 @@ fn generator_layout( &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 @@ fn generator_layout( // 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 @@ fn field(this: TyLayout<'tcx>, cx: &C, i: usize) -> C::TyLayout { 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 @@ fn field(this: TyLayout<'tcx>, cx: &C, i: usize) -> C::TyLayout { 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 @@ pub fn push_outlives_components(&self, ty0: Ty<'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 @@ pub fn push_type_name(&self, t: Ty<'tcx>, output: &mut String, debug: bool) { 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 @@ fn pretty_print_type( } 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 @@ pub fn tuple_fields(&self) -> impl DoubleEndedIterator> { 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 @@ pub fn discriminant_for_variant( 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 @@ pub fn discriminant_for_variant( 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 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'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::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::{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 @@ fn generator_layout( 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 @@ fn generator_layout( .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 @@ 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.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 @@ fn visit_substs(&mut self, 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 @@ fn super_rvalue(&mut self, generator_substs, _movability, ) => { - self.visit_generator_substs(generator_substs, location); + self.visit_substs(generator_substs, location); } } @@ -846,10 +840,6 @@ fn super_const(&mut self, _const: & $($mutability)? &'tcx ty::Const<'tcx>) { 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 @@ pub fn discriminant_for_variant( /// variant indices. #[inline] pub fn discriminants( - &'tcx self, + self, def_id: DefId, tcx: TyCtxt<'tcx>, ) -> impl Iterator)> + Captures<'tcx> { @@ -524,7 +524,7 @@ pub fn discriminants( /// 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 @@ pub fn prefix_tys(self, def_id: DefId, tcx: TyCtxt<'tcx>) -> impl Iterator { Closure(SubstsRef<'tcx>), - Generator(GeneratorSubsts<'tcx>), + Generator(SubstsRef<'tcx>), } impl<'tcx> UpvarSubsts<'tcx> { @@ -582,7 +582,7 @@ pub fn upvar_tys( ) -> 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 @@ pub fn as_closure(&'a self) -> ClosureSubsts<'a> { /// 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::{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 @@ fn create_member_descriptions(&self, cx: &CodegenCx<'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 @@ fn map_struct_name(&self, f: impl FnOnce(&str) -> R) -> R { 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 @@ fn print_type( 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 @@ fn print_type( 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 @@ 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 @@ fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) { 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 @@ fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) { 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 @@ fn field_ty( 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 @@ fn field_ty( 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 @@ fn aggregate_field_ty( // 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 @@ fn prove_aggregate_predicates( // 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::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 @@ pub fn upvar_tys(self, tcx: TyCtxt<'tcx>) -> impl Iterator> + 't 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 @@ pub fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { 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 @@ fn build(self) -> UniversalRegions<'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 @@ fn compute_indices( 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 @@ fn compute_inputs_and_output( 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 @@ fn print_type(mut self, ty: Ty<'tcx>) -> Result { | 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 @@ pub fn read_discriminant( 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 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<' // 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 @@ fn open_drop(&mut self) -> BasicBlock { // 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 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 @@ fn check_closure( } }); 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 @@ pub(super) fn eval_static_to_mplace( 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 @@ impl Unsigned for U8 { 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 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 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 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 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 @@ fn foo() {} 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 @@ fn main() { [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 @@ fn main() { 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 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 @@ pub fn is_char_boundary(&self, index: usize) -> bool { #[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 @@ pub 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(|| { - 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 @@ pub fn ast_block(&mut self, 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 @@ fn ast_block_stmts(&mut self, 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 @@ fn expr_as_rvalue( 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 @@ fn expr_as_temp( } } - 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 @@ 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 @@ pub fn into_expr( _ => 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 @@ pub fn into_expr( } => { 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 @@ pub fn into_expr( // 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( // 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( 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 @@ fn eval_into( 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 @@ fn eval_into( 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 @@ fn eval_into( 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 @@ pub fn match_expr( }; // 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 @@ pub fn match_expr( 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 @@ pub(super) fn expr_into_pattern( } => { 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 @@ pub(super) fn expr_into_pattern( }, ); - self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } @@ -352,9 +362,10 @@ pub(super) fn expr_into_pattern( 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 @@ pub(super) fn expr_into_pattern( }, ); - 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 @@ fn construct_fn<'a, 'tcx, A>( 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 @@ fn construct_fn<'a, 'tcx, A>( 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 @@ fn args_and_body(&mut self, } 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 @@ pub fn break_scope( 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 @@ pub fn schedule_drop( 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 @@ pub fn schedule_drop( self.arg_count, ) } + false } - } + }; for scope in self.scopes.iter_mut() { let this_scope = scope.region_scope == region_scope; @@ -1068,6 +1070,18 @@ pub fn assert(&mut self, block: BasicBlock, 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 @@ fn drop(&mut self) { // // 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 @@ fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { /// 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 @@ fn fallible_operation(&self) { // 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 @@ fn run_test(cx: &mut Context<'_>, ref f: F) // 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 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 @@ fn alloc(&self) -> Ptr<'_> { 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 @@ fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) { 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 @@ fn parse_symbol_mangling_version( 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 @@ pub fn puts(&mut self, line: usize, col: usize, string: &str, style: Style) { 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::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 @@ fn recover_mut_ref_ident(&mut self, lo: Span) -> PResult<'a, PatKind> { 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 @@ pub fn new(cgcx: &'a CodegenContext, 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 @@ fn codegen_static( 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 @@ fn codegen_static( 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 @@ pub fn now() -> 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 @@ pub fn now() -> 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 @@ pub fn duration(&self) -> Duration { #[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 @@ fn from_inner(time: time::SystemTime) -> 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 @@ fn instant_checked_duration_since_nopanic() { 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 @@ fn system_time_math() { 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 @@ fn check_type_for_ffi(&self, }; } + 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 @@ fn check_type_for_ffi(&self, } } + 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 @@ fn size_hint(&self) -> (usize, Option) { 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::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 @@ pub fn items(&self, tcx: TyCtxt<'tcx>) -> ty::AssocItemsIterator<'tcx> { 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 @@ pub fn def_id(&self) -> DefId { } } +#[derive(Copy, Clone)] pub struct Ancestors<'tcx> { trait_def_id: DefId, specialization_graph: &'tcx Graph, @@ -465,32 +494,18 @@ pub fn map U>(self, f: F) -> 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 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 @@ pub fn impl_is_default(self, node_item_def_id: DefId) -> bool { } } - 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 @@ impl<'a, I, T: 'a> Iterator for Cloned 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 @@ fn bar(&self) -> i32 { 0 } // / \ // 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 @@ pub fn item( | (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 @@ fn size_hint(&self) -> (usize, Option) { 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 @@ fn foo(&self) -> bool { true } // 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 @@ pub fn join( 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::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 @@ pub fn name(&self) -> Option { } } -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 @@ fn lookup_import_candidates_from_module(&mut self, 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 @@ fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion // 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 @@ fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion 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 @@ fn for_each_child(&'a self, resolver: &mut R, mut f: F) } } - 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 @@ struct Flags: u8 { 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 @@ fn maybe_collect_in_band_lifetime(&mut self, ident: Ident) { /// 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 @@ macro_rules! report_function { } 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 @@ macro_rules! report_function { 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 @@ macro_rules! report_function { 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 @@ pub fn check_ref( // 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 @@ fn check_expr_meets_expectation_or_error( } 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 @@ pub fn cargo( 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 @@ fn run(self, builder: &Builder<'_>) { // 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 drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { // 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 @@ fn simple_unicode() { } #[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 drop(&mut self) { } } -// 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// 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 @@ pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, '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 @@ fn set_flags(&mut self, sess: &Session, no_builtins: bool) { // 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 @@ mod aarch64; mod amdgpu; mod arm; +mod asmjs; mod hexagon; mod mips; mod mips64; @@ -21,7 +22,6 @@ 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 @@ pub fn adjust_for_cabi(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), "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 @@ pub fn adjust_for_cabi(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), "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 @@ fn $module() { ("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 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { ("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 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 @@ fn f() {} 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 f() { 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 f() { 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 f() { 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 @@ // 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 @@ pub struct i8x16( // 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 @@ pub fn from_file(config: &Config, testfile: &Path) -> Self { 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 @@ fn push_ty_ref<'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 @@ fn lifetime_display(lifetime: Region<'_>) -> String { // ^ 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 @@ fn lifetime_display(lifetime: Region<'_>) -> String { 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 @@ fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef { 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 @@ fn clean(&self, cx: &DocContext<'_>) -> Item { 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 @@ fn clean(&self, cx: &DocContext<'_>) -> Type { } 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 @@ fn clean(&self, cx: &DocContext<'_>) -> Type { 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 @@ fn rust_input(options: config::Options, f: F) -> R 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 @@ struct SomeStruct { ``` "##, +// 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 @@ fn foo() {} ``` "##, +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 @@ fn foo() {} ``` "##, -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 @@ extern "C" fn foo(userdata: Box) { [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 @@ pub fn new(prev_graph: PreviousDepGraph, 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 @@ pub fn exec_cache_promotions(&self, tcx: TyCtxt<'_>) { } } } - - 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 @@ fn load_from_disk_and_cache_in_memory>( 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 @@ fn force_query_with_job>( 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 @@ fn main() { 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 @@ fn foo(){} 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 @@ fn main() { 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 @@ fn find_loop_head_dfs( /// 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 @@ pub fn new(x: T) -> 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 @@ fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I) 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 @@ fn debug_dump<'a, 'tcx, I>(tcx: TyCtxt<'tcx>, label: &str, cgus: I) 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 @@ macro_rules! force_ex { } }; - 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 @@ macro_rules! force { 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 @@ macro_rules! def_id { } }; - macro_rules! krate { - () => { (def_id!()).krate } - }; - macro_rules! force_ex { ($tcx:expr, $query:ident, $key:expr) => { { @@ -1236,7 +1232,7 @@ macro_rules! force_ex { 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 @@ macro_rules! force_ex { 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 @@ macro_rules! force_ex { // 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::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 @@ fn parse_impl_item_(&mut self, }; (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 @@ fn is_const_item(&self) -> bool { !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 @@ pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> 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 @@ fn parse_trait_item_(&mut self, // 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 @@ fn parse_trait_item_(&mut self, }) } + 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 @@ fn parse_trait_method_body( /// 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( ) .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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( ); } let abi = self.parse_extern_abi()?; - self.bump(); // 'fn' + self.bump(); // `fn` let header = FnHeader { unsafety, @@ -181,7 +181,8 @@ fn parse_item_implementation( ) .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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( 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 @@ fn parse_item_implementation( }; 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 @@ fn parse_item_implementation( }; 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 @@ fn parse_item_implementation( 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 @@ fn mk_item_with_info( 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 @@ fn parse_item_fn( 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 @@ fn parse_item_implementation( { // 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 @@ fn parse_item_implementation( && 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 @@ fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { 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 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 @@ struct Restrictions: u8 { 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 @@ fn with_res(&mut self, res: Restrictions, f: impl FnOnce(&mut Self) -> T) -> 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 @@ fn parse_fn_params( } })?; - 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 @@ fn parse_fn_params( 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 @@ fn parse_impl_method( /// 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 @@ fn parse_item_fn( 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 @@ fn parse_item_foreign_fn( 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::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 @@ fn parse_ty_bare_fn(&mut self, generic_params: Vec) -> PResult<'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 @@ 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 @@ fn visit_item(&mut self, it: &'tcx hir::Item) { "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 @@ fn register_native_lib(&mut self, span: Option, lib: NativeLibrary) { 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 @@ pub fn set(&self, features: &mut Features, span: Span) { /// 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 @@ macro_rules! experimental { "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 @@ link_cfg, link_llvm_intrinsics, link_name, + link_ordinal, link_section, LintPass, lint_reasons, @@ -531,6 +532,7 @@ 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 @@ pub fn new() -> 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 @@ fn register_native_lib(&mut self, span: Option, lib: NativeLibrary) { 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 fn set(&self, features: &mut Features, span: Span) { 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 @@ macro_rules! experimental { 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::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 @@ fn parse_ty_bare_fn(&mut self, generic_params: Vec) -> PResult<'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 @@ fn parse_use_tree(&mut self) -> PResult<'a, UseTree> { ); } - 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 @@ fn parse_use_tree(&mut self) -> PResult<'a, UseTree> { 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 @@ pub fn set(&self, features: &mut Features, span: Span) { (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 @@ macro_rules! tidy_error { 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 @@ impl<'a, T> SomeTrait<'a> for T "##, 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 @@ fn foo(){} // 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 @@ fn foo(){} 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 @@ fn mutable() { "##, 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 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 @@ struct SomeStruct { 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 @@ pub fn bar() -> Bar { // ok! 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 @@ fn foo() { "##, 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 @@ struct Foo<'a> { 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 @@ impl Copy for Foo { } 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 @@ impl ForeignTrait for T0 { ... } [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 @@ fn x(self: Rc) {} } ``` -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 @@ fn x(self: Box) {} // ok! } ``` "##, - */ 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 @@ fn foo_recursive(n: usize) -> Pin>> { // 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 @@ fn foo_recursive(n: usize) -> Pin>> { 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 @@ async fn foo() {} ; 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 @@ fn add_const(&mut self, c: &ty::Const<'_>) { 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 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { } 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 @@ pub fn to_opt_closure_kind(&self) -> Option { _ => 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 @@ fn pretty_print_type( 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 @@ fn pretty_print_type( }, 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 @@ fn pretty_print_const( ) -> 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 @@ impl Foo { 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 @@ fn check_attributes(&self, item: &hir::Item, target: Target) { 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 @@ fn check_attributes(&self, item: &hir::Item, target: Target) { 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 @@ fn check_inline(&self, attr: &hir::Attribute, span: &Span, target: Target) -> bo } } + /// 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 @@ pub struct CodegenFnAttrFlags: u32 { 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 @@ pub fn set(&self, features: &mut Features, span: Span) { // 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 @@ macro_rules! experimental { 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 @@ 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 @@ impl Foo { "##, 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::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 @@ fn check_attributes(&self, item: &hir::Item, target: 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 @@ -122,19 +120,6 @@ fn check_attributes(&self, item: &hir::Item, target: Target) { 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 @@ fn check_inline(&self, attr: &hir::Attribute, span: &Span, target: Target) -> bo } } - /// 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 @@ fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Ta .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 @@ fn foo_recursive(n: usize) -> Pin>> { "##, 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 @@ pub fn set(&self, features: &mut Features, span: Span) { (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 @@ macro_rules! experimental { ), 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 @@ macro_rules! experimental { 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 @@ pub fn set(&self, features: &mut Features, span: Span) { (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 fn set(&self, features: &mut Features, span: Span) { 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 @@ impl Foo { 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 @@ fn foo(){} 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 @@ fn foo(){} 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 @@ fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Ta 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 @@ fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Ta 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 @@ fn foo_recursive(n: usize) -> Pin>> { 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 @@ fn foo(){} 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 @@ fn check_track_caller(&self, attr: &hir::Attribute, item: &hir::Item, target: Ta 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 @@ fn foo(){} 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 @@ fn foo_recursive(n: usize) -> Pin>> { "##, 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 @@ fn bar(&self) {} 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 @@ impl<'a, T> SomeTrait<'a> for T ``` "##, +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 @@ fn foo(){} 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 @@ fn c(t: &T) -> T { t.clone() } #[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 @@ 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 @@ macro_rules! describe { 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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { 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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { 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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { 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 @@ macro_rules! describe { 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 @@ fn run(self, builder: &Builder<'_>) { } } +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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { 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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { 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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { 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 @@ 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)); + 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 @@ fn build_manifest(&mut self) -> Manifest { 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 @@ fn target_host_combination(&mut self, host: &str, manifest: &Manifest) -> Option // 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 @@ fn target_host_combination(&mut self, host: &str, manifest: &Manifest) -> Option .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 @@ fn target_host_combination(&mut self, host: &str, manifest: &Manifest) -> Option // 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 @@ fn target_host_combination(&mut self, host: &str, manifest: &Manifest) -> Option 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 @@ fn add_profiles_to(&mut self, manifest: &mut Manifest) { "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 @@ fn profile(&mut self, 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 @@ macro_rules! report_function { } } + 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; 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 @@ pub fn from_parser_lint_id(lint_id: BufferedEarlyLintId) -> &'static Self { 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 @@ 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::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 @@ struct ExpandResult<'a> { } 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 @@ fn commit_from(&self, snapshot: CombinedSnapshot<'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 @@ pub fn commit_if_ok(&self, f: F) -> Result 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 @@ fn collect_predicates_for_types( // 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 @@ fn confirm_candidate( } 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 @@ fn vtable_auto_impl( 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 @@ fn confirm_impl_candidate( // 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 @@ fn confirm_trait_alias_candidate( 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 @@ pub fn is_empty(&self) -> bool { 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 @@ pub fn map TokenTree>(self, mut f: F) -> 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 @@ pub fn new() -> 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 @@ pub fn push>(&mut self, stream: T) { 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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { .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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { } } - // 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 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough( 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 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough( 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 @@ fn report_escaping_closure_capture( 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 @@ 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 @@ fn main() { ``` "##, +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 @@ async fn foo() {} ; 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 @@ pub fn is_place_expr(&self) -> bool { } } } + + /// 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 @@ pub fn check_ref( }; 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 @@ pub fn demand_coerce_diag(&self, 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 @@ fn check_expr_meets_expectation_or_error( } 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 @@ pub fn get_fn_decl(&self, blk_id: hir::HirId) -> Option<(&'tcx hir::FnDecl, bool 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::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 @@ pub fn unwrap_memory(&self, id: AllocId) -> &'tcx Allocation { } } + /// 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 @@ fn pretty_print_const( 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::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 @@ fn call() -> u32 { 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 @@ fn pretty_print_const( } 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 @@ fn get() -> u32 { 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 @@ 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 @@ pub fn is_place_expr(&self) -> bool { /// `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 @@ pub fn demand_coerce_diag(&self, 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 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 @@ enum PatBoundCtx { 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 @@ fn visit_poly_trait_ref(&mut self, 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 @@ fn search_label(&self, mut ident: Ident, pred: P) -> Option 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 @@ fn resolve_item(&mut self, item: &Item) { 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 @@ fn resolve_item(&mut self, item: &Item) { 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 @@ fn resolve_item(&mut self, item: &Item) { 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 @@ fn resolve_item(&mut self, item: &Item) { 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 @@ fn resolve_item(&mut self, item: &Item) { 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 @@ fn resolve_item(&mut self, item: &Item) { } } - 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 @@ fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) { 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 @@ fn resolve_implementation(&mut self, 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 @@ fn resolve_implementation(&mut self, 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 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 @@ fn cmp(&self, other: &BindingError) -> cmp::Ordering { 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 @@ fn validate_res_from_ribs( 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 @@ fn validate_res_from_ribs( } 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 @@ fn validate_res_from_ribs( 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 @@ fn default() -> Self { } // 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 @@ fn default() -> 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 @@ pub fn store(&self, val: bool, order: Ordering) { /// ``` #[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 @@ pub fn swap(&self, val: bool, order: Ordering) -> bool { /// ``` #[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 @@ pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> boo /// ``` #[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 @@ pub fn compare_exchange(&self, /// ``` #[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 @@ pub fn compare_exchange_weak(&self, /// ``` #[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 @@ pub fn fetch_and(&self, val: bool, order: Ordering) -> bool { /// ``` #[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 @@ pub fn fetch_nand(&self, val: bool, order: Ordering) -> bool { /// ``` #[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 @@ pub fn fetch_or(&self, val: bool, order: Ordering) -> bool { /// ``` #[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 @@ pub fn store(&self, ptr: *mut T, order: Ordering) { /// ``` #[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 @@ pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T { /// ``` #[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 @@ pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> /// ``` #[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 @@ pub fn compare_exchange(&self, /// ``` #[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 @@ pub fn compare_exchange_weak(&self, } } -#[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 @@ pub fn store(&self, val: $int_type, order: Ordering) { ```"), #[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 @@ pub fn swap(&self, val: $int_type, order: Ordering) -> $int_type { ```"), #[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 @@ pub fn compare_and_swap(&self, ```"), #[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 @@ pub fn compare_exchange(&self, ```"), #[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 @@ pub fn compare_exchange_weak(&self, ```"), #[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 @@ pub fn fetch_add(&self, val: $int_type, order: Ordering) -> $int_type { ```"), #[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 @@ pub fn fetch_sub(&self, val: $int_type, order: Ordering) -> $int_type { ```"), #[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 @@ pub fn fetch_and(&self, val: $int_type, order: Ordering) -> $int_type { ```"), #[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 @@ pub fn fetch_nand(&self, val: $int_type, order: Ordering) -> $int_type { ```"), #[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 @@ pub fn fetch_or(&self, val: $int_type, order: Ordering) -> $int_type { ```"), #[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 @@ pub fn fetch_xor(&self, val: $int_type, order: Ordering) -> $int_type { #[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 @@ pub fn fetch_update(&self, #[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 @@ pub fn fetch_max(&self, val: $int_type, order: Ordering) -> $int_type { #[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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { } } -#[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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ pub fn fetch_min(&self, val: $int_type, order: Ordering) -> $int_type { "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 @@ macro_rules! ptr_width { "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 @@ macro_rules! ptr_width { } #[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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -#[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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -#[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::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 @@ macro_rules! cfg_fn { // (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 @@ 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 @@ pub fn and_modify(self, f: F) -> Self 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 @@ pub fn into_key(self) -> K { 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 @@ #![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 @@ #![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 @@ pub unsafe fn read(&self) { 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 @@ struct TestRunOpts { fn run_test_inner( desc: TestDesc, - strategy: RunStrategy, monitor_ch: Sender, testfn: Box, opts: TestRunOpts, @@ -1747,10 +1747,10 @@ fn run_test_inner( 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 @@ fn run_test_inner( } let test_run_opts = TestRunOpts { + strategy, nocapture: opts.nocapture, concurrency, time: opts.time_options @@ -1792,15 +1793,13 @@ fn run_test_inner( }; 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 f() {} ..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 @@ fn write_result( 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 @@ pub fn from_env_var(env_var_name: &str) -> Option { 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 @@ fn run_test_inner( 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 @@ trait Trait: Super { 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 @@ pub fn is_green(&self, dep_node: &DepNode) -> bool { // 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 @@ pub fn partition<'tcx, I>( // 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 @@ pub fn partition<'tcx, I>( // 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 @@ pub fn partition<'tcx, I>( // 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 @@ fn has_derives(&self, expn_id: ExpnId, markers: SpecialDerives) -> bool { /// 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 @@ pub struct DepNodeIndex { .. } } 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 @@ fn register_crate( }, 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_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 @@ pub fn provide_extern<$lt>(providers: &mut Providers<$lt>) { 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_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 @@ pub fn imported_source_files(&'a self, // 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 @@ fn register_crate( 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 @@ pub fn provide_extern<$lt>(providers: &mut Providers<$lt>) { $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 @@ pub fn item_children_untracked( } 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 @@ fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh /// 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::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 @@ pub fn crate_edition_untracked(&self, cnum: CrateNum) -> Edition { self.get_crate_data(cnum).root.edition } - pub fn struct_field_names_untracked(&self, def: DefId) -> 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 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 @@ pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Att 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::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 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility { } } - 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 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) { } // 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 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) { 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 @@ fn build_reduced_graph_for_external_crate_res(&mut self, child: Export) // 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 @@ fn extract_node_id(t: &Ty) -> Option { 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::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::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 @@ fn report_errors(&mut self, krate: &Crate) { 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 @@ pub fn cargo( 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 @@ fn layout_raw_uncached(&self, ty: Ty<'tcx>) -> Result<&'tcx LayoutDetails, Layou }); (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 @@ fn on_unimplemented_note( } } - 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 @@ fn find_similar_impl_candidates(&self, } } - 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 @@ pub fn report_selection_error( // 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 @@ fn suggest_remove_reference( 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 @@ fn suggest_remove_reference( } } + /// 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 @@ pub fn lookup_method( 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 @@ macro_rules! report_function { 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 @@ macro_rules! report_function { }); 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 @@ fn suggest_change_mut( ); } 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 @@ macro_rules! report_function { 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 @@ fn suggest_change_mut( 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 @@ pub fn evaluate_obligation( // 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 @@ pub fn and(self, other: Self) -> Self { 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 @@ pub fn lookup_method( 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 @@ macro_rules! report_function { 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 @@ pub fn and(self, other: Self) -> Self { } } - 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 @@ pub fn lookup_method( 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 @@ macro_rules! report_function { 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 @@ fn suggest_change_mut( { // 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 @@ fn pretty_print_const( }, (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 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) { 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 @@ fn visit_body(&mut self, body: &'tcx hir::Body) { 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 @@ fn check_match( }) } - 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 @@ fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str) { "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 @@ pub fn ast_block( 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 @@ fn ast_block_stmts( 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 @@ fn expr_as_rvalue( 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 @@ fn expr_as_temp( } } - 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 @@ 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 @@ pub fn into_expr( _ => 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 @@ pub fn into_expr( } => { 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 @@ pub fn into_expr( // 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( // 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( 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 @@ pub fn into_expr( 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 @@ fn eval_into( 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 @@ fn eval_into( 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 @@ fn eval_into( 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 @@ pub fn match_expr( }; // 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 @@ pub fn match_expr( 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 @@ pub(super) fn expr_into_pattern( } => { 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 @@ pub(super) fn expr_into_pattern( }, ); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } @@ -362,10 +352,9 @@ pub(super) fn expr_into_pattern( 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 @@ pub(super) fn expr_into_pattern( }, ); + 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 @@ fn construct_fn<'a, 'tcx, A>( 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 @@ fn construct_fn<'a, 'tcx, A>( 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 @@ fn args_and_body(&mut self, } 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 @@ pub fn break_scope( 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 @@ pub fn assert(&mut self, block: BasicBlock, 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 @@ fn drop(&mut self) { // // 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 @@ fn poll(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll { /// 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 @@ fn fallible_operation(&self) { // 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 @@ fn run_test(cx: &mut Context<'_>, ref f: F, name: &'static str) // 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 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 @@ fn alloc(&self) -> Ptr<'_> { 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 @@ pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut De 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 @@ pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut 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 @@ pub fn entries(&mut self, entries: I) -> &mut 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 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 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 @@ fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey { 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 @@ pub fn def_id(&self) -> DefId { 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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 @@ pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'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 @@ fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { 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 @@ fn super_fold_with>(&self, folder: &mut F) -> Self { 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 @@ fn super_visit_with>(&self, visitor: &mut V) -> bool { 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 @@ fn eval_fn_call( 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 @@ pub fn resolve( 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 @@ pub fn resolve_for_fn_ptr( 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 @@ pub fn codegen_rvalue_operand( 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 @@ pub fn resolve_for_fn_ptr( 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 @@ pub fn cast( 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 @@ fn sub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> bool { /// 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 @@ fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'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 @@ fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'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 @@ fn lub_concrete_regions(&self, a: Region<'tcx>, b: Region<'tcx>) -> Region<'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 @@ fn expand_node( 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 @@ fn enforce_member_constraint( } 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 @@ fn process_edges<'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 @@ fn iterate_until_fixed_point(&self, tag: &str, mut body: F) 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 @@ fn iterate_until_fixed_point(&self, tag: &str, mut body: F) 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 @@ pub fn peel_refs(&'tcx self) -> Ty<'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 @@ pub fn imported_source_files(&'a self, 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 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { 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 @@ pub fn from_matches(matches: &getopts::Matches) -> Result { 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 @@ pub fn extension(&self) -> Option<&OsStr> { /// 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 @@ async fn foo() {} ; 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 @@ pub fn resolve_for_fn_ptr( 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 @@ fn from_inner(fd: c_int) -> 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 @@ pub fn count(&self) -> usize { 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 @@ pub fn id(&self) -> BodyId { 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 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough( .. }, ) 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 @@ pub(super) fn report_borrowed_value_does_not_live_long_enough( }, ) 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 @@ fn try_report_cannot_return_reference_to_local( 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 @@ fn report_escaping_closure_capture( 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 @@ fn report_escaping_closure_capture( }, 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::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 @@ pub(super) fn var_or_use(self) -> Span { } } + 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 @@ pub(super) fn var_span_label( /// 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 @@ pub(super) fn for_closure(&self) -> bool { /// 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 @@ pub(super) fn for_generator(&self) -> bool { /// 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 @@ pub(super) fn move_spans( 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 @@ pub(super) fn borrow_spans(&self, use_span: Span, location: Location) -> UseSpan "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 @@ fn closure_span( 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 @@ fn closure_span( 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 @@ pub fn eval_stability(self, def_id: DefId, id: Option, span: Span) -> Eva /// 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 @@ fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Pat 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 @@ struct Foo { 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 @@ fn foo() {} 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 @@ fn suggest_traits_to_import<'b>( // 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 @@ fn suggest_traits_to_import<'b>( 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 @@ pub fn lookup_method( 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 create_vec_and_test_convert(capacity: usize, offset: usize, len: usize) { } } +#[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 @@ fn try_fold(&mut self, init: B, mut f: F) -> R 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 @@ fn fold(self, mut accum: Acc, mut f: F) -> Acc 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 @@ fn msg_span_from_early_bound_and_free_regions( { 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 @@ fn msg_span_from_early_bound_and_free_regions( { 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 @@ fn msg_span_from_early_bound_and_free_regions( 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::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 @@ fn expand_struct_method_body<'b>(&self, // [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 @@ pub fn resolve_for_fn_ptr( ) -> 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 @@ fn report_errors(&mut self, krate: &Crate) { 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 @@ fn test() { } 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 @@ pub mod n { 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 @@ fn f() { 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 @@ pub fn saturating_abs(self) -> Self { #[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 @@ pub fn seek(&self, pos: SeekFrom) -> io::Result { 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 @@ fn report_errors(&mut self, krate: &Crate) { 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 @@ pub fn new( } } - #[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 @@ pub(super) fn eval_terminator( .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! { 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 @@ fn supplied_sig_of_closure( 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 @@ fn supplied_sig_of_closure( 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 @@ fn deduce_future_output_from_obligations( } 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 @@ pub fn lookup_source_file_idx(&self, pos: BytePos) -> usize { 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 @@ 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 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 @@ pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec(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 @@ fn try_fast_path( 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 @@ fn dtorck_constraint_for_ty<'tcx>( 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 @@ pub fn to_digit(self, radix: u32) -> Option { // 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 @@ pub fn to_digit(self, radix: u32) -> Option { } }; - 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 @@ pub fn escape_default(self) -> EscapeDefault { '\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 @@ pub fn len_utf16(self) -> usize { 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 @@ pub fn encode_utf16(self, dst: &mut [u16]) -> &mut [u16] { *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 @@ pub fn is_alphabetic(self) -> bool { } } - /// 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 @@ pub fn is_lowercase(self) -> bool { } } - /// 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 @@ pub fn is_uppercase(self) -> bool { } } - /// 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 @@ pub fn is_whitespace(self) -> bool { } } - /// 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 @@ pub fn is_alphanumeric(self) -> bool { 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 @@ pub fn is_control(self) -> bool { 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 @@ pub fn is_numeric(self) -> bool { } } - /// 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 @@ pub fn to_lowercase(self) -> ToLowercase { 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// 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 @@ pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos { // 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 @@ macro_rules! describe { 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 @@ fn run(self, builder: &Builder<'_>) { } } -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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { 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 @@ fn run(self, builder: &Builder<'_>) -> PathBuf { 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 @@ fn build_manifest(&mut self) -> Manifest { 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 @@ fn add_profiles_to(&mut self, manifest: &mut Manifest) { "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 @@ fn target_host_combination(&mut self, host: &str, manifest: &Manifest) -> Option 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 @@ fn target_host_combination(&mut self, host: &str, manifest: &Manifest) -> Option .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 @@ fn profile(&mut self, 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; 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 @@ fn nest_tables(&mut self, item_id: NodeId, f: F) 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 @@ 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 @@ fn process_struct( ); } - 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 @@ 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 @@ pub fn maybe_annotate_with_ascription( 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 @@ pub fn maybe_annotate_with_ascription( ";".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 @@ pub fn from_environment() -> 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 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// 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 @@ fn eq(&self, symbol: &Symbol) -> bool { } } -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 @@ pub fn to_string(op: UnOp) -> &'static str { } /// A statement -#[derive(Clone, RustcEncodable, RustcDecodable)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Stmt { pub id: NodeId, pub kind: StmtKind, @@ -865,18 +853,7 @@ pub fn is_expr(&self) -> bool { } } -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 @@ pub fn precedence(&self) -> ExprPrecedence { } } -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 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 @@ pub fn push(&mut self, attrs: &[ast::Attribute]) -> BuilderPush { 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_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 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) { } } 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 @@ pub(crate) fn run

( 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 @@ fn no_questions_in_bounds(&self, bounds: &GenericBounds, where_: &str, is_trait: 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::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 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility { .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 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 @@ fn resolve_path_with_ribs( 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::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 @@ fn smart_resolve_macro_path( 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 @@ fn check_stability_and_deprecation(&self, ext: &SyntaxExtension, path: &ast::Pat } } 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 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 @@ 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 @@ fn eq(&self, symbol: &Symbol) -> bool { } } -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::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 @@ macro_rules! get_meta { 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 @@ macro_rules! get_meta { sess, meta.span(), AttrError::UnknownMetaItem( - mi.path.to_string(), + pprust::path_to_string(&mi.path), &["feature", "reason", "issue", "soft"] ), ); @@ -434,7 +442,8 @@ macro_rules! get_meta { 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::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 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm "`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 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstF 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 @@ pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span 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 @@ fn consume_fn_args(&mut self) -> Result<(), ()> { // 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 @@ fn recover_incorrect_vis_restriction(&mut self) -> PResult<'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 @@ fn parse_assoc_op_cast(&mut self, lhs: P, lhs_span: Span, // 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::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 @@ fn visit_item(&mut self, item: &'a ast::Item) { 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 @@ fn visit_item(&mut self, item: &'a ast::Item) { }; 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 @@ fn visit_item(&mut self, item: &'a ast::Item) { } 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::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 @@ fn from_str(&mut self, src: &str) -> Self::TokenStream { ) } 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_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 @@ pub fn look_ahead(&self, n: usize) -> Option { } } -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 @@ fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> { // 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 @@ fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> { 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 @@ fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> { .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 @@ fn description(&self) -> &str { "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 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 @@ pub fn fewer_names(&self) -> bool { .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 @@ fn from(err: E) -> 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 @@ fn from(err: E) -> Box { #[stable(feature = "rust1", since = "1.0.0")] impl From 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 @@ fn from(str_err: String) -> 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 @@ fn from(err: &str) -> 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 @@ fn description(&self) -> &str { } } } - - 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 @@ fn description(&self) -> &str { } } } - - fn cause(&self) -> Option<&dyn error::Error> { - None - } } #[stable(feature = "mpsc_error_conversions", since = "1.24.0")] @@ -1726,10 +1710,6 @@ fn description(&self) -> &str { } } } - - 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 @@ 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 @@ struct Restrictions: u8 { 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 @@ fn with_res(&mut self, res: Restrictions, f: impl FnOnce(&mut Self) -> T) -> 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 @@ fn parse_item_implementation( 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 @@ fn mk_item_with_info( 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 @@ pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { 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 @@ fn parse_impl_item_(&mut self, (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 @@ fn parse_impl_const(&mut self) -> PResult<'a, (Ident, ImplItemKind, Generics)> { 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 @@ fn parse_trait_item_( // 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 @@ fn parse_trait_item_const(&mut self) -> PResult<'a, (Ident, TraitItemKind, Gener 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 @@ fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> { 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 @@ fn parse_item_foreign_mod( } } - /// 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 @@ fn mk_item(&self, span: Span, ident: Ident, kind: ItemKind, vis: Visibility, }) } } + +/// 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 @@ fn parse_ty_bare_fn(&mut self, generic_params: Vec) -> PResult<'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 @@ fn drop(&mut self) { 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 @@ pub fn bundle(&self) -> &OperandBundleDef<'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 @@ fn new_operand>( 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 @@ 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 @@ fn create_function_debug_context( &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 @@ fn vtables( &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 @@ fn const_struct( 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 @@ pub fn project_index>( // 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 @@ pub fn codegen_rvalue( 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 @@ fn print_version(&self) { 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 @@ fn print(&self, _req: PrintRequest, _sess: &Session) {} 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 @@ fn metadata_loader(&self) -> Box { } 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::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_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_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 @@ fn drop(&mut self) { 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 @@ pub fn bundle(&self) -> &OperandBundleDef<'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 @@ fn new_operand>( 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 @@ 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 @@ fn create_function_debug_context( &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 @@ fn vtables( &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::{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 @@ fn eh_personality(&self) -> &'ll Value { 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 @@ fn eh_unwind_resume(&self) -> &'ll Value { 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::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 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( 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 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 crate::base; use crate::MemFlags; -use crate::callee; use crate::common::{self, RealPredicate, IntPredicate}; use crate::traits::*; @@ -190,7 +189,15 @@ pub fn codegen_rvalue_operand( 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 @@ fn scalar_to_backend( } } 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 @@ fn vtables(&self) -> &RefCell, &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 @@ fn eh_personality(&self) -> &'ll Value { 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 @@ fn eh_unwind_resume(&self) -> &'ll Value { 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 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( 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 @@ fn codegen_drop_terminator<'b>( (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 @@ fn codegen_assert_terminator<'b>( 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 @@ fn codegen_call_terminator<'b>( 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 @@ fn codegen_call_terminator<'b>( 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 @@ pub fn codegen_rvalue_operand( 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 @@ pub fn codegen_rvalue_operand( 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 @@ pub fn codegen_rvalue_operand( } }; 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 @@ fn vtables( &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::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 @@ fn const_struct( } 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 @@ struct InvariantOpaque<'a> { 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 @@ pub fn LLVMStructTypeInContext(C: &'a Context, 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 @@ pub fn LLVMRustDIBuilderCreateDebugLocation(Context: &'a Context, #[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::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::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::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 @@ fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream { 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 @@ macro_rules! op { } 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::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::path::{Path, PathBuf}; use std::str; +use log::info; + #[cfg(test)] mod tests; @@ -407,3 +408,132 @@ pub fn none() -> 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 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } } - -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::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 @@ fn resolve_str_path( 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 @@ fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream { 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 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::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 @@ fn resolve_str_path( 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 @@ fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream { 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 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::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 @@ fn borrow_allows_mutation( 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 @@ fn from_tokens(tokens: &mut iter::Peekable) -> Option 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 @@ fn extract_proc_macro_attr_input(&self, tokens: TokenStream, span: Span) -> Toke } } 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 @@ pub fn parse_attr_item(&mut self) -> PResult<'a, ast::AttrItem> { }; 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 @@ pub fn close_tt(span: Span, delim: DelimToken) -> 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 @@ fn eq(&self, other: &TokenStream) -> bool { } 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 @@ pub fn is_empty(&self) -> bool { // 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 @@ fn semantic_tree(tree: &TokenTree) -> bool { } 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 @@ pub fn push>(&mut self, stream: T) { // 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 @@ fn new(stream: TokenStream) -> Self { } 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 @@ pub fn append(&mut self, new_stream: TokenStream) { 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 @@ fn collect_tokens( // 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 @@ fn collect_tokens( // 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 @@ fn mac_placeholder() -> ast::Mac { 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 @@ fn mac_placeholder() -> ast::Mac { body: expr_placeholder(), guard: None, id, - pat, + pat: pat(), span, is_placeholder: true, } @@ -105,7 +105,7 @@ fn mac_placeholder() -> ast::Mac { id, ident, is_shorthand: false, - pat, + pat: pat(), span, is_placeholder: true, } @@ -124,9 +124,9 @@ fn mac_placeholder() -> ast::Mac { ast::Param { attrs: Default::default(), id, - pat, + pat: pat(), span, - ty, + ty: ty(), is_placeholder: true, } ]), @@ -136,7 +136,7 @@ fn mac_placeholder() -> ast::Mac { 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::source_map::SourceMap; use errors::emitter::HumanReadableErrorType; -use errors::{ColorConfig, FatalError, Handler}; +use errors::{ColorConfig, FatalError, Handler, SourceMapperDyn}; use getopts; @@ -1854,6 +1854,7 @@ pub fn rustc_optgroups() -> Vec { 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::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 @@ fn emit_diagnostic(&mut self, db: &rustc_errors::Diagnostic) { } 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 @@ fn emit_diagnostic(&mut self, db: &Diagnostic) { &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 @@ fn should_show_explain(&self) -> bool { 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 @@ fn should_show_explain(&self) -> bool { /// 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 @@ fn primary_span_formatted<'a>( 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 @@ fn fix_multispan_in_std_macros(&self, } 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 @@ fn emit_suggestion_default( 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 @@ fn emit_suggestion_default( } 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 @@ 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 @@ fn push_trailing(buf: &mut String, 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 @@ fn push_trailing(buf: &mut String, 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 @@ fn emit_artifact_notification(&mut self, path: &Path, artifact_type: &str) { } } + 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 @@ fn span_to_lines(&self, sp: Span) -> FileLinesResult { 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 @@ struct X { 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 @@ struct X { x: (), } ``` "##, +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 @@ struct X { x: (), } ``` "##, +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 @@ pub enum Method { GET, POST } 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 @@ fn main() { 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 @@ fn drop(&mut self) { /* ... */ } 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 @@ fn main() { 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 @@ fn foo(x: Option) { 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 @@ enum Terminator { 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 @@ enum Terminator { 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 @@ struct X { 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 @@ struct X { x: (), } 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 @@ struct Bar {x: u8} E0017: r##" References in statics and constants may only refer to immutable values. + Erroneous code example: ```compile_fail,E0017 @@ -282,24 +292,17 @@ struct Bar {x: u8} 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 @@ fn main() { "##, 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 @@ fn main() { Erroneous code example: -```compile_fail +```compile_fail,E0161 #![feature(box_syntax)] fn main() { @@ -705,7 +728,9 @@ fn foo() -> Box u32> { "##, 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 @@ fn main() { #### 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 @@ fn mutable() { 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 @@ struct Foo { "##, 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 @@ struct Foo { "##, 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 @@ fn you_know_nothing(jon_snow: &mut i32) { 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 @@ fn foo(a: &mut i32) { 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 @@ fn foo(a: &mut i32) { 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 @@ fn main() { 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 @@ fn main() { 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 @@ fn main() { 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 @@ fn main() { 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 @@ fn main() { 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 @@ fn dragoooon(x: &mut isize) { 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 @@ fn dragoooon(x: &mut isize) { 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 @@ fn dragoooon(x: &mut isize) { 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 @@ struct Foo<'a> { 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 @@ struct Foo<'a> { 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 @@ fn main() { 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 @@ pub fn list_metadata(sess: &Session, 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::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 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 @@ fn register_crate( 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 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 @@ // 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 @@ pub fn new(metadata_loader: Box) -> 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 @@ pub(super) fn iter_crate_data(&self, mut i: I) } } - 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 @@ pub(super) fn push_dependencies_in_postorder(&self, 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 @@ pub(super) fn do_postorder_cnums_untracked(&self) -> Vec { 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::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 @@ pub fn export_macros_untracked(&self, cnum: CrateNum) { } } - 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 @@ pub fn struct_field_names_untracked(&self, def: DefId, sess: &Session) -> Vec 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 @@ pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro { 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 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 @@ fn tcx(self) -> Option> { } 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 @@ pub fn decode>(self, meta: M) -> T { } 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 @@ pub fn decode>( } 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 @@ fn specialized_decode(&mut self) -> Result, Self::Error> 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 @@ pub fn get_root(&self) -> CrateRoot<'tcx> { 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 @@ fn def_kind(&self) -> Option { } 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 @@ fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro { &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 @@ pub fn item_name(&self, item_index: DefIndex) -> Symbol { } } - 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 @@ pub fn def_kind(&self, index: DefIndex) -> Option { } } - 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 @@ pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span { ) } - 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 @@ fn get_variant( ) } - 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 @@ pub fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'tcx>) -> &'tcx ty::Adt 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 @@ pub fn get_predicates( 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 @@ pub fn get_predicates_defined_on( 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 @@ pub fn get_super_predicates( 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { } } - 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 @@ pub fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(ast::Name, Option) -> &'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 @@ pub fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] { } /// 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 @@ pub fn get_diagnostic_items( } /// 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 @@ pub fn each_child_of_item(&self, id: DefIndex, mut callback: F, sess: &Sessio } } - 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 @@ pub fn get_optimized_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { }) } - pub fn get_promoted_mir( + crate fn get_promoted_mir( &self, tcx: TyCtxt<'tcx>, id: DefIndex, @@ -936,7 +934,7 @@ pub fn get_promoted_mir( }) } - 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 @@ pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { } } - 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 @@ pub fn get_associated_item(&self, id: DefIndex) -> ty::AssocItem { } } - 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 @@ pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { } } - 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 @@ pub fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { } } - - 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 @@ pub fn get_item_attrs(&self, node_id: DefIndex, sess: &Session) -> Lrc<[ast::Att 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 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option { 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 @@ pub fn get_inherent_implementations_for_type( .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 @@ pub fn get_implementations_for_trait( } } - 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 @@ pub fn get_trait_of_item(&self, id: DefIndex) -> Option { } - 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 @@ pub fn get_native_libraries(&self, sess: &Session) -> Vec { } } - 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 @@ pub fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] { } } - pub fn get_dylib_dependency_formats( + crate fn get_dylib_dependency_formats( &self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(CrateNum, LinkagePreference)] { @@ -1140,7 +1141,7 @@ pub fn get_dylib_dependency_formats( })) } - 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 @@ pub fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::La } } - 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 @@ pub fn get_fn_param_names(&self, id: DefIndex) -> Vec { 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 @@ pub fn exported_symbols( } } - 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 @@ pub fn get_rendered_const(&self, id: DefIndex) -> String { } } - 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 @@ pub fn get_macro(&self, id: DefIndex) -> MacroDef { 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 @@ pub fn asyncness(&self, id: DefIndex) -> hir::IsAsync { } } - 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 @@ pub fn is_foreign_item(&self, id: DefIndex) -> bool { } } - 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 @@ pub fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { } #[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 @@ pub fn def_key(&self, index: DefIndex) -> DefKey { } // 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 @@ pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { /// /// 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::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 @@ pub fn open(filename: Option<&Path>) -> Result { } } - /// 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 @@ pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { }) } - 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 @@ unsafe fn open_internal() -> *mut u8 { 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 @@ pub fn check_for_errors_in(f: F) -> Result where } } - 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 @@ fn GetProcAddress(handle: HMODULE, 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 @@ pub fn open(filename: Option<&OsStr>) -> Result<*mut u8, String> { 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::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 @@ fn lazy( /// 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 @@ fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { // 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::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 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 @@ fn write_to_bytes(self, b: &mut [u8]) { /// `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 @@ pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { 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_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 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 @@ fn paths(&self) -> Vec { } 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 @@ pub fn reset(&mut self) { 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 @@ pub fn maybe_load_library_crate(&mut self) -> Option { } } - 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::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 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 fn rustc_version() -> String { /// 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 @@ fn min_size(len: usize) -> usize { #[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 @@ pub fn from_position_and_meta(position: usize, meta: T::Meta) -> 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 @@ pub fn with_def_id(&self, def_id: DefId) -> ty::AssocItemContainer { } } - 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 @@ pub fn defaultness(&self) -> hir::Defaultness { } #[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 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 @@ fn register_crate( 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 @@ fn register_crate( 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 @@ fn register_crate( 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 @@ fn read_extension_crate(&mut self, name: Symbol, span: Span) -> ExtensionCrate { (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 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 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -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 @@ fn find_library_crate(&mut self, // 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 @@ fn find_library_crate(&mut self, 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 @@ fn find_library_crate(&mut self, } } + 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 @@ fn find_commandline_library<'b, LOCS>(&mut self, locs: LOCS) -> Option } }; - // 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 @@ } 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 @@ fn verify_no_symbol_conflicts(&self, } fn register_crate( - &mut self, + &self, host_lib: Option, root: Option<&CratePaths>, span: Span, @@ -272,7 +272,7 @@ fn register_crate( } fn load_proc_macro<'b>( - &mut self, + &self, locate_ctxt: &mut locator::Context<'b>, path_kind: PathKind, ) -> Option<(LoadResult, Option)> @@ -327,7 +327,7 @@ fn load_proc_macro<'b>( } fn resolve_crate<'b>( - &'b mut self, + &'b self, name: Symbol, span: Span, dep_kind: DepKind, @@ -337,7 +337,7 @@ fn resolve_crate<'b>( } fn maybe_resolve_crate<'b>( - &'b mut self, + &'b self, name: Symbol, span: Span, mut dep_kind: DepKind, @@ -397,7 +397,7 @@ fn maybe_resolve_crate<'b>( } } - 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 @@ fn load(&mut self, locate_ctxt: &mut locator::Context<'_>) -> Option } } - 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 @@ fn update_extern_crate(&mut self, } // 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 @@ fn resolve_crate_deps(&mut self, })).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 @@ fn dlsym_proc_macros(&self, /// 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 @@ pub fn find_plugin_registrar(&mut self, } } - 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 @@ fn inject_panic_runtime(&mut self, krate: &ast::Crate) { &|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 @@ fn inject_sanitizer_runtime(&mut self) { } } - 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 @@ fn inject_profiler_runtime(&mut self) { } } - 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 @@ fn inject_dependency_if(&self, } 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 @@ pub fn postprocess(&mut self, krate: &ast::Crate) { } } - 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 @@ pub fn process_extern_crate( } } - 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 @@ pub fn process_path_extern( 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 @@ pub fn new(session: &'a Session, 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::{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 = 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::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 @@ #[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 @@ fn from_owned_resolver( 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 @@ pub fn from_resolver_ref( 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 @@ pub fn process_extern_crate(&self, item: &ast::Item, definitions: &Definitions) }, &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::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 @@ pub fn new(metadata_loader: Box) -> 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 @@ pub fn new(metadata_loader: Box) -> 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 @@ fn crates_untracked(&self) -> Vec 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 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) { 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::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 @@ pub fn new(session: &'a Session, 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 @@ fn parse_pat_with_range_pat( 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 @@ fn parse_pat_with_range_pat( 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 @@ fn recover_intersection_pat(&mut self, lhs: P) -> PResult<'a, P> { .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 @@ fn recover_intersection_pat(&mut self, lhs: P) -> PResult<'a, P> { *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 @@ fn print_qpath(&mut self, } 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 @@ 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 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) { 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 @@ fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { 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 @@ fn encode_info_for_generics(&mut self, generics: &hir::Generics) { } } - 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::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 @@ macro_rules! rustc_erase_owner { } } + 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 @@ macro_rules! rustc_erase_owner { } } - 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 @@ pub fn fetch_add(&self, val: T, _: Ordering) -> T { 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 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 @@ fn primary_span_formatted<'a>( 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 @@ fn drop(&mut self) { } } } + +/// 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 @@ 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 @@ fn push_trailing(buf: &mut String, 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 @@ fn push_trailing(buf: &mut String, 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::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 @@ pub fn new(prev_graph: PreviousDepGraph, 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 @@ pub fn is_fully_enabled(&self) -> bool { } 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 @@ pub fn with_task<'a, C, A, R>( 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 @@ fn identity_fn(_: C, arg: A) -> A { 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 @@ fn with_task_impl<'a, C, A, R>( 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 @@ pub fn with_anon_task(&self, dep_kind: DepKind, op: OP) -> (R, DepNodeInde (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 @@ pub fn with_eval_always_task<'a, C, A, R>( 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 @@ pub fn with_eval_always_task<'a, C, A, R>( #[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 @@ pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex { .as_ref() .unwrap() .current - .borrow_mut() .node_to_node_index + .lock() .get(dep_node) .cloned() .unwrap() @@ -416,7 +414,7 @@ pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex { #[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 @@ pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { #[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 @@ pub(super) fn dep_node_debug_str(&self, dep_node: DepNode) -> Option { 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 @@ fn try_mark_previous_green<'tcx>( #[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 @@ fn try_mark_previous_green<'tcx>( // 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 @@ fn new(prev_graph_node_count: usize) -> 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 @@ fn complete_task( 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 @@ fn complete_anon_task(&mut self, kind: DepKind, task_deps: TaskDeps) -> DepNodeI } 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 @@ fn read_index(&self, source: DepNodeIndex) { 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 @@ fn read_index(&self, source: DepNodeIndex) { #[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 @@ fn read_index(&self, source: DepNodeIndex) { } } } 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 @@ struct OpaqueTypeExpander<'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 @@ fn expand_opaque_ty( } 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 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'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 @@ fn tcx(&self) -> 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 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) { } 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 @@ pub fn to_lit_token(&self) -> token::Lit { 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 @@ fn eq(&self, other: &T) -> bool { } } -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 @@ pub fn fatal(&self, msg: &str) { } 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 @@ fn right(&self, line_len: usize) -> usize { /// 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 @@ fn should_show_explain(&self) -> bool { /// 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 @@ fn primary_span_formatted<'a>( // 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 @@ 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); + 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 @@ pub fn ui_testing(self, ui_testing: bool) -> Self { } 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 @@ fn flush(&mut self) -> io::Result<()> { 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::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 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstF 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 @@ fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstF })), 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 @@ fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) { ); } - 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 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 @@ fn check_abi(&self, abi: Abi, span: Span) { 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 @@ fn visit_item(&mut self, i: &'a ast::Item) { 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 @@ fn consume_fn_args(&mut self) -> Result<(), ()> { } } - 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 attr; pub mod lexer; pub mod token; +mod sess; +pub use sess::ParseSess; crate mod classify; crate mod diagnostics; @@ -46,112 +41,6 @@ #[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 @@ fn report_invalid_macro_expansion_item(&self) { ], 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 @@ 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 @@ pub fn to_lit_token(&self) -> token::Lit { 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 @@ pub fn from_lit_kind(kind: LitKind, span: Span) -> 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 @@ 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 @@ fn expect_or(&mut self) -> PResult<'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::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 @@ macro_rules! parse_lit { 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::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::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::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 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 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::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::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::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::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 @@ pub fn new_parser_from_tts(&self, stream: TokenStream) -> parser::Parser<'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::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::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 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::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::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 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::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 util { 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::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 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 @@ 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::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::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::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::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::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 @@ 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 @@ 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::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 @@ fn elided_path_lifetime(&mut self, span: Span) -> hir::Lifetime { 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 @@ fn suggest_traits_to_import<'b>( } 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 @@ fn suggest_traits_to_import<'b>( } 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 @@ fn suggest_traits_to_import<'b>( // 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 @@ fn record_index(&mut self, item: DefIndex, entry: Lazy>) { 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 std::io; use std::mem; +use std::num::NonZeroUsize; use std::u32; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; @@ -131,7 +132,7 @@ fn tcx(self) -> Option> { 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 @@ fn read_lazy_with_meta( 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::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 @@ fn emit_lazy_distance( &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 @@ fn emit_lazy_distance( "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 @@ fn lazy( &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 @@ fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { // 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 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 @@ fn record_index(&mut self, item: DefIndex, entry: Lazy>) { 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_pos::{self, Span}; use std::marker::PhantomData; +use std::num::NonZeroUsize; crate fn rustc_version() -> String { format!("rustc {}", @@ -102,13 +103,13 @@ fn min_size(len: usize) -> usize { 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy /// 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 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 @@ fn write_to_bytes(self, b: &mut [u8]) { /// 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 @@ fn write_to_bytes(self, b: &mut [u8]) { 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 @@ fn entry_unless_proc_macro(&self, id: DefIndex) -> Option> { } 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 @@ fn record( 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 @@ fn encode_crate_root(&mut self) -> Lazy> { 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 @@ fn encode_crate_root(&mut self) -> Lazy> { impls, exported_symbols, interpret_alloc_index, - entries_index, + entries_table, }); let total_bytes = self.position(); @@ -562,7 +562,7 @@ fn encode_crate_root(&mut self) -> Lazy> { 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 @@ fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { 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 @@ 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy 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 @@ fn write_to_bytes(self, b: &mut [u8]) { /// `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 @@ fn record_index(&mut self, item: DefIndex, entry: Lazy>) { 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 @@ fn record_index(&mut self, item: DefIndex, entry: Lazy>) { } } -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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy /// 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 @@ impl AssocContainer { #[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 @@ fn write_to_bytes(self, b: &mut [u8]) { } } -/// 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 @@ fn record_index(&mut self, item: DefIndex, entry: Lazy>) { } } -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::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 @@ fn tcx(self) -> Option> { } } -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 @@ fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { } } -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 @@ fn specialized_decode(&mut self) -> Result, Self::Error> { } } +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 @@ fn emit_unit(&mut self) -> Result<(), Self::Error> { } } -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 @@ fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { } } +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 @@ fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) { } } -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_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 @@ 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 @@ fn min_size(_: ()) -> usize { } } -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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy // 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 @@ macro_rules! Lazy { 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 @@ fn write_to_bytes(self, b: &mut [u8]) { /// (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 @@ fn specialized_decode(&mut self) -> Result, Self::Error> { } } -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 @@ fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { } } -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 @@ fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { 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 @@ impl rustc_serialize::UseSpecializedDecodable for Lazy // 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 @@ macro_rules! Lazy { 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 @@ fn write_to_bytes(self, b: &mut [u8]) { /// (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 @@ fn entry_unless_proc_macro(&self, id: DefIndex) -> Option> { } 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 @@ fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> usize { } } +// 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 @@ fn lazy( 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 @@ fn encode_crate_root(&mut self) -> Lazy> { 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 @@ fn encode_crate_root(&mut self) -> Lazy> { impls, exported_symbols, interpret_alloc_index, - entries_table, + per_def, }); let total_bytes = self.position(); @@ -571,7 +568,7 @@ fn encode_crate_root(&mut self) -> Lazy> { 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 @@ fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { 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 @@ fn encode_enum_variant_info( 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 @@ fn encode_enum_variant_info( 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 @@ fn encode_enum_variant_ctor( 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 @@ fn encode_enum_variant_ctor( 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 @@ fn encode_info_for_mod( }, }; - 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 @@ fn encode_info_for_mod( 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 @@ fn encode_field( 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 @@ fn encode_field( 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 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry< 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 @@ fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry< 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 @@ fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy 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 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'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 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'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 @@ fn metadata_output_only(&self) -> bool { !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 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'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 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'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 @@ fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy 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 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> 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 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> _ => 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 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> // 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 @@ fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx predicates_defined_on: None, mir: None, promoted_mir: None, - } + }) } fn encode_info_for_generic_param( @@ -1381,9 +1387,9 @@ fn encode_info_for_generic_param( 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 @@ fn encode_info_for_generic_param( 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 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'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 @@ fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'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 @@ fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'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 @@ fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'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 @@ fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option 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 @@ fn encode_info_for_foreign_item(&mut self, 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 @@ fn encode_info_for_foreign_item(&mut self, 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 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) { 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 @@ fn visit_item(&mut self, item: &'tcx hir::Item) { 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 @@ fn encode_info_for_generics(&mut self, generics: &hir::Generics) { 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 @@ fn encode_info_for_expr(&mut self, expr: &hir::Expr) { 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 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) { 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 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) { // 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 @@ fn encode_addl_info_for_item(&mut self, item: &hir::Item) { } 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 @@ fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { 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 @@ macro_rules! Lazy { 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 @@ macro_rules! Lazy { 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 @@ macro_rules! Lazy { 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 @@ fn specialized_decode(&mut self) -> Result, Self::Error> { } 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 @@ fn entry_unless_proc_macro(&self, id: DefIndex) -> Option> { } 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 @@ fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { } 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 @@ fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'tcx>) -> usize { } } -// 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 @@ macro_rules! Lazy { #[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 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 @@ fn read_from_bytes_at(b: &[u8], i: usize) -> Self { 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 @@ fn write_to_bytes(self, b: &mut [u8]) { } } -/// 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 @@ fn min_size(len: usize) -> usize { } } -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 @@ fn min_size(meta: Self::Meta) -> usize { } } -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 @@ fn tcx(self) -> Option> { } 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 @@ fn entry_unless_proc_macro(&self, id: DefIndex) -> Option> { } 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 @@ fn min_size(len: usize) -> usize { 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 @@ fn as_table(&self) -> Lazy> { /// 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 @@ fn is_proc_macro(&self, id: DefIndex) -> bool { 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 @@ fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro { 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 @@ fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro { } 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 @@ fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro { 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 @@ fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro { 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 @@ fn get_variant( 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 @@ fn get_variant( } 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 @@ fn get_variant( 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 @@ fn get_variant( 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 @@ fn get_variant( 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 @@ fn get_variant( } 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { } // 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { } 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { } } - 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { } 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { } 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { } 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { 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 @@ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { 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 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option { 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 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option { _ => 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 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option { } 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 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option { } 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 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option { } 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 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option { } 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 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option { } 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 @@ fn reverse_translate_def_id(&self, did: DefId) -> Option { } 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::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 @@ fn encode_crate_root(&mut self) -> Lazy> { 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 @@ fn encode_crate_root(&mut self) -> Lazy> { } 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 @@ fn encode_enum_variant_info( 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 @@ fn encode_enum_variant_ctor( 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 @@ fn encode_info_for_mod( }, }; - 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 @@ fn encode_field( 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 @@ fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) { 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 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) { 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 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) { 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 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) { } }; 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 @@ fn encode_info_for_trait_item(&mut self, def_id: DefId) { } 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 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) { 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 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) { 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 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) { } 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 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) { 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 @@ fn encode_fn_param_names(&mut self, param_names: &[ast::Ident]) -> Lazy<[ast::Na 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 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { 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 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { 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 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { // "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 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { 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 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { } 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 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { } _ => 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 @@ fn encode_info_for_closure(&mut self, def_id: DefId) { 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 @@ fn encode_info_for_foreign_item( 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 @@ fn encode_info_for_foreign_item( 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 @@ fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { // 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 @@ fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { 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 @@ macro_rules! Lazy { #[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 @@ fn visit_impl_item(&mut self, _impl_item: &'v hir::ImplItem) { // 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 @@ // 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 @@ 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 @@ fn read_from_bytes_at(b: &[u8], i: usize) -> Self { 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 @@ fn write_to_bytes(self, b: &mut [u8]) { /// 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 @@ fn write_to_bytes(self, b: &mut [u8]) { _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 @@ // 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 @@ fn write_to_bytes(self, b: &mut [u8]) { } } -/// 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 @@ fn default() -> Self { 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 @@ fn parse_token_tree(&mut self) -> PResult<'a, TreeAndJoint> { 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 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) { 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 @@ fn check_uses_for_lifetimes_defined_by_scope(&mut self) { _ => 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 @@ pub fn words(&self) -> &[Word] { /// 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 @@ pub fn words(&self) -> &[Word] { 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 @@ fn to_string(&self) -> String { } 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 @@ fn add_import_directive( 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 @@ fn build_reduced_graph_for_use_tree( }; 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 @@ fn build_reduced_graph_for_item(&mut self, item: &'b Item) { 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 @@ fn build_reduced_graph_for_block(&mut self, block: &Block) { 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 @@ pub(crate) fn check_for_module_export_macro( } 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 @@ pub fn name(&self) -> Option { } } -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 @@ fn new(parent: Option>, 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 @@ pub fn new(session: &'a Session, 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 @@ fn new_module( 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 @@ fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'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::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 @@ pub fn try_define( } 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 @@ pub fn try_define( 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 @@ fn ambiguity( // 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 @@ fn update_resolution( // 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 @@ fn update_resolution( // 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 @@ fn update_resolution( }; 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 @@ fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'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 @@ fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool { 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 @@ fn finalize_import( _ => 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 @@ fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'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 @@ fn finalize_resolutions_in(&mut self, module: Module<'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 @@ fn finalize_resolutions_in(&mut self, module: Module<'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 @@ fn finalize_resolutions_in(&mut self, module: Module<'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 @@ fn finalize_resolutions_in(&mut self, module: Module<'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 @@ fn finalize_resolutions_in(&mut self, module: Module<'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 @@ pub fn modern_and_legacy(self) -> 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 @@ fn default_decode(d: &mut D) -> Result { } } -/// 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 @@ pub fn as_str(self) -> LocalInternedString { }) } - /// 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 @@ pub fn as_u32(self) -> u32 { 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 @@ fn decode(d: &mut D) -> Result { } // 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 @@ pub fn intern(&mut self, string: &str) -> Symbol { 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -/// 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 @@ fn name_by_region_index(index: usize) -> InternedString { } // 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 @@ fn new(sym: Symbol, is_raw: bool, span: Span) -> 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 @@ pub fn report_selection_error( // 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 @@ pub fn report_selection_error( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( } 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ pub fn span(&self) -> Option { 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 @@ fn suggest_restricting_param_bound( } 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 @@ fn suggest_restricting_param_bound( } }; + 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( }) | 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 @@ fn suggest_restricting_param_bound( 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 @@ fn suggest_restricting_param_bound( }; 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 @@ pub fn check_ref( // 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 @@ fn suggest_restricting_param_bound( 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 @@ /// 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 @@ #[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 @@ pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T> 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::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 @@ pub fn is_proc_macro_attr(attr: &Attribute) -> bool { 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 @@ pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { /// 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 @@ pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path 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 @@ pub fn parse_derive_paths<'a>(&self, sess: &'a ParseSess) -> PResult<'a, Vec Vec { 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 @@ fn parse_unsuffixed_lit(&mut self) -> PResult<'a, ast::Lit> { 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 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 @@ 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::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::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::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::{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 @@ pub fn meta(&self) -> Option { 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 @@ pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T> 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 @@ pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span 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 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 @@ struct Restrictions: u8 { } #[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 @@ fn next_desugared(&mut self) -> Token { } #[derive(Clone, PartialEq)] -crate enum TokenType { +enum TokenType { Token(TokenKind), Keyword(Symbol), Operator, @@ -311,7 +309,7 @@ fn next_desugared(&mut self) -> Token { } 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 @@ pub fn this_token_to_string(&self) -> String { 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 @@ pub fn this_token_to_string(&self) -> String { }) } - 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 @@ pub fn expect_one_of( } } - 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 @@ fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> { /// /// 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 @@ fn check_keyword(&mut self, kw: Symbol) -> bool { /// 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 @@ fn check_or_expected(&mut self, ok: bool, typ: TokenType) -> bool { } } - 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 @@ fn expect_gt(&mut self) -> PResult<'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 @@ pub fn parse_seq_to_end( /// 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 @@ fn expect_any_with_type(&mut self, kets: &[&TokenKind], expect: TokenExpectType) }) } - crate fn parse_seq_to_before_tokens( + fn parse_seq_to_before_tokens( &mut self, kets: &[&TokenKind], sep: SeqSep, @@ -1101,7 +1099,7 @@ fn is_crate_vis(&self) -> bool { /// 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 @@ fn is_import_coupler(&mut self) -> bool { *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 @@ enum InnerAttributeParsePolicy<'a> { 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 @@ pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attrib /// 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 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 @@ fn span_err>( } } -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 @@ fn recovered(qself: Option, path: ast::Path) -> Self { } 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 @@ pub fn span_err>(&self, sp: S, m: &str) { 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 @@ pub fn span_err>(&self, sp: S, m: &str) { 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 @@ pub fn maybe_annotate_with_ascription( /// 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 @@ pub fn maybe_annotate_with_ascription( /// 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 @@ pub fn maybe_annotate_with_ascription( /// 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 @@ fn consume_fn_args(&mut self) -> Result<(), ()> { } } - 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 @@ pub(super) fn maybe_recover_from_bad_type_plus( /// 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 @@ pub(super) fn maybe_recover_from_bad_type_plus( /// 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 @@ pub(super) fn maybe_recover_from_bad_type_plus( ))) } - 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 @@ pub(super) fn maybe_recover_from_bad_type_plus( /// 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 @@ pub fn unexpected_try_recover( 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 @@ pub fn unexpected_try_recover( /// 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: } /// 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: /// 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: } } - 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: } } - crate fn recover_closing_delimiter( + pub(super) fn recover_closing_delimiter( &mut self, tokens: &[TokenKind], mut err: DiagnosticBuilder<'a>, @@ -1142,7 +1143,7 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: } /// 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: /// 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: /// /// 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: } } - 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: } } - 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: } } - crate fn parameter_without_type( + pub(super) fn parameter_without_type( &mut self, err: &mut DiagnosticBuilder<'_>, pat: P, @@ -1351,7 +1352,7 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: 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 @@ fn error_on_incorrect_await(&self, lo: Span, hi: Span, expr: &Expr, is_question: } } - 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 @@ fn consume_tts( /// 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 @@ macro_rules! parse_lit { } /// 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 @@ pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option, lo: Span, @@ -1558,7 +1558,7 @@ fn parse_match_expr(&mut self, mut attrs: ThinVec) -> PResult<'a, P PResult<'a, Arm> { + pub(super) fn parse_arm(&mut self) -> PResult<'a, Arm> { let attrs = self.parse_outer_attributes()?; let lo = self.token.span; let pat = self.parse_top_pat(GateOr::No)?; @@ -1666,7 +1666,7 @@ fn is_try_block(&self) -> bool { } /// Parses an `async move? {...}` expression. - pub fn parse_async_block(&mut self, mut attrs: ThinVec) -> PResult<'a, P> { + fn parse_async_block(&mut self, mut attrs: ThinVec) -> PResult<'a, P> { let span_lo = self.token.span; self.expect_keyword(kw::Async)?; let capture_clause = self.parse_capture_clause(); diff --git a/src/libsyntax/parse/parser/generics.rs b/src/libsyntax/parse/parser/generics.rs index 2ecd9cca3c64..bfcb0042a75a 100644 --- a/src/libsyntax/parse/parser/generics.rs +++ b/src/libsyntax/parse/parser/generics.rs @@ -74,7 +74,7 @@ fn parse_const_param(&mut self, preceding_attrs: Vec) -> PResult<'a, /// Parses a (possibly empty) list of lifetime and type parameters, possibly including /// a trailing comma and erroneous trailing attributes. - crate fn parse_generic_params(&mut self) -> PResult<'a, Vec> { + pub(super) fn parse_generic_params(&mut self) -> PResult<'a, Vec> { let mut params = Vec::new(); loop { let attrs = self.parse_outer_attributes()?; diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 90517d4d7708..4f161a481ca3 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -24,7 +24,7 @@ /// Whether the type alias or associated type is a concrete type or an opaque type. #[derive(Debug)] -pub enum AliasKind { +pub(super) enum AliasKind { /// Just a new name for the same type. Weak(P), /// Only trait impls of the type will be usable, not the actual type itself. @@ -675,7 +675,7 @@ fn parse_impl_body(&mut self) -> PResult<'a, (Vec, Vec)> { } /// Parses an impl item. - pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { + crate fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { maybe_whole!(self, NtImplItem, |x| x); let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; @@ -851,7 +851,7 @@ fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> { } /// Parses the items in a trait declaration. - pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { + crate fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { maybe_whole!(self, NtTraitItem, |x| x); let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; diff --git a/src/libsyntax/parse/parser/module.rs b/src/libsyntax/parse/parser/module.rs index 20bd189cf8fb..1a8178f0bec5 100644 --- a/src/libsyntax/parse/parser/module.rs +++ b/src/libsyntax/parse/parser/module.rs @@ -12,13 +12,13 @@ use std::path::{self, Path, PathBuf}; /// Information about the path to a module. -pub struct ModulePath { +pub(super) struct ModulePath { name: String, path_exists: bool, pub result: Result, } -pub struct ModulePathSuccess { +pub(super) struct ModulePathSuccess { pub path: PathBuf, pub directory_ownership: DirectoryOwnership, warn: bool, @@ -26,7 +26,7 @@ pub struct ModulePathSuccess { impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. - pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { + crate fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { let lo = self.token.span; let krate = Ok(ast::Crate { attrs: self.parse_inner_attributes()?, @@ -198,7 +198,7 @@ fn submod_path( } } - pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { + pub(super) fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) { let s = s.as_str(); @@ -215,7 +215,7 @@ pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option, dir_path: &Path, diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index e288346a3292..b30e0636bb16 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -22,7 +22,7 @@ /// Whether or not an or-pattern should be gated when occurring in the current context. #[derive(PartialEq)] -pub enum GateOr { Yes, No } +pub(super) enum GateOr { Yes, No } /// Whether or not to recover a `,` when parsing or-patterns. #[derive(PartialEq, Copy, Clone)] @@ -34,7 +34,7 @@ impl<'a> Parser<'a> { /// Corresponds to `pat` in RFC 2535 and does not admit or-patterns /// at the top level. Used when parsing the parameters of lambda expressions, /// functions, function pointers, and `pat` macro fragments. - pub fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P> { + crate fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P> { self.parse_pat_with_range_pat(true, expected) } diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs index 1f48cc753048..0f28fb11cde4 100644 --- a/src/libsyntax/parse/parser/path.rs +++ b/src/libsyntax/parse/parser/path.rs @@ -13,7 +13,7 @@ /// Specifies how to parse a path. #[derive(Copy, Clone, PartialEq)] -pub enum PathStyle { +crate enum PathStyle { /// In some contexts, notably in expressions, paths with generic arguments are ambiguous /// with something else. For example, in expressions `segment < ....` can be interpreted /// as a comparison and `segment ( ....` can be interpreted as a function call. @@ -88,7 +88,7 @@ pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, Pa /// `a::b::C::` (with disambiguator) /// `Fn(Args)` (without disambiguator) /// `Fn::(Args)` (with disambiguator) - pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { + crate fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { maybe_whole!(self, NtPath, |path| { if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some()) { @@ -144,7 +144,7 @@ fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> { Ok(list) } - crate fn parse_path_segments( + pub(super) fn parse_path_segments( &mut self, segments: &mut Vec, style: PathStyle, diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index c8d6b6ff9ddc..a6625e127337 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -20,7 +20,7 @@ impl<'a> Parser<'a> { /// Parses a statement. This stops just before trailing semicolons on everything but items. /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. - pub fn parse_stmt(&mut self) -> PResult<'a, Option> { + crate fn parse_stmt(&mut self) -> PResult<'a, Option> { Ok(self.parse_stmt_(true)) } @@ -300,7 +300,7 @@ fn is_auto_trait_item(&self) -> bool { } /// Parses a block. No inner attributes are allowed. - pub fn parse_block(&mut self) -> PResult<'a, P> { + crate fn parse_block(&mut self) -> PResult<'a, P> { maybe_whole!(self, NtBlock, |x| x); let lo = self.token.span; @@ -373,7 +373,7 @@ pub fn parse_block(&mut self) -> PResult<'a, P> { } /// Parses a block. Inner attributes are allowed. - crate fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec, P)> { + pub(super) fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec, P)> { maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); let lo = self.token.span; diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index e696ab0804d6..fe18a08ae1e5 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -296,7 +296,7 @@ fn parse_ty_bare_fn(&mut self, generic_params: Vec) -> PResult<'a, }))) } - crate fn parse_generic_bounds(&mut self, + pub(super) fn parse_generic_bounds(&mut self, colon_span: Option) -> PResult<'a, GenericBounds> { self.parse_generic_bounds_common(true, colon_span) } From 55f3c2d59a5f82b70c0bfbaa4ed783859c553b84 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 13:38:14 +0200 Subject: [PATCH 440/545] ast: use more direct imports --- src/libsyntax/ast.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 79d91125ec4c..0408d7d1bc2a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2,30 +2,29 @@ pub use GenericArgs::*; pub use UnsafeSource::*; -pub use crate::symbol::{Ident, Symbol as Name}; pub use crate::util::parser::ExprPrecedence; -use crate::ext::hygiene::ExpnId; use crate::parse::token::{self, DelimToken}; use crate::ptr::P; use crate::source_map::{dummy_spanned, respan, Spanned}; -use crate::symbol::{kw, sym, Symbol}; use crate::tokenstream::TokenStream; -use crate::ThinVec; + +use rustc_target::spec::abi::Abi; +pub use rustc_target::abi::FloatTy; + +use syntax_pos::{Span, DUMMY_SP, ExpnId}; +use syntax_pos::symbol::{kw, sym, Symbol}; +pub use syntax_pos::symbol::{Ident, Symbol as Name}; use rustc_index::vec::Idx; #[cfg(target_arch = "x86_64")] use rustc_data_structures::static_assert_size; -use rustc_target::spec::abi::Abi; -use syntax_pos::{Span, DUMMY_SP}; - use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::thin_vec::ThinVec; use rustc_serialize::{self, Decoder, Encoder}; use std::fmt; -pub use rustc_target::abi::FloatTy; - #[cfg(test)] mod tests; From 7ec38a9ae3c5e7b8eef0ec4696d058cd9e85583d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 14:15:26 +0200 Subject: [PATCH 441/545] attr: remove dep on ExtCtxt --- src/libsyntax/attr/builtin.rs | 14 +++++--------- src/libsyntax_ext/global_allocator.rs | 3 ++- src/libsyntax_ext/lib.rs | 1 + src/libsyntax_ext/test.rs | 4 +++- src/libsyntax_ext/util.rs | 11 +++++++++++ 5 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 src/libsyntax_ext/util.rs diff --git a/src/libsyntax/attr/builtin.rs b/src/libsyntax/attr/builtin.rs index 1fe698c2572c..28b61c5aa77c 100644 --- a/src/libsyntax/attr/builtin.rs +++ b/src/libsyntax/attr/builtin.rs @@ -2,7 +2,6 @@ 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::print::pprust; use crate::sess::ParseSess; @@ -32,6 +31,10 @@ pub struct AttributeTemplate { } impl AttributeTemplate { + pub fn only_word() -> Self { + Self { word: true, list: None, name_value_str: None } + } + /// Checks that the given meta-item is compatible with this template. fn compatible(&self, meta_item_kind: &ast::MetaItemKind) -> bool { match meta_item_kind { @@ -937,14 +940,7 @@ pub fn find_transparency( (transparency.map_or(fallback, |t| t.0), error) } -pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { - // All the built-in macro attributes are "words" at the moment. - let template = AttributeTemplate { word: true, list: None, name_value_str: None }; - let attr = ecx.attribute(meta_item.clone()); - check_builtin_attribute(ecx.parse_sess, &attr, name, template); -} - -crate fn check_builtin_attribute( +pub fn check_builtin_attribute( sess: &ParseSess, attr: &ast::Attribute, name: Symbol, template: AttributeTemplate ) { // Some special attributes like `cfg` must be checked diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs index cd2a9b61a76d..f014b4f4f9fd 100644 --- a/src/libsyntax_ext/global_allocator.rs +++ b/src/libsyntax_ext/global_allocator.rs @@ -1,6 +1,7 @@ +use crate::util::check_builtin_macro_attribute; + use syntax::ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafety}; use syntax::ast::{self, Param, Attribute, Expr, FnHeader, Generics, Ident}; -use syntax::attr::check_builtin_macro_attribute; use syntax::ext::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; use syntax::ext::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 64d46a84cba4..5ba76a52350f 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -37,6 +37,7 @@ mod source_util; mod test; mod trace_macros; +mod util; pub mod cmdline_attrs; pub mod plugin_macro_defs; diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index d4638c45473b..4d7441ca0b66 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -1,8 +1,10 @@ /// The expansion from a test function to the appropriate test struct for libtest /// Ideally, this code would be in libtest but for efficiency and error messages it lives here. +use crate::util::check_builtin_macro_attribute; + use syntax::ast; -use syntax::attr::{self, check_builtin_macro_attribute}; +use syntax::attr; use syntax::ext::base::*; use syntax::print::pprust; use syntax::source_map::respan; diff --git a/src/libsyntax_ext/util.rs b/src/libsyntax_ext/util.rs new file mode 100644 index 000000000000..fbae68057c5b --- /dev/null +++ b/src/libsyntax_ext/util.rs @@ -0,0 +1,11 @@ +use syntax_pos::Symbol; +use syntax::ast::MetaItem; +use syntax::attr::{check_builtin_attribute, AttributeTemplate}; +use syntax::ext::base::ExtCtxt; + +pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { + // All the built-in macro attributes are "words" at the moment. + let template = AttributeTemplate::only_word(); + let attr = ecx.attribute(meta_item.clone()); + check_builtin_attribute(ecx.parse_sess, &attr, name, template); +} From d160a4e4225eb5e310554316cba78efb2cbe6fa2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 14:39:58 +0200 Subject: [PATCH 442/545] syntax::parse: don't depend on syntax::ext --- src/libsyntax/parse/parser/expr.rs | 4 ++++ src/libsyntax/parse/parser/item.rs | 3 +-- src/libsyntax/parse/parser/stmt.rs | 5 ++--- src/libsyntax/parse/parser/ty.rs | 6 +++++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 2e6b9de7693d..bf9526dece23 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1946,4 +1946,8 @@ fn mk_await_expr(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> crate fn mk_expr(&self, span: Span, kind: ExprKind, attrs: ThinVec) -> P { P(Expr { kind, span, attrs, id: DUMMY_NODE_ID }) } + + pub(super) fn mk_expr_err(&self, span: Span) -> P { + self.mk_expr(span, ExprKind::Err, ThinVec::new()) + } } diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 4f161a481ca3..6a1cbd2ebb77 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -9,7 +9,6 @@ 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::tokenstream::{TokenTree, TokenStream}; @@ -606,7 +605,7 @@ fn parse_item_impl(&mut self, unsafety: Unsafety, defaultness: Defaultness) let ty_second = if self.token == token::DotDot { // We need to report this error after `cfg` expansion for compatibility reasons self.bump(); // `..`, do not add it to expected tokens - Some(DummyResult::raw_ty(self.prev_span, true)) + Some(self.mk_ty(self.prev_span, TyKind::Err)) } else if has_for || self.token.can_begin_type() { Some(self.parse_ty()?) } else { diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index a6625e127337..f656bc11e1ca 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -8,7 +8,6 @@ use crate::{maybe_whole, ThinVec}; use crate::ast::{self, DUMMY_NODE_ID, Stmt, StmtKind, Local, Block, BlockCheckMode, Expr, ExprKind}; use crate::ast::{Attribute, AttrStyle, VisibilityKind, MacStmtStyle, Mac, MacDelimiter}; -use crate::ext::base::DummyResult; use crate::parse::{classify, DirectoryOwnership}; use crate::parse::token; use crate::source_map::{respan, Span}; @@ -400,7 +399,7 @@ pub(super) fn parse_block_tail( self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); Some(Stmt { id: DUMMY_NODE_ID, - kind: StmtKind::Expr(DummyResult::raw_expr(self.token.span, true)), + kind: StmtKind::Expr(self.mk_expr_err(self.token.span)), span: self.token.span, }) } @@ -443,7 +442,7 @@ pub(super) fn parse_block_tail( self.recover_stmt(); // Don't complain about type errors in body tail after parse error (#57383). let sp = expr.span.to(self.prev_span); - stmt.kind = StmtKind::Expr(DummyResult::raw_expr(sp, true)); + stmt.kind = StmtKind::Expr(self.mk_expr_err(sp)); } } } diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index fe18a08ae1e5..ae9f4d06c055 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -210,7 +210,7 @@ pub(super) fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: }; let span = lo.to(self.prev_span); - let ty = P(Ty { kind, span, id: ast::DUMMY_NODE_ID }); + let ty = self.mk_ty(span, kind); // Try to recover from use of `+` with incorrect priority. self.maybe_report_ambiguous_plus(allow_plus, impl_dyn_multi, &ty); @@ -448,4 +448,8 @@ pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec P { + P(Ty { kind, span, id: ast::DUMMY_NODE_ID }) + } } From d420d719c4c44c3c6d02b5fafba4f2cf5e837dba Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 16 Oct 2019 10:59:30 +0200 Subject: [PATCH 443/545] move syntax::ext to new crate syntax_expand --- Cargo.lock | 27 ++ src/librustc/Cargo.toml | 1 + src/librustc/hir/def.rs | 2 +- src/librustc/hir/lowering.rs | 6 +- src/librustc/hir/lowering/item.rs | 2 +- src/librustc/hir/map/def_collector.rs | 2 +- src/librustc/hir/map/definitions.rs | 2 +- src/librustc/hir/map/mod.rs | 2 +- src/librustc/ich/hcx.rs | 2 +- src/librustc/ich/impls_syntax.rs | 2 +- src/librustc/lint/mod.rs | 2 +- src/librustc/session/mod.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc_codegen_llvm/allocator.rs | 2 +- src/librustc_codegen_llvm/lib.rs | 3 +- src/librustc_codegen_ssa/Cargo.toml | 1 + .../back/symbol_export.rs | 2 +- src/librustc_codegen_ssa/back/write.rs | 2 +- src/librustc_codegen_ssa/traits/backend.rs | 2 +- src/librustc_interface/Cargo.toml | 1 + src/librustc_interface/passes.rs | 8 +- src/librustc_metadata/Cargo.toml | 1 + src/librustc_metadata/creader.rs | 2 +- src/librustc_metadata/cstore.rs | 2 +- src/librustc_metadata/decoder.rs | 4 +- src/librustc_metadata/encoder.rs | 2 +- src/librustc_passes/Cargo.toml | 1 + src/librustc_passes/ast_validation.rs | 2 +- src/librustc_plugin/Cargo.toml | 1 + src/librustc_plugin/lib.rs | 2 +- src/librustc_plugin/registry.rs | 4 +- src/librustc_resolve/Cargo.toml | 1 + src/librustc_resolve/build_reduced_graph.rs | 6 +- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_resolve/late/diagnostics.rs | 2 +- src/librustc_resolve/lib.rs | 14 +- src/librustc_resolve/macros.rs | 10 +- src/librustc_resolve/resolve_imports.rs | 2 +- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/doctree.rs | 2 +- src/librustdoc/html/item_type.rs | 2 +- src/librustdoc/html/render.rs | 4 +- src/librustdoc/lib.rs | 1 + .../passes/collect_intra_doc_links.rs | 2 +- src/librustdoc/visit_ast.rs | 2 +- src/libsyntax/attr/mod.rs | 4 +- src/libsyntax/config.rs | 1 + src/libsyntax/feature_gate/check.rs | 2 +- src/libsyntax/feature_gate/mod.rs | 3 +- src/libsyntax/lib.rs | 41 +-- src/libsyntax/parse/literal.rs | 2 +- src/libsyntax/parse/parser.rs | 14 +- src/libsyntax/parse/parser/diagnostics.rs | 6 +- src/libsyntax/parse/parser/expr.rs | 2 +- src/libsyntax/parse/parser/item.rs | 6 +- src/libsyntax/parse/parser/pat.rs | 2 +- src/libsyntax/parse/parser/path.rs | 4 +- src/libsyntax/parse/parser/stmt.rs | 6 +- src/libsyntax/parse/parser/ty.rs | 4 +- src/libsyntax/parse/token.rs | 14 +- src/libsyntax/tokenstream.rs | 2 +- src/libsyntax_expand/Cargo.toml | 26 ++ .../ext => libsyntax_expand}/allocator.rs | 4 +- .../ext => libsyntax_expand}/base.rs | 31 +-- .../ext => libsyntax_expand}/build.rs | 15 +- .../ext => libsyntax_expand}/expand.rs | 242 +++++++++--------- src/libsyntax_expand/lib.rs | 38 +++ .../ext => libsyntax_expand}/mbe.rs | 6 +- .../mbe/macro_check.rs | 14 +- .../mbe/macro_parser.rs | 21 +- .../mbe/macro_rules.rs | 72 +++--- .../ext => libsyntax_expand}/mbe/quoted.rs | 17 +- .../mbe/transcribe.rs | 15 +- .../ext => libsyntax_expand}/placeholders.rs | 17 +- .../ext => libsyntax_expand}/proc_macro.rs | 34 ++- .../proc_macro_server.rs | 23 +- src/libsyntax_ext/Cargo.toml | 1 + src/libsyntax_ext/asm.rs | 2 +- src/libsyntax_ext/assert.rs | 2 +- src/libsyntax_ext/cfg.rs | 2 +- src/libsyntax_ext/cmdline_attrs.rs | 2 +- src/libsyntax_ext/compile_error.rs | 2 +- src/libsyntax_ext/concat.rs | 2 +- src/libsyntax_ext/concat_idents.rs | 2 +- src/libsyntax_ext/deriving/bounds.rs | 2 +- src/libsyntax_ext/deriving/clone.rs | 2 +- src/libsyntax_ext/deriving/cmp/eq.rs | 2 +- src/libsyntax_ext/deriving/cmp/ord.rs | 2 +- src/libsyntax_ext/deriving/cmp/partial_eq.rs | 2 +- src/libsyntax_ext/deriving/cmp/partial_ord.rs | 2 +- src/libsyntax_ext/deriving/debug.rs | 2 +- src/libsyntax_ext/deriving/decodable.rs | 2 +- src/libsyntax_ext/deriving/default.rs | 2 +- src/libsyntax_ext/deriving/encodable.rs | 2 +- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- src/libsyntax_ext/deriving/generic/ty.rs | 2 +- src/libsyntax_ext/deriving/hash.rs | 2 +- src/libsyntax_ext/deriving/mod.rs | 2 +- src/libsyntax_ext/env.rs | 2 +- src/libsyntax_ext/format.rs | 2 +- src/libsyntax_ext/global_allocator.rs | 4 +- src/libsyntax_ext/global_asm.rs | 2 +- src/libsyntax_ext/lib.rs | 6 +- src/libsyntax_ext/log_syntax.rs | 2 +- src/libsyntax_ext/plugin_macro_defs.rs | 2 +- src/libsyntax_ext/proc_macro_harness.rs | 8 +- src/libsyntax_ext/source_util.rs | 5 +- src/libsyntax_ext/standard_library_imports.rs | 6 +- src/libsyntax_ext/test.rs | 2 +- src/libsyntax_ext/test_harness.rs | 4 +- src/libsyntax_ext/trace_macros.rs | 2 +- src/libsyntax_ext/util.rs | 2 +- 113 files changed, 500 insertions(+), 430 deletions(-) create mode 100644 src/libsyntax_expand/Cargo.toml rename src/{libsyntax/ext => libsyntax_expand}/allocator.rs (96%) rename src/{libsyntax/ext => libsyntax_expand}/base.rs (98%) rename src/{libsyntax/ext => libsyntax_expand}/build.rs (98%) rename src/{libsyntax/ext => libsyntax_expand}/expand.rs (91%) create mode 100644 src/libsyntax_expand/lib.rs rename src/{libsyntax/ext => libsyntax_expand}/mbe.rs (98%) rename src/{libsyntax/ext => libsyntax_expand}/mbe/macro_check.rs (98%) rename src/{libsyntax/ext => libsyntax_expand}/mbe/macro_parser.rs (99%) rename src/{libsyntax/ext => libsyntax_expand}/mbe/macro_rules.rs (96%) rename src/{libsyntax/ext => libsyntax_expand}/mbe/quoted.rs (97%) rename src/{libsyntax/ext => libsyntax_expand}/mbe/transcribe.rs (98%) rename src/{libsyntax/ext => libsyntax_expand}/placeholders.rs (97%) rename src/{libsyntax/ext => libsyntax_expand}/proc_macro.rs (88%) rename src/{libsyntax/ext => libsyntax_expand}/proc_macro_server.rs (98%) diff --git a/Cargo.lock b/Cargo.lock index 6d40b1989279..a5a7521abde1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3112,6 +3112,7 @@ dependencies = [ "serialize", "smallvec", "syntax", + "syntax_expand", "syntax_pos", ] @@ -3427,6 +3428,7 @@ dependencies = [ "rustc_target", "serialize", "syntax", + "syntax_expand", "syntax_pos", "tempfile", ] @@ -3559,6 +3561,7 @@ dependencies = [ "serialize", "smallvec", "syntax", + "syntax_expand", "syntax_ext", "syntax_pos", "tempfile", @@ -3630,6 +3633,7 @@ dependencies = [ "smallvec", "stable_deref_trait", "syntax", + "syntax_expand", "syntax_pos", ] @@ -3678,6 +3682,7 @@ dependencies = [ "rustc_index", "rustc_target", "syntax", + "syntax_expand", "syntax_pos", ] @@ -3695,6 +3700,7 @@ dependencies = [ "rustc", "rustc_metadata", "syntax", + "syntax_expand", "syntax_pos", ] @@ -3723,6 +3729,7 @@ dependencies = [ "rustc_metadata", "smallvec", "syntax", + "syntax_expand", "syntax_pos", ] @@ -4336,6 +4343,25 @@ dependencies = [ "syntax_pos", ] +[[package]] +name = "syntax_expand" +version = "0.0.0" +dependencies = [ + "bitflags", + "lazy_static 1.3.0", + "log", + "rustc_data_structures", + "rustc_errors", + "rustc_index", + "rustc_lexer", + "rustc_target", + "scoped-tls", + "serialize", + "smallvec", + "syntax", + "syntax_pos", +] + [[package]] name = "syntax_ext" version = "0.0.0" @@ -4347,6 +4373,7 @@ dependencies = [ "rustc_target", "smallvec", "syntax", + "syntax_expand", "syntax_pos", ] diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 9b3609eca3e6..cf9f36ca37c9 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -29,6 +29,7 @@ rustc_index = { path = "../librustc_index" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } +syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } backtrace = "0.3.3" parking_lot = "0.9" diff --git a/src/librustc/hir/def.rs b/src/librustc/hir/def.rs index f7d31ca06ee5..a071a539e01d 100644 --- a/src/librustc/hir/def.rs +++ b/src/librustc/hir/def.rs @@ -6,7 +6,7 @@ use crate::util::nodemap::DefIdMap; use syntax::ast; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use syntax::ast::NodeId; use syntax_pos::Span; use rustc_macros::HashStable; diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index e9788a558124..d5287fd415b7 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -64,15 +64,15 @@ use syntax::ptr::P as AstP; use syntax::ast::*; use syntax::errors; -use syntax::ext::base::SpecialDerives; -use syntax::ext::hygiene::ExpnId; +use syntax_expand::base::SpecialDerives; use syntax::print::pprust; -use syntax::tokenstream::{TokenStream, TokenTree}; use syntax::parse::token::{self, Nonterminal, Token}; +use syntax::tokenstream::{TokenStream, TokenTree}; 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::hygiene::ExpnId; use syntax_pos::Span; const HIR_ID_COUNTER_LOCKED: u32 = 0xFFFFFFFF; diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 548a2fedfff6..73d2ac5c134d 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -18,7 +18,7 @@ use syntax::attr; use syntax::ast::*; use syntax::visit::{self, Visitor}; -use syntax::ext::base::SpecialDerives; +use syntax_expand::base::SpecialDerives; use syntax::source_map::{respan, DesugaringKind, Spanned}; use syntax::symbol::{kw, sym}; use syntax_pos::Span; diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 1997e2aab35e..fbef95fec7dc 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -2,7 +2,7 @@ use crate::hir::def_id::DefIndex; use syntax::ast::*; -use syntax::ext::hygiene::ExpnId; +use syntax_expand::hygiene::ExpnId; use syntax::visit; use syntax::symbol::{kw, sym}; use syntax::parse::token::{self, Token}; diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 71bf230e37de..cc099fcc40f6 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -17,7 +17,7 @@ use std::fmt::Write; use std::hash::Hash; use syntax::ast; -use syntax::ext::hygiene::ExpnId; +use syntax_expand::hygiene::ExpnId; use syntax::symbol::{Symbol, sym, InternedString}; use syntax_pos::{Span, DUMMY_SP}; diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 16c4ab7187de..f839087ec027 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -20,7 +20,7 @@ use rustc_index::vec::IndexVec; use syntax::ast::{self, Name, NodeId}; use syntax::source_map::Spanned; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use syntax_pos::{Span, DUMMY_SP}; pub mod blocks; diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 3e6b271b8349..14d0673ecc03 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -13,7 +13,7 @@ use syntax::ast; use syntax::source_map::SourceMap; -use syntax::ext::hygiene::SyntaxContext; +use syntax_expand::hygiene::SyntaxContext; use syntax::symbol::Symbol; use syntax::tokenstream::DelimSpan; use syntax_pos::{Span, DUMMY_SP}; diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index 23a2f115e05e..defc3fb25bc5 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -59,7 +59,7 @@ fn to_stable_hash_key(&self, Intel }); -impl_stable_hash_for!(enum ::syntax::ext::base::MacroKind { +impl_stable_hash_for!(enum ::syntax_expand::base::MacroKind { Bang, Attr, Derive, diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index b31efc24e52d..7443cca822a9 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -39,7 +39,7 @@ use syntax::source_map::{MultiSpan, ExpnKind, DesugaringKind}; use syntax::early_buffered_lints::BufferedEarlyLintId; use syntax::edition::Edition; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index c59df146629f..b65bf2230b39 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -24,7 +24,7 @@ use errors::annotate_snippet_emitter_writer::{AnnotateSnippetEmitterWriter}; use syntax::ast::{self, NodeId}; use syntax::edition::Edition; -use syntax::ext::allocator::AllocatorKind; +use syntax_expand::allocator::AllocatorKind; use syntax::feature_gate::{self, AttributeType}; use syntax::json::JsonEmitter; use syntax::source_map; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 65aea7b459f8..ab9fb1df6828 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -45,7 +45,7 @@ use std::ops::Range; use syntax::ast::{self, Name, Ident, NodeId}; use syntax::attr; -use syntax::ext::hygiene::ExpnId; +use syntax_expand::hygiene::ExpnId; use syntax::symbol::{kw, sym, Symbol, InternedString}; use syntax_pos::Span; diff --git a/src/librustc_codegen_llvm/allocator.rs b/src/librustc_codegen_llvm/allocator.rs index f31765cea4f1..8c60c030eacd 100644 --- a/src/librustc_codegen_llvm/allocator.rs +++ b/src/librustc_codegen_llvm/allocator.rs @@ -3,7 +3,7 @@ use crate::attributes; use libc::c_uint; use rustc::ty::TyCtxt; -use syntax::ext::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; +use syntax_expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use crate::ModuleLlvm; use crate::llvm::{self, False, True}; diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index fde04a68457d..9b55bef0c514 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -39,6 +39,7 @@ #[macro_use] extern crate log; extern crate syntax; +extern crate syntax_expand; extern crate syntax_pos; extern crate rustc_errors as errors; @@ -48,7 +49,7 @@ use rustc_codegen_ssa::CompiledModule; use errors::{FatalError, Handler}; use rustc::dep_graph::WorkProduct; -use syntax::ext::allocator::AllocatorKind; +use syntax_expand::allocator::AllocatorKind; use syntax_pos::symbol::InternedString; pub use llvm_util::target_features; use std::any::Any; diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index c7d09a423d5e..6992f93d9994 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -21,6 +21,7 @@ tempfile = "3.1" rustc_serialize = { path = "../libserialize", package = "serialize" } syntax = { path = "../libsyntax" } +syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } rustc = { path = "../librustc" } rustc_apfloat = { path = "../librustc_apfloat" } diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 9078f77f1f7a..d866a10f0693 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -14,7 +14,7 @@ use rustc::ty::subst::SubstsRef; use rustc::util::nodemap::{FxHashMap, DefIdMap}; use rustc_index::vec::IndexVec; -use syntax::ext::allocator::ALLOCATOR_METHODS; +use syntax_expand::allocator::ALLOCATOR_METHODS; pub type ExportedSymbols = FxHashMap< CrateNum, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 5339134a2a84..856c280cac0f 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -27,7 +27,7 @@ use rustc_errors::emitter::{Emitter}; use rustc_target::spec::MergeFunctions; use syntax::attr; -use syntax::ext::hygiene::ExpnId; +use syntax_expand::hygiene::ExpnId; use syntax_pos::symbol::{Symbol, sym}; use jobserver::{Client, Acquired}; diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index a7faf4eaf102..7cae3e9ade59 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -9,7 +9,7 @@ use rustc_codegen_utils::codegen_backend::CodegenBackend; use std::sync::Arc; use std::sync::mpsc; -use syntax::ext::allocator::AllocatorKind; +use syntax_expand::allocator::AllocatorKind; use syntax_pos::symbol::InternedString; pub trait BackendTypes { diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index bed5febb72ed..7a0d931ca732 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -15,6 +15,7 @@ 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" } +syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } rustc_serialize = { path = "../libserialize", package = "serialize" } rustc = { path = "../librustc" } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 396c5610251a..89de5714695d 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -35,7 +35,7 @@ use rustc_typeck as typeck; use syntax::{self, ast, visit}; use syntax::early_buffered_lints::BufferedEarlyLint; -use syntax::ext::base::{NamedSyntaxExtension, ExtCtxt}; +use syntax_expand::base::{NamedSyntaxExtension, ExtCtxt}; use syntax::mut_visit::MutVisitor; use syntax::parse::{self, PResult}; use syntax::util::node_count::NodeCounter; @@ -397,12 +397,12 @@ fn configure_and_expand_inner<'a>( // Create the config for macro expansion let features = sess.features_untracked(); - let cfg = syntax::ext::expand::ExpansionConfig { + let cfg = syntax_expand::expand::ExpansionConfig { features: Some(&features), recursion_limit: *sess.recursion_limit.get(), trace_mac: sess.opts.debugging_opts.trace_macros, should_test: sess.opts.test, - ..syntax::ext::expand::ExpansionConfig::default(crate_name.to_string()) + ..syntax_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver); @@ -559,7 +559,7 @@ pub fn lower_to_hir( // Discard hygiene data, which isn't required after lowering to HIR. if !sess.opts.debugging_opts.keep_hygiene_data { - syntax::ext::hygiene::clear_syntax_context_map(); + syntax_expand::hygiene::clear_syntax_context_map(); } Ok(hir_forest) diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 032470e1400a..18192e35f8a2 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -22,4 +22,5 @@ rustc_index = { path = "../librustc_index" } rustc_serialize = { path = "../libserialize", package = "serialize" } stable_deref_trait = "1.0.0" syntax = { path = "../libsyntax" } +syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 9850121d2ce5..6a2da5d49887 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -26,7 +26,7 @@ use syntax::ast; use syntax::attr; -use syntax::ext::allocator::{global_allocator_spans, AllocatorKind}; +use syntax_expand::allocator::{global_allocator_spans, AllocatorKind}; use syntax::symbol::{Symbol, sym}; use syntax::{span_err, span_fatal}; use syntax_pos::{Span, DUMMY_SP}; diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index a5a458e49a38..9a0b98ffb73a 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -11,7 +11,7 @@ use rustc::util::nodemap::FxHashMap; use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell}; use syntax::ast; -use syntax::ext::base::SyntaxExtension; +use syntax_expand::base::SyntaxExtension; use syntax_pos; use proc_macro::bridge::client::ProcMacro; diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 6969d608d76d..37f3726124a2 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -32,11 +32,11 @@ use syntax::ast::{self, Ident}; use syntax::source_map::{self, respan, Spanned}; use syntax::symbol::{Symbol, sym}; -use syntax::ext::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension}; +use syntax_expand::base::{MacroKind, SyntaxExtensionKind, SyntaxExtension}; use syntax_pos::{self, Span, BytePos, Pos, DUMMY_SP, symbol::{InternedString}}; use log::debug; use proc_macro::bridge::client::ProcMacro; -use syntax::ext::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; +use syntax_expand::proc_macro::{AttrProcMacro, ProcMacroDerive, BangProcMacro}; crate struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 03a14f886455..ac20284233a9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -31,7 +31,7 @@ use std::u32; use syntax::ast; use syntax::attr; -use syntax::ext::proc_macro::is_proc_macro_attr; +use syntax_expand::proc_macro::is_proc_macro_attr; use syntax::source_map::Spanned; use syntax::symbol::{kw, sym, Ident, Symbol}; use syntax_pos::{self, FileName, SourceFile, Span}; diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 9d29a2303144..118deb560d62 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -13,6 +13,7 @@ log = "0.4" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } syntax = { path = "../libsyntax" } +syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } errors = { path = "../librustc_errors", package = "rustc_errors" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs index 43c4f720ad41..74de31263d39 100644 --- a/src/librustc_passes/ast_validation.rs +++ b/src/librustc_passes/ast_validation.rs @@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashMap; use syntax::ast::*; use syntax::attr; -use syntax::ext::proc_macro::is_proc_macro_attr; +use syntax_expand::proc_macro::is_proc_macro_attr; use syntax::feature_gate::is_builtin_attr; use syntax::source_map::Spanned; use syntax::symbol::{kw, sym}; diff --git a/src/librustc_plugin/Cargo.toml b/src/librustc_plugin/Cargo.toml index 3f11430dc82c..e8bf4e7ea8ff 100644 --- a/src/librustc_plugin/Cargo.toml +++ b/src/librustc_plugin/Cargo.toml @@ -14,4 +14,5 @@ doctest = false rustc = { path = "../librustc" } rustc_metadata = { path = "../librustc_metadata" } syntax = { path = "../libsyntax" } +syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_plugin/lib.rs b/src/librustc_plugin/lib.rs index 4e1a47c503e5..38738e20630c 100644 --- a/src/librustc_plugin/lib.rs +++ b/src/librustc_plugin/lib.rs @@ -21,7 +21,7 @@ //! extern crate syntax_pos; //! //! use rustc_driver::plugin::Registry; -//! use syntax::ext::base::{ExtCtxt, MacResult}; +//! use syntax_expand::base::{ExtCtxt, MacResult}; //! use syntax_pos::Span; //! use syntax::tokenstream::TokenTree; //! diff --git a/src/librustc_plugin/registry.rs b/src/librustc_plugin/registry.rs index bb3c950edae3..b826dd911983 100644 --- a/src/librustc_plugin/registry.rs +++ b/src/librustc_plugin/registry.rs @@ -4,8 +4,8 @@ use rustc::session::Session; use rustc::util::nodemap::FxHashMap; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension}; -use syntax::ext::base::MacroExpanderFn; +use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension}; +use syntax_expand::base::MacroExpanderFn; use syntax::symbol::Symbol; use syntax::ast; use syntax::feature_gate::AttributeType; diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index 936e72ef2c57..06bf30859898 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -14,6 +14,7 @@ doctest = false bitflags = "1.0" log = "0.4" syntax = { path = "../libsyntax" } +syntax_expand = { path = "../libsyntax_expand" } rustc = { path = "../librustc" } arena = { path = "../libarena" } errors = { path = "../librustc_errors", package = "rustc_errors" } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 0d5361fe8d84..eadae52c250a 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -32,9 +32,9 @@ use syntax::ast::{self, Block, ForeignItem, ForeignItemKind, Item, ItemKind, NodeId}; use syntax::ast::{MetaItemKind, StmtKind, TraitItem, TraitItemKind}; -use syntax::ext::base::{MacroKind, SyntaxExtension}; -use syntax::ext::expand::AstFragment; -use syntax::ext::hygiene::ExpnId; +use syntax_expand::base::{MacroKind, SyntaxExtension}; +use syntax_expand::expand::AstFragment; +use syntax_expand::hygiene::ExpnId; use syntax::feature_gate::is_builtin_attr; use syntax::parse::token::{self, Token}; use syntax::print::pprust; diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index de8758086709..5647d5b2794a 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -10,7 +10,7 @@ use rustc::ty::{self, DefIdTree}; use rustc::util::nodemap::FxHashSet; use syntax::ast::{self, Ident, Path}; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use syntax::feature_gate::BUILTIN_ATTRIBUTES; use syntax::source_map::SourceMap; use syntax::struct_span_err; diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index ace9903a835f..412734eabe05 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -13,7 +13,7 @@ use rustc::session::config::nightly_options; use rustc::util::nodemap::FxHashSet; use syntax::ast::{self, Expr, ExprKind, Ident, NodeId, Path, Ty, TyKind}; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use syntax::symbol::kw; use syntax::util::lev_distance::find_best_match_for_name; use syntax_pos::Span; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e5b0ef89a417..17d8f0f211a9 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -35,18 +35,16 @@ use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::CStore; -use syntax::ext::hygiene::{ExpnId, Transparency, SyntaxContext}; +use syntax_expand::hygiene::{ExpnId, Transparency, SyntaxContext}; +use syntax_expand::base::{SyntaxExtension, MacroKind, SpecialDerives}; +use syntax::{struct_span_err, unwrap_or}; +use syntax::attr; use syntax::ast::{self, Name, NodeId, Ident, FloatTy, IntTy, UintTy}; -use syntax::ext::base::{SyntaxExtension, MacroKind, SpecialDerives}; +use syntax::ast::{ItemKind, Path, CRATE_NODE_ID, Crate}; use syntax::print::pprust; use syntax::symbol::{kw, sym}; - -use syntax::visit::{self, Visitor}; -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::visit::{self, Visitor}; use syntax_pos::{Span, DUMMY_SP}; use errors::{Applicability, DiagnosticBuilder}; diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 49186088fa06..c91a0b2ed985 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -14,11 +14,11 @@ use syntax::ast::{self, NodeId, Ident}; use syntax::attr::StabilityLevel; use syntax::edition::Edition; -use syntax::ext::base::{self, InvocationRes, Indeterminate, SpecialDerives}; -use syntax::ext::base::{MacroKind, SyntaxExtension}; -use syntax::ext::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind}; -use syntax::ext::hygiene::{self, ExpnId, ExpnData, ExpnKind}; -use syntax::ext::compile_declarative_macro; +use syntax_expand::base::{self, InvocationRes, Indeterminate, SpecialDerives}; +use syntax_expand::base::{MacroKind, SyntaxExtension}; +use syntax_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind}; +use syntax_expand::hygiene::{self, ExpnId, ExpnData, ExpnKind}; +use syntax_expand::compile_declarative_macro; use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name}; use syntax::feature_gate::GateIssue; use syntax::print::pprust; diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 56fd2da2576f..424bf31a7850 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -28,7 +28,7 @@ use rustc::{bug, span_bug}; use syntax::ast::{Ident, Name, NodeId, CRATE_NODE_ID}; -use syntax::ext::hygiene::ExpnId; +use syntax_expand::hygiene::ExpnId; use syntax::symbol::kw; use syntax::util::lev_distance::find_best_match_for_name; use syntax::{struct_span_err, unwrap_or}; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 532c5f67bf3b..63350b2a5d25 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -3,7 +3,7 @@ use std::iter::once; use syntax::ast; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use syntax::symbol::sym; use syntax_pos::Span; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 212a09ee6e63..ba00631dc6ca 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -28,7 +28,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use syntax::ast::{self, AttrStyle, Ident}; use syntax::attr; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use syntax::source_map::DUMMY_SP; use syntax::symbol::{Symbol, kw, sym}; use syntax::symbol::InternedString; diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 6e453561f6da..0dc094ae329f 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -4,7 +4,7 @@ use syntax::ast; use syntax::ast::Name; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use syntax_pos::{self, Span}; use rustc::hir; diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 5fb9afd6c49a..e015739b03c4 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -1,7 +1,7 @@ //! Item types. use std::fmt; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use crate::clean; /// Item type. Corresponds to `clean::ItemEnum` variants. diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b726ad1e0d63..72a72e892814 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -45,11 +45,11 @@ use serialize::json::{ToJson, Json, as_json}; use syntax::ast; use syntax::edition::Edition; -use syntax::ext::base::MacroKind; +use syntax::feature_gate::UnstableFeatures; use syntax::print::pprust; use syntax::source_map::FileName; -use syntax::feature_gate::UnstableFeatures; use syntax::symbol::{Symbol, sym}; +use syntax_expand::base::MacroKind; use rustc::hir::def_id::DefId; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 6bcb4a817d78..8cd32a3d1b50 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -34,6 +34,7 @@ extern crate rustc_lexer; extern crate serialize; extern crate syntax; +extern crate syntax_expand; extern crate syntax_pos; extern crate test as testing; #[macro_use] extern crate log; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 9186ed514202..4270b162bafa 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -7,7 +7,7 @@ use rustc_resolve::ParentScope; use syntax; use syntax::ast::{self, Ident}; -use syntax::ext::base::SyntaxExtensionKind; +use syntax_expand::base::SyntaxExtensionKind; use syntax::feature_gate::UnstableFeatures; use syntax::symbol::Symbol; use syntax_pos::DUMMY_SP; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index b6a90e1fb988..70c30687dabc 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -8,7 +8,7 @@ use rustc::util::nodemap::{FxHashSet, FxHashMap}; use rustc::ty::TyCtxt; use syntax::ast; -use syntax::ext::base::MacroKind; +use syntax_expand::base::MacroKind; use syntax::source_map::Spanned; use syntax::symbol::sym; use syntax_pos::{self, Span}; diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 65257c7e9855..402c2cad72f9 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -298,14 +298,14 @@ pub fn meta(&self) -> Option { Ok(result) } - crate fn parse_derive_paths<'a>(&self, sess: &'a ParseSess) -> PResult<'a, Vec> { + 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, |p| p.parse_derive_paths()) } - crate fn parse_meta<'a>(&self, sess: &'a ParseSess) -> PResult<'a, MetaItem> { + pub 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/config.rs b/src/libsyntax/config.rs index ee5a4eeb3a31..54dc95291d67 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -56,6 +56,7 @@ pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition, (krate, features) } +#[macro_export] macro_rules! configure { ($this:ident, $node:ident) => { match $this.configure($node) { diff --git a/src/libsyntax/feature_gate/check.rs b/src/libsyntax/feature_gate/check.rs index c07b6050afe3..172511f0f099 100644 --- a/src/libsyntax/feature_gate/check.rs +++ b/src/libsyntax/feature_gate/check.rs @@ -56,7 +56,7 @@ macro_rules! gate_feature { }; } -crate fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) { +pub fn check_attribute(attr: &ast::Attribute, parse_sess: &ParseSess, features: &Features) { PostExpansionVisitor { parse_sess, features }.visit_attribute(attr) } diff --git a/src/libsyntax/feature_gate/mod.rs b/src/libsyntax/feature_gate/mod.rs index ca13ab362050..ba970618c0e1 100644 --- a/src/libsyntax/feature_gate/mod.rs +++ b/src/libsyntax/feature_gate/mod.rs @@ -58,8 +58,7 @@ pub struct Feature { deprecated_attributes, is_builtin_attr, is_builtin_attr_name, }; pub use check::{ - check_crate, get_features, feature_err, emit_feature_err, + check_crate, check_attribute, get_features, feature_err, emit_feature_err, Stability, GateIssue, UnstableFeatures, EXPLAIN_STMT_ATTR_SYNTAX, EXPLAIN_UNSIZED_TUPLE_COERCION, }; -crate use check::check_attribute; diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index fa75f5624f8f..a68b7fdf931a 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -13,17 +13,12 @@ #![feature(crate_visibility_modifier)] #![feature(label_break_value)] #![feature(nll)] -#![feature(proc_macro_diagnostic)] -#![feature(proc_macro_internals)] -#![feature(proc_macro_span)] #![feature(try_trait)] #![feature(slice_patterns)] #![feature(unicode_internals)] #![recursion_limit="256"] -extern crate proc_macro; - pub use errors; use rustc_data_structures::sync::Lock; use rustc_index::bit_set::GrowableBitSet; @@ -34,26 +29,7 @@ #[cfg(test)] mod tests; -const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments"); - -// A variant of 'try!' that panics on an Err. This is used as a crutch on the -// way towards a non-panic!-prone parser. It should be used for fatal parsing -// errors; eventually we plan to convert all code using panictry to just use -// normal try. -#[macro_export] -macro_rules! panictry { - ($e:expr) => ({ - use std::result::Result::{Ok, Err}; - use errors::FatalError; - match $e { - Ok(e) => e, - Err(mut e) => { - e.emit(); - FatalError.raise() - } - } - }) -} +pub const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments"); // A variant of 'panictry!' that works on a Vec instead of a single DiagnosticBuilder. macro_rules! panictry_buffer { @@ -157,19 +133,4 @@ pub mod print { mod helpers; } -pub mod ext { - mod placeholders; - mod proc_macro_server; - - pub use syntax_pos::hygiene; - pub use mbe::macro_rules::compile_declarative_macro; - pub mod allocator; - pub mod base; - pub mod build; - pub mod expand; - pub mod proc_macro; - - crate mod mbe; -} - pub mod early_buffered_lints; diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 54e523430e45..14e1696610a4 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). - crate fn from_lit_kind(kind: LitKind, span: Span) -> Lit { + pub 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 7914fdbf9788..64ec943294ae 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5,7 +5,7 @@ mod module; mod ty; mod path; -crate use path::PathStyle; +pub use path::PathStyle; mod stmt; mod generics; mod diagnostics; @@ -130,7 +130,7 @@ pub struct Parser<'a> { /// 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. - crate root_module_name: Option, + pub root_module_name: Option, expected_tokens: Vec, token_cursor: TokenCursor, desugar_doc_comments: bool, @@ -148,7 +148,7 @@ pub struct Parser<'a> { /// error. pub(super) unclosed_delims: Vec, last_unexpected_token_span: Option, - crate last_type_ascription: Option<(Span, bool /* likely path typo */)>, + pub last_type_ascription: Option<(Span, bool /* likely path typo */)>, /// If present, this `Parser` is not parsing Rust code but rather a macro call. subparser_name: Option<&'static str>, } @@ -330,7 +330,7 @@ enum TokenExpectType { } impl<'a> Parser<'a> { - crate fn new( + pub fn new( sess: &'a ParseSess, tokens: TokenStream, directory: Option>, @@ -1003,7 +1003,7 @@ fn parse_or_use_outer_attributes( } } - crate fn process_potential_macro_variable(&mut self) { + pub fn process_potential_macro_variable(&mut self) { self.token = match self.token.kind { token::Dollar if self.token.span.from_expansion() && self.look_ahead(1, |t| t.is_ident()) => { @@ -1037,7 +1037,7 @@ fn parse_or_use_outer_attributes( } /// Parses a single token tree from the input. - crate fn parse_token_tree(&mut self) -> TokenTree { + pub fn parse_token_tree(&mut self) -> TokenTree { match self.token.kind { token::OpenDelim(..) => { let frame = mem::replace(&mut self.token_cursor.frame, @@ -1099,7 +1099,7 @@ fn is_crate_vis(&self) -> bool { /// 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. - crate fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibility> { + pub 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)); diff --git a/src/libsyntax/parse/parser/diagnostics.rs b/src/libsyntax/parse/parser/diagnostics.rs index a6884ec2c722..32a41bb0e271 100644 --- a/src/libsyntax/parse/parser/diagnostics.rs +++ b/src/libsyntax/parse/parser/diagnostics.rs @@ -170,7 +170,7 @@ fn recovered(qself: Option, path: ast::Path) -> Self { } impl<'a> Parser<'a> { - crate fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { + pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { self.span_fatal(self.token.span, m) } @@ -190,11 +190,11 @@ pub(super) fn span_err>(&self, sp: S, m: &str) { self.sess.span_diagnostic.span_err(sp, m) } - crate fn struct_span_err>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { + pub fn struct_span_err>(&self, sp: S, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_err(sp, m) } - crate fn span_bug>(&self, sp: S, m: &str) -> ! { + pub fn span_bug>(&self, sp: S, m: &str) -> ! { self.sess.span_diagnostic.span_bug(sp, m) } diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index bf9526dece23..273f5a5ffa36 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -1233,7 +1233,7 @@ pub(super) fn expect_no_suffix(&self, sp: Span, kind: &str, suffix: Option PResult<'a, P> { + pub fn parse_literal_maybe_minus(&mut self) -> PResult<'a, P> { maybe_whole_expr!(self); let minus_lo = self.token.span; diff --git a/src/libsyntax/parse/parser/item.rs b/src/libsyntax/parse/parser/item.rs index 6a1cbd2ebb77..0acfd1450d81 100644 --- a/src/libsyntax/parse/parser/item.rs +++ b/src/libsyntax/parse/parser/item.rs @@ -674,7 +674,7 @@ fn parse_impl_body(&mut self) -> PResult<'a, (Vec, Vec)> { } /// Parses an impl item. - crate fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { + pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, ImplItem> { maybe_whole!(self, NtImplItem, |x| x); let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; @@ -850,7 +850,7 @@ fn parse_item_trait(&mut self, unsafety: Unsafety) -> PResult<'a, ItemInfo> { } /// Parses the items in a trait declaration. - crate fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { + pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, TraitItem> { maybe_whole!(self, NtTraitItem, |x| x); let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; @@ -1116,7 +1116,7 @@ fn parse_item_foreign_mod( } /// Parses a foreign item. - crate fn parse_foreign_item(&mut self, extern_sp: Span) -> PResult<'a, ForeignItem> { + pub fn parse_foreign_item(&mut self, extern_sp: Span) -> PResult<'a, ForeignItem> { maybe_whole!(self, NtForeignItem, |ni| ni); let attrs = self.parse_outer_attributes()?; diff --git a/src/libsyntax/parse/parser/pat.rs b/src/libsyntax/parse/parser/pat.rs index b30e0636bb16..af795e51792f 100644 --- a/src/libsyntax/parse/parser/pat.rs +++ b/src/libsyntax/parse/parser/pat.rs @@ -34,7 +34,7 @@ impl<'a> Parser<'a> { /// Corresponds to `pat` in RFC 2535 and does not admit or-patterns /// at the top level. Used when parsing the parameters of lambda expressions, /// functions, function pointers, and `pat` macro fragments. - crate fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P> { + pub fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P> { self.parse_pat_with_range_pat(true, expected) } diff --git a/src/libsyntax/parse/parser/path.rs b/src/libsyntax/parse/parser/path.rs index 0f28fb11cde4..639d61a2b5cd 100644 --- a/src/libsyntax/parse/parser/path.rs +++ b/src/libsyntax/parse/parser/path.rs @@ -13,7 +13,7 @@ /// Specifies how to parse a path. #[derive(Copy, Clone, PartialEq)] -crate enum PathStyle { +pub enum PathStyle { /// In some contexts, notably in expressions, paths with generic arguments are ambiguous /// with something else. For example, in expressions `segment < ....` can be interpreted /// as a comparison and `segment ( ....` can be interpreted as a function call. @@ -88,7 +88,7 @@ pub(super) fn parse_qpath(&mut self, style: PathStyle) -> PResult<'a, (QSelf, Pa /// `a::b::C::` (with disambiguator) /// `Fn(Args)` (without disambiguator) /// `Fn::(Args)` (with disambiguator) - crate fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { + pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, Path> { maybe_whole!(self, NtPath, |path| { if style == PathStyle::Mod && path.segments.iter().any(|segment| segment.args.is_some()) { diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index f656bc11e1ca..4b1fdb2eef3a 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -19,7 +19,7 @@ impl<'a> Parser<'a> { /// Parses a statement. This stops just before trailing semicolons on everything but items. /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. - crate fn parse_stmt(&mut self) -> PResult<'a, Option> { + pub fn parse_stmt(&mut self) -> PResult<'a, Option> { Ok(self.parse_stmt_(true)) } @@ -299,7 +299,7 @@ fn is_auto_trait_item(&self) -> bool { } /// Parses a block. No inner attributes are allowed. - crate fn parse_block(&mut self) -> PResult<'a, P> { + pub fn parse_block(&mut self) -> PResult<'a, P> { maybe_whole!(self, NtBlock, |x| x); let lo = self.token.span; @@ -421,7 +421,7 @@ pub(super) fn parse_block_tail( } /// Parses a statement, including the trailing semicolon. - crate fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option> { + pub fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option> { // Skip looking for a trailing semicolon when we have an interpolated statement. maybe_whole!(self, NtStmt, |x| Some(x)); diff --git a/src/libsyntax/parse/parser/ty.rs b/src/libsyntax/parse/parser/ty.rs index ae9f4d06c055..86c94b680b2c 100644 --- a/src/libsyntax/parse/parser/ty.rs +++ b/src/libsyntax/parse/parser/ty.rs @@ -433,13 +433,13 @@ pub(super) fn parse_late_bound_lifetime_defs(&mut self) -> PResult<'a, Vec bool { + pub fn check_lifetime(&mut self) -> bool { self.expected_tokens.push(TokenType::Lifetime); self.token.is_lifetime() } /// Parses a single lifetime `'a` or panics. - crate fn expect_lifetime(&mut self) -> Lifetime { + pub fn expect_lifetime(&mut self) -> Lifetime { if let Some(ident) = self.token.lifetime() { let span = self.token.span; self.bump(); diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index eb74ab2b9192..e527989fb0ba 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -285,7 +285,7 @@ pub fn lit(kind: LitKind, symbol: Symbol, suffix: Option) -> TokenKind { } impl Token { - crate fn new(kind: TokenKind, span: Span) -> Self { + pub fn new(kind: TokenKind, span: Span) -> Self { Token { kind, span } } @@ -295,12 +295,12 @@ impl Token { } /// Recovers a `Token` from an `ast::Ident`. This creates a raw identifier if necessary. - crate fn from_ast_ident(ident: ast::Ident) -> Self { + pub fn from_ast_ident(ident: ast::Ident) -> Self { Token::new(Ident(ident.name, ident.is_raw_guess()), ident.span) } /// Return this token by value and leave a dummy token in its place. - crate fn take(&mut self) -> Self { + pub fn take(&mut self) -> Self { mem::replace(self, Token::dummy()) } @@ -321,7 +321,7 @@ impl Token { } /// Returns `true` if the token can appear at the start of an expression. - crate fn can_begin_expr(&self) -> bool { + pub fn can_begin_expr(&self) -> bool { match self.kind { Ident(name, is_raw) => ident_can_begin_expr(name, self.span, is_raw), // value name or keyword @@ -353,7 +353,7 @@ impl Token { } /// Returns `true` if the token can appear at the start of a type. - crate fn can_begin_type(&self) -> bool { + pub fn can_begin_type(&self) -> bool { match self.kind { Ident(name, is_raw) => ident_can_begin_type(name, self.span, is_raw), // type name or keyword @@ -396,7 +396,7 @@ impl Token { } /// Returns `true` if the token is any literal - crate fn is_lit(&self) -> bool { + pub fn is_lit(&self) -> bool { match self.kind { Literal(..) => true, _ => false, @@ -412,7 +412,7 @@ impl Token { /// Returns `true` if the token is any literal, a minus (which can prefix a literal, /// for example a '-42', or one of the boolean idents). - crate fn can_begin_literal_or_bool(&self) -> bool { + pub fn can_begin_literal_or_bool(&self) -> bool { match self.kind { Literal(..) | BinOp(Minus) => true, Ident(name, false) if name.is_bool_lit() => true, diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 0ff1c26bac2b..db6832d64232 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -156,7 +156,7 @@ pub enum IsJoint { impl TokenStream { /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream` /// separating the two arguments with a comma for diagnostic suggestions. - pub(crate) fn add_comma(&self) -> Option<(TokenStream, Span)> { + pub fn add_comma(&self) -> Option<(TokenStream, Span)> { // Used to suggest if a user writes `foo!(a b);` let mut suggestion = None; let mut iter = self.0.iter().enumerate().peekable(); diff --git a/src/libsyntax_expand/Cargo.toml b/src/libsyntax_expand/Cargo.toml new file mode 100644 index 000000000000..f063753f5994 --- /dev/null +++ b/src/libsyntax_expand/Cargo.toml @@ -0,0 +1,26 @@ +[package] +authors = ["The Rust Project Developers"] +name = "syntax_expand" +version = "0.0.0" +edition = "2018" +build = false + +[lib] +name = "syntax_expand" +path = "lib.rs" +doctest = false + +[dependencies] +bitflags = "1.0" +rustc_serialize = { path = "../libserialize", package = "serialize" } +log = "0.4" +scoped-tls = "1.0" +lazy_static = "1.0.0" +syntax_pos = { path = "../libsyntax_pos" } +errors = { path = "../librustc_errors", package = "rustc_errors" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_index = { path = "../librustc_index" } +rustc_lexer = { path = "../librustc_lexer" } +rustc_target = { path = "../librustc_target" } +smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } +syntax = { path = "../libsyntax" } diff --git a/src/libsyntax/ext/allocator.rs b/src/libsyntax_expand/allocator.rs similarity index 96% rename from src/libsyntax/ext/allocator.rs rename to src/libsyntax_expand/allocator.rs index 99aeb5414c5d..3526be17721a 100644 --- a/src/libsyntax/ext/allocator.rs +++ b/src/libsyntax_expand/allocator.rs @@ -1,5 +1,5 @@ -use crate::{ast, attr, visit}; -use crate::symbol::{sym, Symbol}; +use syntax::{ast, attr, visit}; +use syntax::symbol::{sym, Symbol}; use syntax_pos::Span; #[derive(Clone, Copy)] diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax_expand/base.rs similarity index 98% rename from src/libsyntax/ext/base.rs rename to src/libsyntax_expand/base.rs index 01be5642d5c4..593e06f29b93 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax_expand/base.rs @@ -1,18 +1,19 @@ -use crate::ast::{self, NodeId, Attribute, Name, PatKind}; -use crate::attr::{self, HasAttrs, Stability, Deprecation}; -use crate::source_map::SourceMap; -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, 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}; -use crate::visit::Visitor; +use crate::expand::{self, AstFragment, Invocation}; +use crate::hygiene::ExpnId; + +use syntax::ast::{self, NodeId, Attribute, Name, PatKind}; +use syntax::attr::{self, HasAttrs, Stability, Deprecation}; +use syntax::source_map::SourceMap; +use syntax::edition::Edition; +use syntax::mut_visit::{self, MutVisitor}; +use syntax::parse::{self, parser, DirectoryOwnership}; +use syntax::parse::token; +use syntax::ptr::P; +use syntax::sess::ParseSess; +use syntax::symbol::{kw, sym, Ident, Symbol}; +use syntax::{ThinVec, MACRO_ARGUMENTS}; +use syntax::tokenstream::{self, TokenStream}; +use syntax::visit::Visitor; use errors::{DiagnosticBuilder, DiagnosticId}; use smallvec::{smallvec, SmallVec}; diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax_expand/build.rs similarity index 98% rename from src/libsyntax/ext/build.rs rename to src/libsyntax_expand/build.rs index 8c5289671c98..105ffe3ee8a9 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax_expand/build.rs @@ -1,10 +1,11 @@ -use crate::ast::{self, Ident, Expr, BlockCheckMode, UnOp, PatKind}; -use crate::attr; -use crate::source_map::{respan, Spanned}; -use crate::ext::base::ExtCtxt; -use crate::ptr::P; -use crate::symbol::{kw, sym, Symbol}; -use crate::ThinVec; +use crate::base::ExtCtxt; + +use syntax::ast::{self, Ident, Expr, BlockCheckMode, UnOp, PatKind}; +use syntax::attr; +use syntax::source_map::{respan, Spanned}; +use syntax::ptr::P; +use syntax::symbol::{kw, sym, Symbol}; +use syntax::ThinVec; use syntax_pos::{Pos, Span}; diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax_expand/expand.rs similarity index 91% rename from src/libsyntax/ext/expand.rs rename to src/libsyntax_expand/expand.rs index 44a51a017104..47b4bca314a2 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -1,24 +1,26 @@ -use crate::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path}; -use crate::ast::{MacStmtStyle, StmtKind, ItemKind}; -use crate::attr::{self, HasAttrs}; -use crate::source_map::respan; -use crate::config::StripUnconfigured; -use crate::ext::base::*; -use crate::ext::proc_macro::{collect_derives, MarkAttrs}; -use crate::ext::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; -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}; -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::Visitor; -use crate::util::map_in_place::MapInPlace; +use crate::base::*; +use crate::proc_macro::{collect_derives, MarkAttrs}; +use crate::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; +use crate::mbe::macro_rules::annotate_err_with_kind; +use crate::placeholders::{placeholder, PlaceholderExpander}; + +use syntax::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path}; +use syntax::ast::{MacStmtStyle, StmtKind, ItemKind}; +use syntax::attr::{self, HasAttrs}; +use syntax::source_map::respan; +use syntax::configure; +use syntax::config::StripUnconfigured; +use syntax::feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; +use syntax::mut_visit::*; +use syntax::parse::{DirectoryOwnership, PResult}; +use syntax::parse::token; +use syntax::parse::parser::Parser; +use syntax::print::pprust; +use syntax::ptr::P; +use syntax::symbol::{sym, Symbol}; +use syntax::tokenstream::{TokenStream, TokenTree}; +use syntax::visit::Visitor; +use syntax::util::map_in_place::MapInPlace; use errors::{Applicability, FatalError}; use smallvec::{smallvec, SmallVec}; @@ -116,8 +118,8 @@ pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) { } } - impl<'a> MacResult for crate::ext::mbe::macro_rules::ParserAnyMacro<'a> { - $(fn $make_ast(self: Box>) + impl<'a> MacResult for crate::mbe::macro_rules::ParserAnyMacro<'a> { + $(fn $make_ast(self: Box>) -> Option<$AstTy> { Some(self.make(AstFragmentKind::$Kind).$make_ast()) })* @@ -752,9 +754,9 @@ fn parse_ast_fragment( span: Span, ) -> AstFragment { let mut parser = self.cx.new_parser_from_tts(toks); - match parser.parse_ast_fragment(kind, false) { + match parse_ast_fragment(&mut parser, kind, false) { Ok(fragment) => { - parser.ensure_complete_parse(path, kind.name(), span); + ensure_complete_parse(&mut parser, path, kind.name(), span); fragment } Err(mut err) => { @@ -768,100 +770,106 @@ fn parse_ast_fragment( } } -impl<'a> Parser<'a> { - pub fn parse_ast_fragment(&mut self, kind: AstFragmentKind, macro_legacy_warnings: bool) - -> PResult<'a, AstFragment> { - Ok(match kind { - AstFragmentKind::Items => { - let mut items = SmallVec::new(); - while let Some(item) = self.parse_item()? { - items.push(item); - } - AstFragment::Items(items) +pub fn parse_ast_fragment<'a>( + this: &mut Parser<'a>, + kind: AstFragmentKind, + macro_legacy_warnings: bool, +) -> PResult<'a, AstFragment> { + Ok(match kind { + AstFragmentKind::Items => { + let mut items = SmallVec::new(); + while let Some(item) = this.parse_item()? { + items.push(item); } - AstFragmentKind::TraitItems => { - let mut items = SmallVec::new(); - while self.token != token::Eof { - items.push(self.parse_trait_item(&mut false)?); - } - AstFragment::TraitItems(items) - } - AstFragmentKind::ImplItems => { - let mut items = SmallVec::new(); - while self.token != token::Eof { - items.push(self.parse_impl_item(&mut false)?); - } - AstFragment::ImplItems(items) - } - AstFragmentKind::ForeignItems => { - let mut items = SmallVec::new(); - while self.token != token::Eof { - items.push(self.parse_foreign_item(DUMMY_SP)?); - } - AstFragment::ForeignItems(items) - } - AstFragmentKind::Stmts => { - let mut stmts = SmallVec::new(); - while self.token != token::Eof && - // won't make progress on a `}` - self.token != token::CloseDelim(token::Brace) { - if let Some(stmt) = self.parse_full_stmt(macro_legacy_warnings)? { - stmts.push(stmt); - } - } - AstFragment::Stmts(stmts) - } - AstFragmentKind::Expr => AstFragment::Expr(self.parse_expr()?), - AstFragmentKind::OptExpr => { - if self.token != token::Eof { - AstFragment::OptExpr(Some(self.parse_expr()?)) - } else { - AstFragment::OptExpr(None) - } - }, - AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?), - AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat(None)?), - AstFragmentKind::Arms - | AstFragmentKind::Fields - | AstFragmentKind::FieldPats - | AstFragmentKind::GenericParams - | AstFragmentKind::Params - | AstFragmentKind::StructFields - | AstFragmentKind::Variants - => panic!("unexpected AST fragment kind"), - }) - } - - pub fn ensure_complete_parse(&mut self, macro_path: &Path, kind_name: &str, span: Span) { - if self.token != token::Eof { - let msg = format!("macro expansion ignores token `{}` and any following", - self.this_token_to_string()); - // Avoid emitting backtrace info twice. - let def_site_span = self.token.span.with_ctxt(SyntaxContext::root()); - 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", - pprust::path_to_string(¯o_path), - kind_name, - ); - err.note(&msg); - let semi_span = self.sess.source_map().next_point(span); - - let semi_full_span = semi_span.to(self.sess.source_map().next_point(semi_span)); - match self.sess.source_map().span_to_snippet(semi_full_span) { - Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => { - err.span_suggestion( - semi_span, - "you might be missing a semicolon here", - ";".to_owned(), - Applicability::MaybeIncorrect, - ); - } - _ => {} - } - err.emit(); + AstFragment::Items(items) } + AstFragmentKind::TraitItems => { + let mut items = SmallVec::new(); + while this.token != token::Eof { + items.push(this.parse_trait_item(&mut false)?); + } + AstFragment::TraitItems(items) + } + AstFragmentKind::ImplItems => { + let mut items = SmallVec::new(); + while this.token != token::Eof { + items.push(this.parse_impl_item(&mut false)?); + } + AstFragment::ImplItems(items) + } + AstFragmentKind::ForeignItems => { + let mut items = SmallVec::new(); + while this.token != token::Eof { + items.push(this.parse_foreign_item(DUMMY_SP)?); + } + AstFragment::ForeignItems(items) + } + AstFragmentKind::Stmts => { + let mut stmts = SmallVec::new(); + while this.token != token::Eof && + // won't make progress on a `}` + this.token != token::CloseDelim(token::Brace) { + if let Some(stmt) = this.parse_full_stmt(macro_legacy_warnings)? { + stmts.push(stmt); + } + } + AstFragment::Stmts(stmts) + } + AstFragmentKind::Expr => AstFragment::Expr(this.parse_expr()?), + AstFragmentKind::OptExpr => { + if this.token != token::Eof { + AstFragment::OptExpr(Some(this.parse_expr()?)) + } else { + AstFragment::OptExpr(None) + } + }, + AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?), + AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat(None)?), + AstFragmentKind::Arms + | AstFragmentKind::Fields + | AstFragmentKind::FieldPats + | AstFragmentKind::GenericParams + | AstFragmentKind::Params + | AstFragmentKind::StructFields + | AstFragmentKind::Variants + => panic!("unexpected AST fragment kind"), + }) +} + +pub fn ensure_complete_parse<'a>( + this: &mut Parser<'a>, + macro_path: &Path, + kind_name: &str, + span: Span, +) { + if this.token != token::Eof { + let msg = format!("macro expansion ignores token `{}` and any following", + this.this_token_to_string()); + // Avoid emitting backtrace info twice. + let def_site_span = this.token.span.with_ctxt(SyntaxContext::root()); + let mut err = this.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", + pprust::path_to_string(macro_path), + kind_name, + ); + err.note(&msg); + let semi_span = this.sess.source_map().next_point(span); + + let semi_full_span = semi_span.to(this.sess.source_map().next_point(semi_span)); + match this.sess.source_map().span_to_snippet(semi_full_span) { + Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => { + err.span_suggestion( + semi_span, + "you might be missing a semicolon here", + ";".to_owned(), + Applicability::MaybeIncorrect, + ); + } + _ => {} + } + err.emit(); } } diff --git a/src/libsyntax_expand/lib.rs b/src/libsyntax_expand/lib.rs new file mode 100644 index 000000000000..88e69d793973 --- /dev/null +++ b/src/libsyntax_expand/lib.rs @@ -0,0 +1,38 @@ +#![feature(crate_visibility_modifier)] +#![feature(proc_macro_diagnostic)] +#![feature(proc_macro_internals)] +#![feature(proc_macro_span)] + +extern crate proc_macro as pm; + +// A variant of 'try!' that panics on an Err. This is used as a crutch on the +// way towards a non-panic!-prone parser. It should be used for fatal parsing +// errors; eventually we plan to convert all code using panictry to just use +// normal try. +#[macro_export] +macro_rules! panictry { + ($e:expr) => ({ + use std::result::Result::{Ok, Err}; + use errors::FatalError; + match $e { + Ok(e) => e, + Err(mut e) => { + e.emit(); + FatalError.raise() + } + } + }) +} + +mod placeholders; +mod proc_macro_server; + +pub use syntax_pos::hygiene; +pub use mbe::macro_rules::compile_declarative_macro; +pub mod allocator; +pub mod base; +pub mod build; +pub mod expand; +pub mod proc_macro; + +crate mod mbe; diff --git a/src/libsyntax/ext/mbe.rs b/src/libsyntax_expand/mbe.rs similarity index 98% rename from src/libsyntax/ext/mbe.rs rename to src/libsyntax_expand/mbe.rs index a87da791c9b4..453fe94f1de1 100644 --- a/src/libsyntax/ext/mbe.rs +++ b/src/libsyntax_expand/mbe.rs @@ -9,9 +9,9 @@ crate mod macro_rules; crate mod quoted; -use crate::ast; -use crate::parse::token::{self, Token, TokenKind}; -use crate::tokenstream::{DelimSpan}; +use syntax::ast; +use syntax::parse::token::{self, Token, TokenKind}; +use syntax::tokenstream::{DelimSpan}; use syntax_pos::{BytePos, Span}; diff --git a/src/libsyntax/ext/mbe/macro_check.rs b/src/libsyntax_expand/mbe/macro_check.rs similarity index 98% rename from src/libsyntax/ext/mbe/macro_check.rs rename to src/libsyntax_expand/mbe/macro_check.rs index aabaff4e1c30..50abda8d45e9 100644 --- a/src/libsyntax/ext/mbe/macro_check.rs +++ b/src/libsyntax_expand/mbe/macro_check.rs @@ -104,13 +104,13 @@ //! Kleene operators under which a meta-variable is repeating is the concatenation of the stacks //! stored when entering a macro definition starting from the state in which the meta-variable is //! bound. -use crate::ast::NodeId; -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::sess::ParseSess; -use crate::symbol::{kw, sym}; +use crate::mbe::{KleeneToken, TokenTree}; + +use syntax::ast::NodeId; +use syntax::early_buffered_lints::BufferedEarlyLintId; +use syntax::parse::token::{DelimToken, Token, TokenKind}; +use syntax::sess::ParseSess; +use syntax::symbol::{kw, sym}; use rustc_data_structures::fx::FxHashMap; use smallvec::SmallVec; diff --git a/src/libsyntax/ext/mbe/macro_parser.rs b/src/libsyntax_expand/mbe/macro_parser.rs similarity index 99% rename from src/libsyntax/ext/mbe/macro_parser.rs rename to src/libsyntax_expand/mbe/macro_parser.rs index ff382c316ffa..2edb49255129 100644 --- a/src/libsyntax/ext/mbe/macro_parser.rs +++ b/src/libsyntax_expand/mbe/macro_parser.rs @@ -74,15 +74,16 @@ crate use ParseResult::*; use TokenTreeOrTokenTreeSlice::*; -use crate::ast::{Ident, Name}; -use crate::ext::mbe::{self, TokenTree}; -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}; +use crate::mbe::{self, TokenTree}; + +use syntax::ast::{Ident, Name}; +use syntax::parse::{Directory, PResult}; +use syntax::parse::parser::{Parser, PathStyle}; +use syntax::parse::token::{self, DocComment, Nonterminal, Token}; +use syntax::print::pprust; +use syntax::sess::ParseSess; +use syntax::symbol::{kw, sym, Symbol}; +use syntax::tokenstream::{DelimSpan, TokenStream}; use errors::FatalError; use smallvec::{smallvec, SmallVec}; @@ -651,7 +652,7 @@ pub(super) fn parse( directory, recurse_into_modules, true, - crate::MACRO_ARGUMENTS, + syntax::MACRO_ARGUMENTS, ); // A queue of possible matcher positions. We initialize it with the matcher position in which diff --git a/src/libsyntax/ext/mbe/macro_rules.rs b/src/libsyntax_expand/mbe/macro_rules.rs similarity index 96% rename from src/libsyntax/ext/mbe/macro_rules.rs rename to src/libsyntax_expand/mbe/macro_rules.rs index b42232984226..9a4130b2d8d0 100644 --- a/src/libsyntax/ext/mbe/macro_rules.rs +++ b/src/libsyntax_expand/mbe/macro_rules.rs @@ -1,24 +1,25 @@ -use crate::ast; -use crate::attr::{self, TransparencyError}; -use crate::edition::Edition; -use crate::ext::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; -use crate::ext::base::{SyntaxExtension, SyntaxExtensionKind}; -use crate::ext::expand::{AstFragment, AstFragmentKind}; -use crate::ext::mbe; -use crate::ext::mbe::macro_check; -use crate::ext::mbe::macro_parser::parse; -use crate::ext::mbe::macro_parser::{Error, Failure, Success}; -use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult}; -use crate::ext::mbe::transcribe::transcribe; -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; -use crate::print::pprust; -use crate::sess::ParseSess; -use crate::symbol::{kw, sym, Symbol}; -use crate::tokenstream::{DelimSpan, TokenStream, TokenTree}; +use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; +use crate::base::{SyntaxExtension, SyntaxExtensionKind}; +use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment}; +use crate::mbe; +use crate::mbe::macro_check; +use crate::mbe::macro_parser::parse; +use crate::mbe::macro_parser::{Error, Failure, Success}; +use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedParseResult}; +use crate::mbe::transcribe::transcribe; + +use syntax::ast; +use syntax::attr::{self, TransparencyError}; +use syntax::edition::Edition; +use syntax::feature_gate::Features; +use syntax::parse::parser::Parser; +use syntax::parse::token::TokenKind::*; +use syntax::parse::token::{self, NtTT, Token}; +use syntax::parse::Directory; +use syntax::print::pprust; +use syntax::sess::ParseSess; +use syntax::symbol::{kw, sym, Symbol}; +use syntax::tokenstream::{DelimSpan, TokenStream}; use errors::{DiagnosticBuilder, FatalError}; use log::debug; @@ -66,7 +67,7 @@ impl<'a> ParserAnyMacro<'a> { crate fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; - let fragment = panictry!(parser.parse_ast_fragment(kind, true).map_err(|mut e| { + let fragment = panictry!(parse_ast_fragment(parser, kind, true).map_err(|mut e| { if parser.token == token::Eof && e.message().ends_with(", found ``") { if !e.span.is_dummy() { // early end of macro arm (#52866) @@ -128,7 +129,7 @@ impl<'a> ParserAnyMacro<'a> { // Make sure we don't have any tokens left to parse so we don't silently drop anything. let path = ast::Path::from_ident(macro_ident.with_span_pos(site_span)); - parser.ensure_complete_parse(&path, kind.name(), site_span); + ensure_complete_parse(parser, &path, kind.name(), site_span); fragment } } @@ -189,7 +190,7 @@ fn generic_extension<'cx>( _ => cx.span_bug(sp, "malformed macro lhs"), }; - match TokenTree::parse(cx, lhs_tt, arg.clone()) { + match parse_tt(cx, lhs_tt, arg.clone()) { Success(named_matches) => { let rhs = match rhses[i] { // ignore delimiters @@ -265,7 +266,7 @@ fn generic_extension<'cx>( mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], _ => continue, }; - match TokenTree::parse(cx, lhs_tt, arg.clone()) { + match parse_tt(cx, lhs_tt, arg.clone()) { Success(_) => { if comma_span.is_dummy() { err.note("you might be missing a comma"); @@ -1158,7 +1159,7 @@ fn is_legal_fragment_specifier( fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { match *tt { - mbe::TokenTree::Token(ref token) => crate::print::pprust::token_to_string(&token), + mbe::TokenTree::Token(ref token) => pprust::token_to_string(&token), mbe::TokenTree::MetaVar(_, name) => format!("${}", name), mbe::TokenTree::MetaVarDecl(_, name, kind) => format!("${}:{}", name, kind), _ => panic!( @@ -1168,17 +1169,14 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -impl TokenTree { - /// Use this token tree as a matcher to parse given tts. - fn parse(cx: &ExtCtxt<'_>, mtch: &[mbe::TokenTree], tts: TokenStream) - -> NamedParseResult { - // `None` is because we're not interpolating - let directory = Directory { - path: Cow::from(cx.current_expansion.module.directory.as_path()), - ownership: cx.current_expansion.directory_ownership, - }; - parse(cx.parse_sess(), tts, mtch, Some(directory), true) - } +/// Use this token tree as a matcher to parse given tts. +fn parse_tt(cx: &ExtCtxt<'_>, mtch: &[mbe::TokenTree], tts: TokenStream) -> NamedParseResult { + // `None` is because we're not interpolating + let directory = Directory { + path: Cow::from(cx.current_expansion.module.directory.as_path()), + ownership: cx.current_expansion.directory_ownership, + }; + parse(cx.parse_sess(), tts, mtch, Some(directory), true) } /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For diff --git a/src/libsyntax/ext/mbe/quoted.rs b/src/libsyntax_expand/mbe/quoted.rs similarity index 97% rename from src/libsyntax/ext/mbe/quoted.rs rename to src/libsyntax_expand/mbe/quoted.rs index 3cec4bc60e7a..cedd59233adf 100644 --- a/src/libsyntax/ext/mbe/quoted.rs +++ b/src/libsyntax_expand/mbe/quoted.rs @@ -1,11 +1,12 @@ -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::print::pprust; -use crate::sess::ParseSess; -use crate::symbol::kw; -use crate::tokenstream; +use crate::mbe::macro_parser; +use crate::mbe::{TokenTree, KleeneOp, KleeneToken, SequenceRepetition, Delimited}; + +use syntax::ast; +use syntax::parse::token::{self, Token}; +use syntax::print::pprust; +use syntax::sess::ParseSess; +use syntax::symbol::kw; +use syntax::tokenstream; use syntax_pos::Span; diff --git a/src/libsyntax/ext/mbe/transcribe.rs b/src/libsyntax_expand/mbe/transcribe.rs similarity index 98% rename from src/libsyntax/ext/mbe/transcribe.rs rename to src/libsyntax_expand/mbe/transcribe.rs index da930436d817..94523bbf91b5 100644 --- a/src/libsyntax/ext/mbe/transcribe.rs +++ b/src/libsyntax_expand/mbe/transcribe.rs @@ -1,10 +1,11 @@ -use crate::ast::{Ident, Mac}; -use crate::ext::base::ExtCtxt; -use crate::ext::mbe; -use crate::ext::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; -use crate::mut_visit::{self, MutVisitor}; -use crate::parse::token::{self, NtTT, Token}; -use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; +use crate::base::ExtCtxt; +use crate::mbe; +use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; + +use syntax::ast::{Ident, Mac}; +use syntax::mut_visit::{self, MutVisitor}; +use syntax::parse::token::{self, NtTT, Token}; +use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use smallvec::{smallvec, SmallVec}; diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax_expand/placeholders.rs similarity index 97% rename from src/libsyntax/ext/placeholders.rs rename to src/libsyntax_expand/placeholders.rs index 4fae25bbde62..f2c89e14b53b 100644 --- a/src/libsyntax/ext/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -1,11 +1,12 @@ -use crate::ast::{self, NodeId}; -use crate::source_map::{DUMMY_SP, dummy_spanned}; -use crate::ext::base::ExtCtxt; -use crate::ext::expand::{AstFragment, AstFragmentKind}; -use crate::tokenstream::TokenStream; -use crate::mut_visit::*; -use crate::ptr::P; -use crate::ThinVec; +use crate::base::ExtCtxt; +use crate::expand::{AstFragment, AstFragmentKind}; + +use syntax::ast::{self, NodeId}; +use syntax::source_map::{DUMMY_SP, dummy_spanned}; +use syntax::tokenstream::TokenStream; +use syntax::mut_visit::*; +use syntax::ptr::P; +use syntax::ThinVec; use smallvec::{smallvec, SmallVec}; diff --git a/src/libsyntax/ext/proc_macro.rs b/src/libsyntax_expand/proc_macro.rs similarity index 88% rename from src/libsyntax/ext/proc_macro.rs rename to src/libsyntax_expand/proc_macro.rs index 72062d2ffbf5..07b618c99a55 100644 --- a/src/libsyntax/ext/proc_macro.rs +++ b/src/libsyntax_expand/proc_macro.rs @@ -1,22 +1,22 @@ -use crate::ast::{self, ItemKind, Attribute, Mac}; -use crate::attr::{mark_used, mark_known}; -use crate::errors::{Applicability, FatalError}; -use crate::ext::base::{self, *}; -use crate::ext::proc_macro_server; -use crate::parse::{self, token}; -use crate::symbol::sym; -use crate::tokenstream::{self, TokenStream}; -use crate::visit::Visitor; +use crate::base::{self, *}; +use crate::proc_macro_server; + +use syntax::ast::{self, ItemKind, Attribute, Mac}; +use syntax::attr::{mark_used, mark_known}; +use syntax::errors::{Applicability, FatalError}; +use syntax::parse::{self, token}; +use syntax::symbol::sym; +use syntax::tokenstream::{self, TokenStream}; +use syntax::visit::Visitor; use rustc_data_structures::sync::Lrc; use syntax_pos::{Span, DUMMY_SP}; -const EXEC_STRATEGY: proc_macro::bridge::server::SameThread = - proc_macro::bridge::server::SameThread; +const EXEC_STRATEGY: pm::bridge::server::SameThread = pm::bridge::server::SameThread; pub struct BangProcMacro { - pub client: proc_macro::bridge::client::Client< - fn(proc_macro::TokenStream) -> proc_macro::TokenStream, + pub client: pm::bridge::client::Client< + fn(pm::TokenStream) -> pm::TokenStream, >, } @@ -44,9 +44,7 @@ fn expand<'cx>(&self, } pub struct AttrProcMacro { - pub client: proc_macro::bridge::client::Client< - fn(proc_macro::TokenStream, proc_macro::TokenStream) -> proc_macro::TokenStream, - >, + pub client: pm::bridge::client::Client pm::TokenStream>, } impl base::AttrProcMacro for AttrProcMacro { @@ -74,9 +72,7 @@ fn expand<'cx>(&self, } pub struct ProcMacroDerive { - pub client: proc_macro::bridge::client::Client< - fn(proc_macro::TokenStream) -> proc_macro::TokenStream, - >, + pub client: pm::bridge::client::Client pm::TokenStream>, } impl MultiItemModifier for ProcMacroDerive { diff --git a/src/libsyntax/ext/proc_macro_server.rs b/src/libsyntax_expand/proc_macro_server.rs similarity index 98% rename from src/libsyntax/ext/proc_macro_server.rs rename to src/libsyntax_expand/proc_macro_server.rs index e0e1a1c468c9..4ce99cfe73b5 100644 --- a/src/libsyntax/ext/proc_macro_server.rs +++ b/src/libsyntax_expand/proc_macro_server.rs @@ -1,18 +1,19 @@ -use crate::ast; -use crate::ext::base::ExtCtxt; -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 crate::base::ExtCtxt; + +use syntax::ast; +use syntax::parse::{self, token}; +use syntax::parse::lexer::comments; +use syntax::print::pprust; +use syntax::sess::ParseSess; +use syntax::tokenstream::{self, DelimSpan, IsJoint::*, TokenStream, TreeAndJoint}; use errors::Diagnostic; use rustc_data_structures::sync::Lrc; use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span}; use syntax_pos::symbol::{kw, sym, Symbol}; -use proc_macro::{Delimiter, Level, LineColumn, Spacing}; -use proc_macro::bridge::{server, TokenTree}; +use pm::{Delimiter, Level, LineColumn, Spacing}; +use pm::bridge::{server, TokenTree}; use std::{ascii, panic}; use std::ops::Bound; @@ -51,7 +52,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec)> { fn from_internal(((tree, is_joint), sess, stack): (TreeAndJoint, &ParseSess, &mut Vec)) -> Self { - use crate::parse::token::*; + use syntax::parse::token::*; let joint = is_joint == Joint; let Token { kind, span } = match tree { @@ -192,7 +193,7 @@ macro_rules! op { impl ToInternal for TokenTree { fn to_internal(self) -> TokenStream { - use crate::parse::token::*; + use syntax::parse::token::*; let (ch, joint, span) = match self { TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span), diff --git a/src/libsyntax_ext/Cargo.toml b/src/libsyntax_ext/Cargo.toml index 73310df305b3..440873f3c2b2 100644 --- a/src/libsyntax_ext/Cargo.toml +++ b/src/libsyntax_ext/Cargo.toml @@ -17,4 +17,5 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_target = { path = "../librustc_target" } smallvec = { version = "0.6.7", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } +syntax_expand = { path = "../libsyntax_expand" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/libsyntax_ext/asm.rs b/src/libsyntax_ext/asm.rs index becbf6d60a07..8c9a34713ea6 100644 --- a/src/libsyntax_ext/asm.rs +++ b/src/libsyntax_ext/asm.rs @@ -7,7 +7,7 @@ use errors::DiagnosticBuilder; use syntax::ast; -use syntax::ext::base::{self, *}; +use syntax_expand::base::{self, *}; use syntax::parse::token::{self, Token}; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; diff --git a/src/libsyntax_ext/assert.rs b/src/libsyntax_ext/assert.rs index cbfe14fa439b..f4d1f7fb09cd 100644 --- a/src/libsyntax_ext/assert.rs +++ b/src/libsyntax_ext/assert.rs @@ -1,7 +1,7 @@ use errors::{Applicability, DiagnosticBuilder}; use syntax::ast::{self, *}; -use syntax::ext::base::*; +use syntax_expand::base::*; use syntax::parse::token::{self, TokenKind}; use syntax::parse::parser::Parser; use syntax::print::pprust; diff --git a/src/libsyntax_ext/cfg.rs b/src/libsyntax_ext/cfg.rs index 3c33baf95a59..9e693f29c5a3 100644 --- a/src/libsyntax_ext/cfg.rs +++ b/src/libsyntax_ext/cfg.rs @@ -5,7 +5,7 @@ use errors::DiagnosticBuilder; use syntax::ast; -use syntax::ext::base::{self, *}; +use syntax_expand::base::{self, *}; use syntax::attr; use syntax::tokenstream::TokenStream; use syntax::parse::token; diff --git a/src/libsyntax_ext/cmdline_attrs.rs b/src/libsyntax_ext/cmdline_attrs.rs index 2c3159739e24..2d981526a398 100644 --- a/src/libsyntax_ext/cmdline_attrs.rs +++ b/src/libsyntax_ext/cmdline_attrs.rs @@ -2,9 +2,9 @@ use syntax::ast::{self, AttrItem, AttrStyle}; use syntax::attr::mk_attr; -use syntax::panictry; use syntax::parse::{self, token}; use syntax::sess::ParseSess; +use syntax_expand::panictry; use syntax_pos::FileName; pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -> ast::Crate { diff --git a/src/libsyntax_ext/compile_error.rs b/src/libsyntax_ext/compile_error.rs index 24f3a66d4ae1..cd7f78e9e342 100644 --- a/src/libsyntax_ext/compile_error.rs +++ b/src/libsyntax_ext/compile_error.rs @@ -1,6 +1,6 @@ // The compiler code necessary to support the compile_error! extension. -use syntax::ext::base::{self, *}; +use syntax_expand::base::{self, *}; use syntax_pos::Span; use syntax::tokenstream::TokenStream; diff --git a/src/libsyntax_ext/concat.rs b/src/libsyntax_ext/concat.rs index 790fdad5b3f5..47bade698a80 100644 --- a/src/libsyntax_ext/concat.rs +++ b/src/libsyntax_ext/concat.rs @@ -1,5 +1,5 @@ use syntax::ast; -use syntax::ext::base::{self, DummyResult}; +use syntax_expand::base::{self, DummyResult}; use syntax::symbol::Symbol; use syntax::tokenstream::TokenStream; diff --git a/src/libsyntax_ext/concat_idents.rs b/src/libsyntax_ext/concat_idents.rs index f6747658c070..a132a4136ea0 100644 --- a/src/libsyntax_ext/concat_idents.rs +++ b/src/libsyntax_ext/concat_idents.rs @@ -1,7 +1,7 @@ use rustc_data_structures::thin_vec::ThinVec; use syntax::ast; -use syntax::ext::base::{self, *}; +use syntax_expand::base::{self, *}; use syntax::parse::token::{self, Token}; use syntax::ptr::P; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/bounds.rs b/src/libsyntax_ext/deriving/bounds.rs index d5b8a00c75b8..6a9b70920242 100644 --- a/src/libsyntax_ext/deriving/bounds.rs +++ b/src/libsyntax_ext/deriving/bounds.rs @@ -3,7 +3,7 @@ use crate::deriving::generic::ty::*; use syntax::ast::MetaItem; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax_pos::Span; pub fn expand_deriving_copy(cx: &mut ExtCtxt<'_>, diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index 9ef2c033b078..eb7d480aa983 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -3,7 +3,7 @@ use crate::deriving::generic::ty::*; use syntax::ast::{self, Expr, GenericArg, Generics, ItemKind, MetaItem, VariantData}; -use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives}; +use syntax_expand::base::{Annotatable, ExtCtxt, SpecialDerives}; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/cmp/eq.rs b/src/libsyntax_ext/deriving/cmp/eq.rs index c92339dd2fbd..92721dab8782 100644 --- a/src/libsyntax_ext/deriving/cmp/eq.rs +++ b/src/libsyntax_ext/deriving/cmp/eq.rs @@ -3,7 +3,7 @@ use crate::deriving::generic::ty::*; use syntax::ast::{self, Ident, Expr, MetaItem, GenericArg}; -use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives}; +use syntax_expand::base::{Annotatable, ExtCtxt, SpecialDerives}; use syntax::ptr::P; use syntax::symbol::{sym, Symbol}; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/cmp/ord.rs b/src/libsyntax_ext/deriving/cmp/ord.rs index 1f4f5aa37099..3eeed95aff75 100644 --- a/src/libsyntax_ext/deriving/cmp/ord.rs +++ b/src/libsyntax_ext/deriving/cmp/ord.rs @@ -3,7 +3,7 @@ use crate::deriving::generic::ty::*; use syntax::ast::{self, Expr, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; use syntax::symbol::sym; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/cmp/partial_eq.rs b/src/libsyntax_ext/deriving/cmp/partial_eq.rs index 91e1e80e4fbf..1615d9917928 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_eq.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_eq.rs @@ -3,7 +3,7 @@ use crate::deriving::generic::ty::*; use syntax::ast::{BinOpKind, Expr, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives}; +use syntax_expand::base::{Annotatable, ExtCtxt, SpecialDerives}; use syntax::ptr::P; use syntax::symbol::sym; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/cmp/partial_ord.rs b/src/libsyntax_ext/deriving/cmp/partial_ord.rs index 13d63aaf2a80..af8aacc6eb9b 100644 --- a/src/libsyntax_ext/deriving/cmp/partial_ord.rs +++ b/src/libsyntax_ext/deriving/cmp/partial_ord.rs @@ -5,7 +5,7 @@ use crate::deriving::generic::ty::*; use syntax::ast::{self, BinOpKind, Expr, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; use syntax::symbol::{sym, Symbol}; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/debug.rs b/src/libsyntax_ext/deriving/debug.rs index 003c2423576e..35298211e4d3 100644 --- a/src/libsyntax_ext/deriving/debug.rs +++ b/src/libsyntax_ext/deriving/debug.rs @@ -6,7 +6,7 @@ use syntax::ast::{self, Ident}; use syntax::ast::{Expr, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; use syntax::symbol::sym; use syntax_pos::{DUMMY_SP, Span}; diff --git a/src/libsyntax_ext/deriving/decodable.rs b/src/libsyntax_ext/deriving/decodable.rs index cde72abbdef6..3a0379a0eb02 100644 --- a/src/libsyntax_ext/deriving/decodable.rs +++ b/src/libsyntax_ext/deriving/decodable.rs @@ -6,7 +6,7 @@ use syntax::ast; use syntax::ast::{Expr, MetaItem, Mutability}; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; use syntax::symbol::Symbol; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index 2fdea10b76f5..6176791c31b1 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -3,7 +3,7 @@ use crate::deriving::generic::ty::*; use syntax::ast::{Expr, MetaItem}; -use syntax::ext::base::{Annotatable, DummyResult, ExtCtxt}; +use syntax_expand::base::{Annotatable, DummyResult, ExtCtxt}; use syntax::ptr::P; use syntax::symbol::{kw, sym}; use syntax::span_err; diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 655d3bb7c4ab..2105946b666b 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -90,7 +90,7 @@ use crate::deriving::generic::ty::*; use syntax::ast::{Expr, ExprKind, MetaItem, Mutability}; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; use syntax::symbol::Symbol; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 9c3ec06d59a3..1886a5154b7b 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -186,12 +186,12 @@ use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind}; use syntax::ast::{VariantData, GenericParamKind, GenericArg}; use syntax::attr; -use syntax::ext::base::{Annotatable, ExtCtxt, SpecialDerives}; use syntax::source_map::respan; use syntax::util::map_in_place::MapInPlace; use syntax::ptr::P; use syntax::sess::ParseSess; use syntax::symbol::{Symbol, kw, sym}; +use syntax_expand::base::{Annotatable, ExtCtxt, SpecialDerives}; use syntax_pos::{Span}; use ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty}; diff --git a/src/libsyntax_ext/deriving/generic/ty.rs b/src/libsyntax_ext/deriving/generic/ty.rs index 6ae02a5cab19..607746597a59 100644 --- a/src/libsyntax_ext/deriving/generic/ty.rs +++ b/src/libsyntax_ext/deriving/generic/ty.rs @@ -5,7 +5,7 @@ pub use Ty::*; use syntax::ast::{self, Expr, GenericParamKind, Generics, Ident, SelfKind, GenericArg}; -use syntax::ext::base::ExtCtxt; +use syntax_expand::base::ExtCtxt; use syntax::source_map::{respan, DUMMY_SP}; use syntax::ptr::P; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/hash.rs b/src/libsyntax_ext/deriving/hash.rs index 2fc594abd705..fe9ef78bb1b0 100644 --- a/src/libsyntax_ext/deriving/hash.rs +++ b/src/libsyntax_ext/deriving/hash.rs @@ -3,7 +3,7 @@ use crate::deriving::generic::ty::*; use syntax::ast::{Expr, MetaItem, Mutability}; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; use syntax::symbol::sym; use syntax_pos::Span; diff --git a/src/libsyntax_ext/deriving/mod.rs b/src/libsyntax_ext/deriving/mod.rs index 60b6eba7a4b5..f0471a857dc9 100644 --- a/src/libsyntax_ext/deriving/mod.rs +++ b/src/libsyntax_ext/deriving/mod.rs @@ -1,7 +1,7 @@ //! The compiler code necessary to implement the `#[derive]` extensions. use syntax::ast::{self, MetaItem}; -use syntax::ext::base::{Annotatable, ExtCtxt, MultiItemModifier}; +use syntax_expand::base::{Annotatable, ExtCtxt, MultiItemModifier}; use syntax::ptr::P; use syntax::symbol::{Symbol, sym}; use syntax_pos::Span; diff --git a/src/libsyntax_ext/env.rs b/src/libsyntax_ext/env.rs index 02757bf6b168..58fe56bd2353 100644 --- a/src/libsyntax_ext/env.rs +++ b/src/libsyntax_ext/env.rs @@ -4,7 +4,7 @@ // use syntax::ast::{self, Ident, GenericArg}; -use syntax::ext::base::{self, *}; +use syntax_expand::base::{self, *}; use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::Span; use syntax::tokenstream::TokenStream; diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index 8fc64021b51f..45d9f79c28fc 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -8,7 +8,7 @@ use errors::pluralise; use syntax::ast; -use syntax::ext::base::{self, *}; +use syntax_expand::base::{self, *}; use syntax::parse::token; use syntax::ptr::P; use syntax::symbol::{Symbol, sym}; diff --git a/src/libsyntax_ext/global_allocator.rs b/src/libsyntax_ext/global_allocator.rs index f014b4f4f9fd..75dda9535b33 100644 --- a/src/libsyntax_ext/global_allocator.rs +++ b/src/libsyntax_ext/global_allocator.rs @@ -2,8 +2,8 @@ use syntax::ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafety}; use syntax::ast::{self, Param, Attribute, Expr, FnHeader, Generics, Ident}; -use syntax::ext::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; -use syntax::ext::base::{Annotatable, ExtCtxt}; +use syntax_expand::allocator::{AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS}; +use syntax_expand::base::{Annotatable, ExtCtxt}; use syntax::ptr::P; use syntax::symbol::{kw, sym, Symbol}; use syntax_pos::Span; diff --git a/src/libsyntax_ext/global_asm.rs b/src/libsyntax_ext/global_asm.rs index 72fb5b47c215..879ae1e42153 100644 --- a/src/libsyntax_ext/global_asm.rs +++ b/src/libsyntax_ext/global_asm.rs @@ -12,7 +12,7 @@ use syntax::ast; use syntax::source_map::respan; -use syntax::ext::base::{self, *}; +use syntax_expand::base::{self, *}; use syntax::parse::token; use syntax::ptr::P; use syntax_pos::Span; diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs index 5ba76a52350f..5516f276422e 100644 --- a/src/libsyntax_ext/lib.rs +++ b/src/libsyntax_ext/lib.rs @@ -15,9 +15,9 @@ use syntax::ast::Ident; use syntax::edition::Edition; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, MacroExpanderFn}; -use syntax::ext::proc_macro::BangProcMacro; use syntax::symbol::sym; +use syntax_expand::base::{Resolver, SyntaxExtension, SyntaxExtensionKind, MacroExpanderFn}; +use syntax_expand::proc_macro::BangProcMacro; mod error_codes; @@ -45,7 +45,7 @@ pub mod standard_library_imports; pub mod test_harness; -pub fn register_builtin_macros(resolver: &mut dyn syntax::ext::base::Resolver, edition: Edition) { +pub fn register_builtin_macros(resolver: &mut dyn Resolver, edition: Edition) { let mut register = |name, kind| resolver.register_builtin_macro( Ident::with_dummy_span(name), SyntaxExtension { is_builtin: true, ..SyntaxExtension::default(kind, edition) diff --git a/src/libsyntax_ext/log_syntax.rs b/src/libsyntax_ext/log_syntax.rs index 92130bfaf68e..2202375e5e78 100644 --- a/src/libsyntax_ext/log_syntax.rs +++ b/src/libsyntax_ext/log_syntax.rs @@ -1,4 +1,4 @@ -use syntax::ext::base; +use syntax_expand::base; use syntax::print; use syntax::tokenstream::TokenStream; use syntax_pos; diff --git a/src/libsyntax_ext/plugin_macro_defs.rs b/src/libsyntax_ext/plugin_macro_defs.rs index 62c7e188eba2..1ca9422eb9dc 100644 --- a/src/libsyntax_ext/plugin_macro_defs.rs +++ b/src/libsyntax_ext/plugin_macro_defs.rs @@ -4,7 +4,7 @@ use syntax::ast::*; use syntax::attr; use syntax::edition::Edition; -use syntax::ext::base::{Resolver, NamedSyntaxExtension}; +use syntax_expand::base::{Resolver, NamedSyntaxExtension}; use syntax::parse::token; use syntax::ptr::P; use syntax::source_map::respan; diff --git a/src/libsyntax_ext/proc_macro_harness.rs b/src/libsyntax_ext/proc_macro_harness.rs index 1b7068818b01..96d0c3fcab1c 100644 --- a/src/libsyntax_ext/proc_macro_harness.rs +++ b/src/libsyntax_ext/proc_macro_harness.rs @@ -3,14 +3,14 @@ use smallvec::smallvec; use syntax::ast::{self, Ident}; 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::print::pprust; use syntax::ptr::P; use syntax::sess::ParseSess; use syntax::symbol::{kw, sym}; use syntax::visit::{self, Visitor}; +use syntax_expand::base::{ExtCtxt, Resolver}; +use syntax_expand::expand::{AstFragment, ExpansionConfig}; +use syntax_expand::proc_macro::is_proc_macro_attr; use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::hygiene::AstPass; @@ -46,7 +46,7 @@ struct CollectProcMacros<'a> { } pub fn inject(sess: &ParseSess, - resolver: &mut dyn (::syntax::ext::base::Resolver), + resolver: &mut dyn Resolver, mut krate: ast::Crate, is_proc_macro_crate: bool, has_proc_macro_decls: bool, diff --git a/src/libsyntax_ext/source_util.rs b/src/libsyntax_ext/source_util.rs index f74507dcc21f..438e199ebdb8 100644 --- a/src/libsyntax_ext/source_util.rs +++ b/src/libsyntax_ext/source_util.rs @@ -1,5 +1,6 @@ -use syntax::{ast, panictry}; -use syntax::ext::base::{self, *}; +use syntax_expand::panictry; +use syntax_expand::base::{self, *}; +use syntax::ast; use syntax::parse::{self, token, DirectoryOwnership}; use syntax::print::pprust; use syntax::ptr::P; diff --git a/src/libsyntax_ext/standard_library_imports.rs b/src/libsyntax_ext/standard_library_imports.rs index 4f17acf2d0f6..fd27a2189069 100644 --- a/src/libsyntax_ext/standard_library_imports.rs +++ b/src/libsyntax_ext/standard_library_imports.rs @@ -1,11 +1,11 @@ use syntax::{ast, attr}; use syntax::edition::Edition; -use syntax::ext::expand::ExpansionConfig; -use syntax::ext::hygiene::AstPass; -use syntax::ext::base::{ExtCtxt, Resolver}; use syntax::ptr::P; use syntax::sess::ParseSess; use syntax::symbol::{Ident, Symbol, kw, sym}; +use syntax_expand::expand::ExpansionConfig; +use syntax_expand::hygiene::AstPass; +use syntax_expand::base::{ExtCtxt, Resolver}; use syntax_pos::DUMMY_SP; pub fn inject( diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs index 4d7441ca0b66..b0da413d63a0 100644 --- a/src/libsyntax_ext/test.rs +++ b/src/libsyntax_ext/test.rs @@ -5,7 +5,7 @@ use syntax::ast; use syntax::attr; -use syntax::ext::base::*; +use syntax_expand::base::*; use syntax::print::pprust; use syntax::source_map::respan; use syntax::symbol::{Symbol, sym}; diff --git a/src/libsyntax_ext/test_harness.rs b/src/libsyntax_ext/test_harness.rs index 0bb279c0cb0d..33d41a7f53e5 100644 --- a/src/libsyntax_ext/test_harness.rs +++ b/src/libsyntax_ext/test_harness.rs @@ -6,8 +6,8 @@ use syntax::ast::{self, Ident}; use syntax::attr; use syntax::entry::{self, EntryPointType}; -use syntax::ext::base::{ExtCtxt, Resolver}; -use syntax::ext::expand::{AstFragment, ExpansionConfig}; +use syntax_expand::base::{ExtCtxt, Resolver}; +use syntax_expand::expand::{AstFragment, ExpansionConfig}; use syntax::feature_gate::Features; use syntax::mut_visit::{*, ExpectOne}; use syntax::ptr::P; diff --git a/src/libsyntax_ext/trace_macros.rs b/src/libsyntax_ext/trace_macros.rs index d83c24046d9e..dbf96d3b561a 100644 --- a/src/libsyntax_ext/trace_macros.rs +++ b/src/libsyntax_ext/trace_macros.rs @@ -1,4 +1,4 @@ -use syntax::ext::base::{self, ExtCtxt}; +use syntax_expand::base::{self, ExtCtxt}; use syntax::symbol::kw; use syntax_pos::Span; use syntax::tokenstream::{TokenTree, TokenStream}; diff --git a/src/libsyntax_ext/util.rs b/src/libsyntax_ext/util.rs index fbae68057c5b..d84fe19b3eab 100644 --- a/src/libsyntax_ext/util.rs +++ b/src/libsyntax_ext/util.rs @@ -1,7 +1,7 @@ use syntax_pos::Symbol; use syntax::ast::MetaItem; use syntax::attr::{check_builtin_attribute, AttributeTemplate}; -use syntax::ext::base::ExtCtxt; +use syntax_expand::base::ExtCtxt; pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { // All the built-in macro attributes are "words" at the moment. From bf02d49e848e331ba8bf3d14e3b3443bc68ab7f3 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 12:59:59 +0200 Subject: [PATCH 444/545] move SeqSep to parser.rs --- src/libsyntax/parse/mod.rs | 26 +---------------------- src/libsyntax/parse/parser.rs | 26 ++++++++++++++++++++++- src/libsyntax/parse/parser/attr.rs | 3 +-- src/libsyntax/parse/parser/diagnostics.rs | 6 ++++-- 4 files changed, 31 insertions(+), 30 deletions(-) diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1eaee46a3c22..e6b794a6a990 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -2,7 +2,7 @@ use crate::ast; use crate::parse::parser::{Parser, emit_unclosed_delims}; -use crate::parse::token::{Nonterminal, TokenKind}; +use crate::parse::token::Nonterminal; use crate::tokenstream::{self, TokenStream, TokenTree}; use crate::print::pprust; use crate::sess::ParseSess; @@ -271,30 +271,6 @@ pub fn stream_to_parser_with_base_dir<'a>( Parser::new(sess, stream, Some(base_dir), true, false, None) } -/// A sequence separator. -pub struct SeqSep { - /// The separator token. - pub sep: Option, - /// `true` if a trailing separator is allowed. - pub trailing_sep_allowed: bool, -} - -impl SeqSep { - pub fn trailing_allowed(t: TokenKind) -> SeqSep { - SeqSep { - sep: Some(t), - trailing_sep_allowed: true, - } - } - - pub fn none() -> SeqSep { - SeqSep { - sep: None, - trailing_sep_allowed: false, - } - } -} - // 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). diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 64ec943294ae..79901177d187 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -15,7 +15,7 @@ self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident, IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety, }; -use crate::parse::{PResult, Directory, DirectoryOwnership, SeqSep}; +use crate::parse::{PResult, Directory, DirectoryOwnership}; 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}; @@ -329,6 +329,30 @@ enum TokenExpectType { NoExpect, } +/// A sequence separator. +struct SeqSep { + /// The separator token. + sep: Option, + /// `true` if a trailing separator is allowed. + trailing_sep_allowed: bool, +} + +impl SeqSep { + fn trailing_allowed(t: TokenKind) -> SeqSep { + SeqSep { + sep: Some(t), + trailing_sep_allowed: true, + } + } + + fn none() -> SeqSep { + SeqSep { + sep: None, + trailing_sep_allowed: false, + } + } +} + impl<'a> Parser<'a> { pub fn new( sess: &'a ParseSess, diff --git a/src/libsyntax/parse/parser/attr.rs b/src/libsyntax/parse/parser/attr.rs index cfd10e443e96..463629de7a15 100644 --- a/src/libsyntax/parse/parser/attr.rs +++ b/src/libsyntax/parse/parser/attr.rs @@ -1,8 +1,7 @@ +use super::{SeqSep, PResult, Parser, TokenType, PathStyle}; use crate::attr; use crate::ast; -use crate::parse::{SeqSep, PResult}; use crate::parse::token::{self, Nonterminal, DelimToken}; -use crate::parse::parser::{Parser, TokenType, PathStyle}; use crate::tokenstream::{TokenStream, TokenTree}; use crate::source_map::Span; diff --git a/src/libsyntax/parse/parser/diagnostics.rs b/src/libsyntax/parse/parser/diagnostics.rs index 32a41bb0e271..6a4a6c0f16f9 100644 --- a/src/libsyntax/parse/parser/diagnostics.rs +++ b/src/libsyntax/parse/parser/diagnostics.rs @@ -1,9 +1,11 @@ +use super::{ + BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType, + SeqSep, PResult, Parser +}; use crate::ast::{ self, Param, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, }; -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; use crate::ptr::P; From 9dc07b05d5a293339f544dcb31df8c57604ad417 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 8 Oct 2019 21:43:43 +0200 Subject: [PATCH 445/545] parser: leave a FIXME for later --- src/libsyntax/parse/parser/module.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libsyntax/parse/parser/module.rs b/src/libsyntax/parse/parser/module.rs index 1a8178f0bec5..3e88c98b8561 100644 --- a/src/libsyntax/parse/parser/module.rs +++ b/src/libsyntax/parse/parser/module.rs @@ -39,6 +39,8 @@ impl<'a> Parser<'a> { /// Parses a `mod { ... }` or `mod ;` item. pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> { let (in_cfg, outer_attrs) = { + // FIXME(Centril): This results in a cycle between config and parsing. + // Consider using dynamic dispatch via `self.sess` to disentangle the knot. let mut strip_unconfigured = crate::config::StripUnconfigured { sess: self.sess, features: None, // Don't perform gated feature checking. From 904168fe144b5ebabe6d691930a59127b049ac74 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 9 Oct 2019 01:52:19 +0200 Subject: [PATCH 446/545] mbe: leave a FIXME --- src/libsyntax_expand/mbe/macro_parser.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libsyntax_expand/mbe/macro_parser.rs b/src/libsyntax_expand/mbe/macro_parser.rs index 2edb49255129..3efe22626a9f 100644 --- a/src/libsyntax_expand/mbe/macro_parser.rs +++ b/src/libsyntax_expand/mbe/macro_parser.rs @@ -890,6 +890,9 @@ fn may_be_ident(nt: &token::Nonterminal) -> bool { /// /// The parsed non-terminal. fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal { + // FIXME(Centril): Consider moving this to `parser.rs` to make + // the visibilities of the methods used below `pub(super)` at most. + if name == sym::tt { return token::NtTT(p.parse_token_tree()); } From be40bbd2fb7e077b27d346a0b9249d309b9ca690 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 12 Oct 2019 06:12:00 +0200 Subject: [PATCH 447/545] make tidy happy --- src/libsyntax/parse/parser/diagnostics.rs | 12 ++++++++++-- src/libsyntax/parse/parser/stmt.rs | 4 +++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser/diagnostics.rs b/src/libsyntax/parse/parser/diagnostics.rs index 6a4a6c0f16f9..06982c789db8 100644 --- a/src/libsyntax/parse/parser/diagnostics.rs +++ b/src/libsyntax/parse/parser/diagnostics.rs @@ -180,7 +180,11 @@ pub fn fatal(&self, m: &str) -> DiagnosticBuilder<'a> { self.sess.span_diagnostic.struct_span_fatal(sp, m) } - pub(super) 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()) } @@ -1174,7 +1178,11 @@ pub(super) fn recover_stmt(&mut self) { /// /// If `break_on_block` is `Break`, then we will stop consuming tokens /// after finding (and consuming) a brace-delimited block. - pub(super) 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; diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs index 4b1fdb2eef3a..d54d9c4b8e9f 100644 --- a/src/libsyntax/parse/parser/stmt.rs +++ b/src/libsyntax/parse/parser/stmt.rs @@ -372,7 +372,9 @@ pub fn parse_block(&mut self) -> PResult<'a, P> { } /// Parses a block. Inner attributes are allowed. - pub(super) fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (Vec, P)> { + pub(super) fn parse_inner_attrs_and_block( + &mut self + ) -> PResult<'a, (Vec, P)> { maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); let lo = self.token.span; From e5d566c08024db5777af42aa2ffc385a58782afe Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Oct 2019 14:19:39 +0200 Subject: [PATCH 448/545] Add long error explanation for E0573 --- src/librustc_resolve/error_codes.rs | 75 ++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 1e65cbada069..ab3d95dd8edf 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1611,6 +1611,80 @@ fn print_on_failure(state: &State) { ``` "##, +E0573: r##" +Something other than a type has been used when one was expected. + +Erroneous code examples: + +```compile_fail,E0573 +enum Dragon { + Born, +} + +fn oblivion() -> Dragon::Born { // error! + Dragon::Born +} + +const HOBBIT: u32 = 2; +impl HOBBIT {} // error! + +enum Wizard { + Gandalf, + Saruman, +} + +trait Isengard { + fn wizard(_: Wizard::Saruman); // error! +} +``` + +In all these errors, a type was expected. For example, in the first error, if +we want to return the `Born` variant from the `Dragon` enum, we must set the +function to return the enum and not its variant: + +``` +enum Dragon { + Born, +} + +fn oblivion() -> Dragon { // ok! + Dragon::Born +} +``` + +In the second error, you can't implement something on an item, only on types. +We would need to create a new type if we wanted to do something similar: + +``` +struct Hobbit(u32); // we create a new type + +const HOBBIT: Hobbit = Hobbit(2); +impl Hobbit {} // ok! +``` + +In the third case, we tried to only expect one variant of the `Wizard` enum, +which is not possible. To make this work, we need to using pattern matching +over the `Wizard` enum: + +``` +enum Wizard { + Gandalf, + Saruman, +} + +trait Isengard { + fn wizard(w: Wizard) { // error! + match w { + Wizard::Saruman => { + // do something + } + _ => {} // ignore everything else + } + } +} +``` +"##, + E0574: r##" Something other than a struct, variant or union has been used when one was expected. @@ -1788,7 +1862,6 @@ struct Foo> { // E0427, merged into 530 // E0467, removed // E0470, removed - E0573, E0575, E0576, E0577, From 7d357fbffd7338957fe993b8dc28b91ca5c422b4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 9 Oct 2019 14:19:48 +0200 Subject: [PATCH 449/545] update ui tests --- .../ui/const-generics/struct-with-invalid-const-param.stderr | 1 + src/test/ui/enum/enum-variant-type-2.stderr | 1 + src/test/ui/issues/issue-17546.stderr | 1 + src/test/ui/issues/issue-18119.stderr | 1 + src/test/ui/issues/issue-30535.stderr | 1 + src/test/ui/issues/issue-35675.stderr | 2 +- src/test/ui/privacy/privacy-ns1.stderr | 2 +- src/test/ui/privacy/privacy-ns2.stderr | 2 +- src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr | 3 ++- src/test/ui/traits/trait-impl-for-module.stderr | 1 + src/test/ui/type/type-ascription-with-fn-call.stderr | 1 + src/test/ui/variants/variant-used-as-type.stderr | 1 + 12 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr index dfa2557e9f6f..b3aa35e079ae 100644 --- a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr +++ b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr @@ -14,3 +14,4 @@ LL | #![feature(const_generics)] error: aborting due to previous error +For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/enum/enum-variant-type-2.stderr b/src/test/ui/enum/enum-variant-type-2.stderr index 65c45d9bad0d..7e8453c61f62 100644 --- a/src/test/ui/enum/enum-variant-type-2.stderr +++ b/src/test/ui/enum/enum-variant-type-2.stderr @@ -9,3 +9,4 @@ LL | fn foo(x: Foo::Bar) {} error: aborting due to previous error +For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/issues/issue-17546.stderr b/src/test/ui/issues/issue-17546.stderr index 1f71e159f182..4a0fb186e49f 100644 --- a/src/test/ui/issues/issue-17546.stderr +++ b/src/test/ui/issues/issue-17546.stderr @@ -62,3 +62,4 @@ LL | fn newer() -> Result { error: aborting due to 4 previous errors +For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/issues/issue-18119.stderr b/src/test/ui/issues/issue-18119.stderr index 4c5b940190ee..ddee5a9da7a4 100644 --- a/src/test/ui/issues/issue-18119.stderr +++ b/src/test/ui/issues/issue-18119.stderr @@ -18,3 +18,4 @@ LL | impl foo {} error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/issues/issue-30535.stderr b/src/test/ui/issues/issue-30535.stderr index 5faf0374210d..e3692934b62a 100644 --- a/src/test/ui/issues/issue-30535.stderr +++ b/src/test/ui/issues/issue-30535.stderr @@ -9,3 +9,4 @@ LL | _: foo::Foo::FooV error: aborting due to previous error +For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/issues/issue-35675.stderr b/src/test/ui/issues/issue-35675.stderr index 856d6506f2a9..91814d949637 100644 --- a/src/test/ui/issues/issue-35675.stderr +++ b/src/test/ui/issues/issue-35675.stderr @@ -67,5 +67,5 @@ LL | fn qux() -> Some { error: aborting due to 7 previous errors -Some errors have detailed explanations: E0412, E0425. +Some errors have detailed explanations: E0412, E0425, E0573. For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/privacy/privacy-ns1.stderr b/src/test/ui/privacy/privacy-ns1.stderr index 09148f9d0e6e..8ffc12c31cb6 100644 --- a/src/test/ui/privacy/privacy-ns1.stderr +++ b/src/test/ui/privacy/privacy-ns1.stderr @@ -72,5 +72,5 @@ LL | use foo3::Bar; error: aborting due to 4 previous errors -Some errors have detailed explanations: E0412, E0423, E0425. +Some errors have detailed explanations: E0412, E0423, E0425, E0573. For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/privacy/privacy-ns2.stderr b/src/test/ui/privacy/privacy-ns2.stderr index 8ea32f36f9e7..13057a899f3c 100644 --- a/src/test/ui/privacy/privacy-ns2.stderr +++ b/src/test/ui/privacy/privacy-ns2.stderr @@ -82,5 +82,5 @@ LL | use foo3::{Bar,Baz}; error: aborting due to 7 previous errors -Some errors have detailed explanations: E0423, E0603. +Some errors have detailed explanations: E0423, E0573, E0603. For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr index 6bef793e0e71..b831e624cb6f 100644 --- a/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr +++ b/src/test/ui/tool-attributes/tool-attributes-misplaced-1.stderr @@ -42,4 +42,5 @@ LL | rustfmt::skip; error: aborting due to 7 previous errors -For more information about this error, try `rustc --explain E0423`. +Some errors have detailed explanations: E0423, E0573. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/traits/trait-impl-for-module.stderr b/src/test/ui/traits/trait-impl-for-module.stderr index 4a06cd777d49..c62bcfca94de 100644 --- a/src/test/ui/traits/trait-impl-for-module.stderr +++ b/src/test/ui/traits/trait-impl-for-module.stderr @@ -6,3 +6,4 @@ LL | impl A for a { error: aborting due to previous error +For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/type/type-ascription-with-fn-call.stderr b/src/test/ui/type/type-ascription-with-fn-call.stderr index 624c817e33e3..eeaca5300f9b 100644 --- a/src/test/ui/type/type-ascription-with-fn-call.stderr +++ b/src/test/ui/type/type-ascription-with-fn-call.stderr @@ -11,3 +11,4 @@ LL | f(); error: aborting due to previous error +For more information about this error, try `rustc --explain E0573`. diff --git a/src/test/ui/variants/variant-used-as-type.stderr b/src/test/ui/variants/variant-used-as-type.stderr index 1138b69ae3bc..fdfc044d81f6 100644 --- a/src/test/ui/variants/variant-used-as-type.stderr +++ b/src/test/ui/variants/variant-used-as-type.stderr @@ -24,3 +24,4 @@ LL | impl Ty {} error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0573`. From 5bb05a2c5e7fa8c6f85b564a6a1ffcb3facabc97 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 15 Oct 2019 10:46:03 -0700 Subject: [PATCH 450/545] Update cargo, books --- src/doc/book | 2 +- src/doc/nomicon | 2 +- src/doc/rust-by-example | 2 +- src/tools/cargo | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/book b/src/doc/book index 04806c80be0f..9bb8b161963f 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 04806c80be0f54b1290287e3f85e84bdfc0b6ec7 +Subproject commit 9bb8b161963fcebc9d9ccd732ba26f42108016d5 diff --git a/src/doc/nomicon b/src/doc/nomicon index 4374786f0b4b..5004ad30d69f 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 4374786f0b4bf0606b35d5c30a9681f342e5707b +Subproject commit 5004ad30d69f93553ceef74439fea2159d1f769e diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index a6288e7407a6..0b111eaae36c 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit a6288e7407a6c4c19ea29de6d43f40c803883f21 +Subproject commit 0b111eaae36cc4b4997684be853882a59e2c7ca7 diff --git a/src/tools/cargo b/src/tools/cargo index a429e8cc4614..3a9abe3f0655 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit a429e8cc4614a46a86322a0777a477e2baa83f1c +Subproject commit 3a9abe3f065554a7fbc59f440df2baba4a6e47ee From 870ea528897d2500a97150ab01c1a2152e946f13 Mon Sep 17 00:00:00 2001 From: msizanoen Date: Wed, 16 Oct 2019 21:34:17 +0700 Subject: [PATCH 451/545] Mirror crosstool-ng on rust-lang-ci-mirrors --- src/ci/docker/dist-armv7-linux/crosstool-ng.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/dist-armv7-linux/crosstool-ng.sh b/src/ci/docker/dist-armv7-linux/crosstool-ng.sh index 47ce88868ae1..ae737d9677d8 100644 --- a/src/ci/docker/dist-armv7-linux/crosstool-ng.sh +++ b/src/ci/docker/dist-armv7-linux/crosstool-ng.sh @@ -1,6 +1,7 @@ set -ex -url="https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz" +# Mirrored from https://github.com/crosstool-ng/crosstool-ng/archive/crosstool-ng-1.24.0.tar.gz +url="https://rust-lang-ci-mirrors.s3-us-west-1.amazonaws.com/rustc/crosstool-ng-1.24.0.tar.gz" curl -Lf $url | tar xzf - cd crosstool-ng-crosstool-ng-1.24.0 ./bootstrap From 1a26fdf9b2c818186e23188b4dc47349e4133b1a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 16 Oct 2019 13:23:46 +0200 Subject: [PATCH 452/545] ui-fulldeps: make them pass again? --- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax/parse/parser/attr.rs | 2 +- src/libsyntax/parse/parser/module.rs | 2 +- src/test/ui-fulldeps/ast_stmt_expr_attr.rs | 2 +- src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs | 3 ++- src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs | 3 ++- src/test/ui-fulldeps/auxiliary/plugin-args.rs | 5 +++-- src/test/ui-fulldeps/auxiliary/roman-numerals.rs | 3 ++- 8 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 79901177d187..9cb410a8ae31 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1,4 +1,4 @@ -mod attr; +pub mod attr; mod expr; mod pat; mod item; diff --git a/src/libsyntax/parse/parser/attr.rs b/src/libsyntax/parse/parser/attr.rs index 463629de7a15..6f7d1ead4c17 100644 --- a/src/libsyntax/parse/parser/attr.rs +++ b/src/libsyntax/parse/parser/attr.rs @@ -65,7 +65,7 @@ pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, Vec PResult<'a, ast::Attribute> { + pub fn parse_attribute(&mut self, permit_inner: bool) -> PResult<'a, ast::Attribute> { debug!("parse_attribute: permit_inner={:?} self.token={:?}", permit_inner, self.token); diff --git a/src/libsyntax/parse/parser/module.rs b/src/libsyntax/parse/parser/module.rs index 3e88c98b8561..a0e4d2bbb7ac 100644 --- a/src/libsyntax/parse/parser/module.rs +++ b/src/libsyntax/parse/parser/module.rs @@ -26,7 +26,7 @@ pub(super) struct ModulePathSuccess { impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. - crate fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { + pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { let lo = self.token.span; let krate = Ok(ast::Crate { attrs: self.parse_inner_attributes()?, diff --git a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs b/src/test/ui-fulldeps/ast_stmt_expr_attr.rs index 5479119d812f..927e2c0820eb 100644 --- a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs +++ b/src/test/ui-fulldeps/ast_stmt_expr_attr.rs @@ -18,7 +18,7 @@ use syntax::parse::parser::Parser; use syntax::parse::token; use syntax::ptr::P; -use syntax::parse::attr::*; +use syntax::parse::parser::attr::*; use syntax::print::pprust; use std::fmt; diff --git a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs index c053c7152487..3d08c1c9eeef 100644 --- a/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs +++ b/src/test/ui-fulldeps/auxiliary/attr-plugin-test.rs @@ -5,9 +5,10 @@ extern crate rustc_driver; extern crate syntax; +extern crate syntax_expand; use rustc_driver::plugin::Registry; -use syntax::ext::base::SyntaxExtension; +use syntax_expand::base::SyntaxExtension; use syntax::feature_gate::AttributeType; use syntax::symbol::Symbol; diff --git a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs index 6fb99b2c9836..bb0ebf693d0b 100644 --- a/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs +++ b/src/test/ui-fulldeps/auxiliary/issue-40001-plugin.rs @@ -5,10 +5,11 @@ extern crate rustc; extern crate rustc_driver; extern crate syntax; +extern crate syntax_expand; use rustc_driver::plugin::Registry; use syntax::attr; -use syntax::ext::base::*; +use syntax_expand::base::*; use syntax::feature_gate::AttributeType::Whitelisted; use syntax::symbol::Symbol; diff --git a/src/test/ui-fulldeps/auxiliary/plugin-args.rs b/src/test/ui-fulldeps/auxiliary/plugin-args.rs index 5ff24cff23c5..cccdfea20832 100644 --- a/src/test/ui-fulldeps/auxiliary/plugin-args.rs +++ b/src/test/ui-fulldeps/auxiliary/plugin-args.rs @@ -4,14 +4,15 @@ #![feature(box_syntax, rustc_private)] extern crate syntax; +extern crate syntax_expand; extern crate syntax_pos; extern crate rustc; extern crate rustc_driver; use std::borrow::ToOwned; use syntax::ast; -use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind}; -use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager}; +use syntax_expand::base::{SyntaxExtension, SyntaxExtensionKind}; +use syntax_expand::base::{TTMacroExpander, ExtCtxt, MacResult, MacEager}; use syntax::print::pprust; use syntax::symbol::Symbol; use syntax_pos::Span; diff --git a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs index 2b57e9289b52..3524f449c745 100644 --- a/src/test/ui-fulldeps/auxiliary/roman-numerals.rs +++ b/src/test/ui-fulldeps/auxiliary/roman-numerals.rs @@ -10,13 +10,14 @@ #![feature(plugin_registrar, rustc_private)] extern crate syntax; +extern crate syntax_expand; extern crate syntax_pos; extern crate rustc; extern crate rustc_driver; use syntax::parse::token::{self, Token}; use syntax::tokenstream::{TokenTree, TokenStream}; -use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; +use syntax_expand::base::{ExtCtxt, MacResult, DummyResult, MacEager}; use syntax_pos::Span; use rustc_driver::plugin::Registry; From 940d48ed6021541d5e9576873982f68967d4ec87 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Wed, 16 Oct 2019 16:50:07 +0000 Subject: [PATCH 453/545] add example for type_name --- src/libcore/any.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index f75b7a454438..e2704e807d10 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -445,6 +445,15 @@ pub const fn of() -> TypeId { /// /// The current implementation uses the same infrastructure as compiler /// diagnostics and debuginfo, but this is not guaranteed. +/// +/// # Example +/// +/// ```rust +/// assert_eq!( +/// std::any::type_name::>(), +/// "core::option::Option", +/// ); +/// ``` #[stable(feature = "type_name", since = "1.38.0")] #[rustc_const_unstable(feature = "const_type_name")] pub const fn type_name() -> &'static str { From ca1cfdab78d1966efd492cd550a3684f3b95527c Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 16 Oct 2019 20:32:58 +0200 Subject: [PATCH 454/545] Uninitialized boxes: check for zero-size allocation based on Layout::size --- src/liballoc/boxed.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 2693a64e13ba..567b8ea72249 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -141,10 +141,10 @@ pub fn new(x: T) -> Box { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit() -> Box> { - if mem::size_of::() == 0 { + let layout = alloc::Layout::new::>(); + if layout.size() == 0 { return Box(NonNull::dangling().into()) } - let layout = alloc::Layout::new::>(); let ptr = unsafe { Global.alloc(layout) .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) @@ -184,10 +184,10 @@ impl Box<[T]> { /// ``` #[unstable(feature = "new_uninit", issue = "63291")] pub fn new_uninit_slice(len: usize) -> Box<[mem::MaybeUninit]> { - let ptr = if mem::size_of::() == 0 || len == 0 { + let layout = alloc::Layout::array::>(len).unwrap(); + let ptr = if layout.size() == 0 { NonNull::dangling() } else { - let layout = alloc::Layout::array::>(len).unwrap(); unsafe { Global.alloc(layout) .unwrap_or_else(|_| alloc::handle_alloc_error(layout)) From 91a3db95a1a5939054d72d2ce69c5647c3cfb93b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 29 Aug 2019 16:06:44 -0700 Subject: [PATCH 455/545] Add check for overlapping ranges to unreachable patterns lint --- src/libcore/ascii.rs | 2 + src/librustc_mir/hair/pattern/_match.rs | 230 +++++++++++++----- src/librustc_mir/hair/pattern/check_match.rs | 20 +- src/test/ui/check_match/issue-43253.rs | 17 +- src/test/ui/check_match/issue-43253.stderr | 42 +++- src/test/ui/exhaustive_integer_patterns.rs | 8 +- .../ui/exhaustive_integer_patterns.stderr | 32 ++- .../ui/match/match-range-fail-dominate.rs | 24 +- .../ui/match/match-range-fail-dominate.stderr | 42 ++-- src/test/ui/precise_pointer_size_matching.rs | 4 +- .../ui/precise_pointer_size_matching.stderr | 24 +- 11 files changed, 326 insertions(+), 119 deletions(-) diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index 4087333e2cf6..0492fbd55faf 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -100,6 +100,8 @@ pub fn escape_default(c: u8) -> EscapeDefault { b'\\' => ([b'\\', b'\\', 0, 0], 2), b'\'' => ([b'\\', b'\'', 0, 0], 2), b'"' => ([b'\\', b'"', 0, 0], 2), + // The three arms above are in the following range + #[allow(unreachable_patterns)] b'\x20' ..= b'\x7e' => ([c, 0, 0, 0], 1), _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4), }; diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 3ea580528772..542f0ba5c9ca 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -167,13 +167,14 @@ use super::{PatternFoldable, PatternFolder, compare_const_vals}; use rustc::hir::def_id::DefId; -use rustc::hir::RangeEnd; +use rustc::hir::{RangeEnd, HirId}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Const}; use rustc::ty::layout::{Integer, IntegerExt, VariantIdx, Size}; use rustc::mir::Field; use rustc::mir::interpret::{ConstValue, Scalar, truncate, AllocId, Pointer}; use rustc::util::common::ErrorReported; +use rustc::lint; use syntax::attr::{SignedInt, UnsignedInt}; use syntax_pos::{Span, DUMMY_SP}; @@ -418,7 +419,7 @@ fn is_local(&self, ty: Ty<'tcx>) -> bool { } } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug)] enum Constructor<'tcx> { /// The constructor of all patterns that don't vary by constructor, /// e.g., struct patterns and fixed-length arrays. @@ -426,13 +427,30 @@ enum Constructor<'tcx> { /// Enum variants. Variant(DefId), /// Literal values. - ConstantValue(&'tcx ty::Const<'tcx>), + ConstantValue(&'tcx ty::Const<'tcx>, Span), /// Ranges of literal values (`2..=5` and `2..5`). - ConstantRange(u128, u128, Ty<'tcx>, RangeEnd), + ConstantRange(u128, u128, Ty<'tcx>, RangeEnd, Span), /// Array patterns of length n. Slice(u64), } +// Ignore spans when comparing, they don't carry semantic information as they are only for lints. +impl<'tcx> std::cmp::PartialEq for Constructor<'tcx> { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Constructor::Single, Constructor::Single) => true, + (Constructor::Variant(a), Constructor::Variant(b)) => a == b, + (Constructor::ConstantValue(a, _), Constructor::ConstantValue(b, _)) => a == b, + ( + Constructor::ConstantRange(a_start, a_end, a_ty, a_range_end, _), + Constructor::ConstantRange(b_start, b_end, b_ty, b_range_end, _), + ) => a_start == b_start && a_end == b_end && a_ty == b_ty && a_range_end == b_range_end, + (Constructor::Slice(a), Constructor::Slice(b)) => a == b, + _ => false, + } + } +} + impl<'tcx> Constructor<'tcx> { fn is_slice(&self) -> bool { match self { @@ -447,15 +465,36 @@ fn variant_index_for_adt<'a>( adt: &'tcx ty::AdtDef, ) -> VariantIdx { match self { - &Variant(id) => adt.variant_index_with_id(id), - &Single => { + Variant(id) => adt.variant_index_with_id(*id), + Single => { assert!(!adt.is_enum()); VariantIdx::new(0) } - &ConstantValue(c) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c), + ConstantValue(c, _) => crate::const_eval::const_variant_index(cx.tcx, cx.param_env, c), _ => bug!("bad constructor {:?} for adt {:?}", self, adt) } } + + fn display(&self, tcx: TyCtxt<'tcx>) -> String { + match self { + Constructor::ConstantValue(val, _) => format!("{}", val), + Constructor::ConstantRange(lo, hi, ty, range_end, _) => { + // Get the right sign on the output: + let ty = ty::ParamEnv::empty().and(*ty); + format!( + "{}..{}{}", + ty::Const::from_bits(tcx, *lo, ty), + match range_end { + RangeEnd::Included => "=", + RangeEnd::Excluded => "", + }, + ty::Const::from_bits(tcx, *hi, ty), + ) + } + Constructor::Slice(val) => format!("[{}]", val), + _ => bug!("bad constructor being displayed: `{:?}", self), + } + } } #[derive(Clone, Debug)] @@ -484,6 +523,7 @@ pub enum WitnessPreference { struct PatCtxt<'tcx> { ty: Ty<'tcx>, max_slice_length: u64, + span: Span, } /// A witness of non-exhaustiveness for error reporting, represented @@ -610,8 +650,8 @@ fn apply_constructor<'a>( _ => { match *ctor { - ConstantValue(value) => PatKind::Constant { value }, - ConstantRange(lo, hi, ty, end) => PatKind::Range(PatRange { + ConstantValue(value, _) => PatKind::Constant { value }, + ConstantRange(lo, hi, ty, end, _) => PatKind::Range(PatRange { lo: ty::Const::from_bits(cx.tcx, lo, ty::ParamEnv::empty().and(ty)), hi: ty::Const::from_bits(cx.tcx, hi, ty::ParamEnv::empty().and(ty)), end, @@ -647,7 +687,7 @@ fn all_constructors<'a, 'tcx>( let ctors = match pcx.ty.kind { ty::Bool => { [true, false].iter().map(|&b| { - ConstantValue(ty::Const::from_bool(cx.tcx, b)) + ConstantValue(ty::Const::from_bool(cx.tcx, b), pcx.span) }).collect() } ty::Array(ref sub_ty, len) if len.try_eval_usize(cx.tcx, cx.param_env).is_some() => { @@ -679,15 +719,19 @@ fn all_constructors<'a, 'tcx>( ty::Char => { vec![ // The valid Unicode Scalar Value ranges. - ConstantRange('\u{0000}' as u128, - '\u{D7FF}' as u128, - cx.tcx.types.char, - RangeEnd::Included + ConstantRange( + '\u{0000}' as u128, + '\u{D7FF}' as u128, + cx.tcx.types.char, + RangeEnd::Included, + pcx.span, ), - ConstantRange('\u{E000}' as u128, - '\u{10FFFF}' as u128, - cx.tcx.types.char, - RangeEnd::Included + ConstantRange( + '\u{E000}' as u128, + '\u{10FFFF}' as u128, + cx.tcx.types.char, + RangeEnd::Included, + pcx.span, ), ] } @@ -695,12 +739,12 @@ fn all_constructors<'a, 'tcx>( let bits = Integer::from_attr(&cx.tcx, SignedInt(ity)).size().bits() as u128; let min = 1u128 << (bits - 1); let max = min - 1; - vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included)] + vec![ConstantRange(min, max, pcx.ty, RangeEnd::Included, pcx.span)] } ty::Uint(uty) => { let size = Integer::from_attr(&cx.tcx, UnsignedInt(uty)).size(); let max = truncate(u128::max_value(), size); - vec![ConstantRange(0, max, pcx.ty, RangeEnd::Included)] + vec![ConstantRange(0, max, pcx.ty, RangeEnd::Included, pcx.span)] } _ => { if cx.is_uninhabited(pcx.ty) { @@ -827,10 +871,11 @@ fn max_slice_length<'p, 'a, 'tcx, I>(cx: &mut MatchCheckCtxt<'a, 'tcx>, patterns /// /// `IntRange` is never used to encode an empty range or a "range" that wraps /// around the (offset) space: i.e., `range.lo <= range.hi`. -#[derive(Clone)] +#[derive(Clone, Debug)] struct IntRange<'tcx> { pub range: RangeInclusive, pub ty: Ty<'tcx>, + pub span: Span, } impl<'tcx> IntRange<'tcx> { @@ -860,6 +905,7 @@ fn from_const( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, value: &Const<'tcx>, + span: Span, ) -> Option> { if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, value.ty) { let ty = value.ty; @@ -877,7 +923,7 @@ fn from_const( return None }; let val = val ^ bias; - Some(IntRange { range: val..=val, ty }) + Some(IntRange { range: val..=val, ty, span }) } else { None } @@ -890,6 +936,7 @@ fn from_range( hi: u128, ty: Ty<'tcx>, end: &RangeEnd, + span: Span, ) -> Option> { if Self::is_integral(ty) { // Perform a shift if the underlying types are signed, @@ -901,7 +948,7 @@ fn from_range( None } else { let offset = (*end == RangeEnd::Excluded) as u128; - Some(IntRange { range: lo..=(hi - offset), ty }) + Some(IntRange { range: lo..=(hi - offset), ty, span }) } } else { None @@ -916,8 +963,8 @@ fn from_ctor( // Floating-point ranges are permitted and we don't want // to consider them when constructing integer ranges. match ctor { - ConstantRange(lo, hi, ty, end) => Self::from_range(tcx, *lo, *hi, ty, end), - ConstantValue(val) => Self::from_const(tcx, param_env, val), + ConstantRange(lo, hi, ty, end, span) => Self::from_range(tcx, *lo, *hi, ty, end, *span), + ConstantValue(val, span) => Self::from_const(tcx, param_env, val, *span), _ => None, } } @@ -930,7 +977,7 @@ fn from_pat( loop { match pat.kind { box PatKind::Constant { value } => { - return Self::from_const(tcx, param_env, value); + return Self::from_const(tcx, param_env, value, pat.span); } box PatKind::Range(PatRange { lo, hi, end }) => { return Self::from_range( @@ -939,6 +986,7 @@ fn from_pat( hi.eval_bits(tcx, param_env, hi.ty), &lo.ty, &end, + pat.span, ); } box PatKind::AscribeUserType { ref subpattern, .. } => { @@ -965,14 +1013,15 @@ fn range_to_ctor( tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, r: RangeInclusive, + span: Span, ) -> Constructor<'tcx> { let bias = IntRange::signed_bias(tcx, ty); let (lo, hi) = r.into_inner(); if lo == hi { let ty = ty::ParamEnv::empty().and(ty); - ConstantValue(ty::Const::from_bits(tcx, lo ^ bias, ty)) + ConstantValue(ty::Const::from_bits(tcx, lo ^ bias, ty), span) } else { - ConstantRange(lo ^ bias, hi ^ bias, ty, RangeEnd::Included) + ConstantRange(lo ^ bias, hi ^ bias, ty, RangeEnd::Included, span) } } @@ -995,17 +1044,23 @@ fn subtract_from( if lo > subrange_hi || subrange_lo > hi { // The pattern doesn't intersect with the subrange at all, // so the subrange remains untouched. - remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=subrange_hi)); + remaining_ranges.push( + Self::range_to_ctor(tcx, ty, subrange_lo..=subrange_hi, self.span), + ); } else { if lo > subrange_lo { // The pattern intersects an upper section of the // subrange, so a lower section will remain. - remaining_ranges.push(Self::range_to_ctor(tcx, ty, subrange_lo..=(lo - 1))); + remaining_ranges.push( + Self::range_to_ctor(tcx, ty, subrange_lo..=(lo - 1), self.span), + ); } if hi < subrange_hi { // The pattern intersects a lower section of the // subrange, so an upper section will remain. - remaining_ranges.push(Self::range_to_ctor(tcx, ty, (hi + 1)..=subrange_hi)); + remaining_ranges.push( + Self::range_to_ctor(tcx, ty, (hi + 1)..=subrange_hi, self.span), + ); } } } @@ -1017,7 +1072,8 @@ fn intersection(&self, other: &Self) -> Option { let (lo, hi) = (*self.range.start(), *self.range.end()); let (other_lo, other_hi) = (*other.range.start(), *other.range.end()); if lo <= other_hi && other_lo <= hi { - Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty }) + let span = other.span; + Some(IntRange { range: max(lo, other_lo)..=min(hi, other_hi), ty, span }) } else { None } @@ -1127,6 +1183,7 @@ pub fn is_useful<'p, 'a, 'tcx>( matrix: &Matrix<'p, 'tcx>, v: &[&Pat<'tcx>], witness: WitnessPreference, + hir_id: HirId, ) -> Usefulness<'tcx> { let &Matrix(ref rows) = matrix; debug!("is_useful({:#?}, {:#?})", matrix, v); @@ -1149,6 +1206,10 @@ pub fn is_useful<'p, 'a, 'tcx>( assert!(rows.iter().all(|r| r.len() == v.len())); + let (ty, span) = rows.iter() + .map(|r| (r[0].ty, r[0].span)) + .find(|(ty, _)| !ty.references_error()) + .unwrap_or((v[0].ty, v[0].span)); let pcx = PatCtxt { // TyErr is used to represent the type of wildcard patterns matching // against inaccessible (private) fields of structs, so that we won't @@ -1169,8 +1230,9 @@ pub fn is_useful<'p, 'a, 'tcx>( // FIXME: this might lead to "unstable" behavior with macro hygiene // introducing uninhabited patterns for inaccessible fields. We // need to figure out how to model that. - ty: rows.iter().map(|r| r[0].ty).find(|ty| !ty.references_error()).unwrap_or(v[0].ty), - max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0]))) + ty, + max_slice_length: max_slice_length(cx, rows.iter().map(|r| r[0]).chain(Some(v[0]))), + span, }; debug!("is_useful_expand_first_col: pcx={:#?}, expanding {:#?}", pcx, v[0]); @@ -1184,9 +1246,9 @@ pub fn is_useful<'p, 'a, 'tcx>( Useful } else { split_grouped_constructors( - cx.tcx, cx.param_env, constructors, matrix, pcx.ty, + cx.tcx, cx.param_env, constructors, matrix, pcx.ty, pcx.span, Some(hir_id), ).into_iter().map(|c| - is_useful_specialized(cx, matrix, v, c, pcx.ty, witness) + is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id) ).find(|result| result.is_useful()).unwrap_or(NotUseful) } } else { @@ -1239,8 +1301,11 @@ pub fn is_useful<'p, 'a, 'tcx>( (pcx.ty.is_ptr_sized_integral() && !cx.tcx.features().precise_pointer_size_matching); if cheap_missing_ctors == MissingCtors::Empty && !is_non_exhaustive { - split_grouped_constructors(cx.tcx, cx.param_env, all_ctors, matrix, pcx.ty) - .into_iter().map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness)) + split_grouped_constructors( + cx.tcx, cx.param_env, all_ctors, matrix, pcx.ty, DUMMY_SP, None, + ) + .into_iter() + .map(|c| is_useful_specialized(cx, matrix, v, c, pcx.ty, witness, hir_id)) .find(|result| result.is_useful()) .unwrap_or(NotUseful) } else { @@ -1251,7 +1316,7 @@ pub fn is_useful<'p, 'a, 'tcx>( None } }).collect(); - match is_useful(cx, &matrix, &v[1..], witness) { + match is_useful(cx, &matrix, &v[1..], witness, hir_id) { UsefulWithWitness(pats) => { let cx = &*cx; // In this case, there's at least one "free" @@ -1344,6 +1409,7 @@ fn is_useful_specialized<'p, 'a, 'tcx>( ctor: Constructor<'tcx>, lty: Ty<'tcx>, witness: WitnessPreference, + hir_id: HirId, ) -> Usefulness<'tcx> { debug!("is_useful_specialized({:#?}, {:#?}, {:?})", v, ctor, lty); let sub_pat_tys = constructor_sub_pattern_tys(cx, &ctor, lty); @@ -1361,7 +1427,7 @@ fn is_useful_specialized<'p, 'a, 'tcx>( .collect() ); match specialize(cx, v, &ctor, &wild_patterns) { - Some(v) => match is_useful(cx, &matrix, &v, witness) { + Some(v) => match is_useful(cx, &matrix, &v, witness, hir_id) { UsefulWithWitness(witnesses) => UsefulWithWitness( witnesses.into_iter() .map(|witness| witness.apply_constructor(cx, &ctor, lty)) @@ -1381,11 +1447,11 @@ fn is_useful_specialized<'p, 'a, 'tcx>( /// `[a, b, ..tail]` can match a slice of length 2, 3, 4 and so on. /// /// Returns `None` in case of a catch-all, which can't be specialized. -fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, - pat: &Pat<'tcx>, - pcx: PatCtxt<'tcx>) - -> Option>> -{ +fn pat_constructors<'tcx>( + cx: &mut MatchCheckCtxt<'_, 'tcx>, + pat: &Pat<'tcx>, + pcx: PatCtxt<'tcx>, +) -> Option>> { match *pat.kind { PatKind::AscribeUserType { ref subpattern, .. } => pat_constructors(cx, subpattern, pcx), @@ -1394,13 +1460,14 @@ fn pat_constructors<'tcx>(cx: &mut MatchCheckCtxt<'_, 'tcx>, PatKind::Variant { adt_def, variant_index, .. } => { Some(vec![Variant(adt_def.variants[variant_index].def_id)]) } - PatKind::Constant { value } => Some(vec![ConstantValue(value)]), + PatKind::Constant { value } => Some(vec![ConstantValue(value, pat.span)]), PatKind::Range(PatRange { lo, hi, end }) => Some(vec![ConstantRange( lo.eval_bits(cx.tcx, cx.param_env, lo.ty), hi.eval_bits(cx.tcx, cx.param_env, hi.ty), lo.ty, end, + pat.span, )]), PatKind::Array { .. } => match pcx.ty.kind { ty::Array(_, length) => Some(vec![ @@ -1433,7 +1500,7 @@ fn constructor_arity(cx: &MatchCheckCtxt<'a, 'tcx>, ctor: &Constructor<'tcx>, ty ty::Tuple(ref fs) => fs.len() as u64, ty::Slice(..) | ty::Array(..) => match *ctor { Slice(length) => length, - ConstantValue(_) => 0, + ConstantValue(..) => 0, _ => bug!("bad slice pattern {:?} {:?}", ctor, ty) } ty::Ref(..) => 1, @@ -1458,7 +1525,7 @@ fn constructor_sub_pattern_tys<'a, 'tcx>( ty::Tuple(ref fs) => fs.into_iter().map(|t| t.expect_ty()).collect(), ty::Slice(ty) | ty::Array(ty, _) => match *ctor { Slice(length) => (0..length).map(|_| ty).collect(), - ConstantValue(_) => vec![], + ConstantValue(..) => vec![], _ => bug!("bad slice pattern {:?} {:?}", ctor, ty) } ty::Ref(_, rty, _) => vec![rty], @@ -1556,8 +1623,8 @@ fn slice_pat_covered_by_const<'tcx>( // constructor is a range or constant with an integer type. fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) -> bool { let ty = match ctor { - ConstantValue(value) => value.ty, - ConstantRange(_, _, ty, _) => ty, + ConstantValue(value, _) => value.ty, + ConstantRange(_, _, ty, _, _) => ty, _ => return false, }; if let ty::Char | ty::Int(_) | ty::Uint(_) = ty.kind { @@ -1599,12 +1666,17 @@ fn should_treat_range_exhaustively(tcx: TyCtxt<'tcx>, ctor: &Constructor<'tcx>) /// boundaries for each interval range, sort them, then create constructors for each new interval /// between every pair of boundary points. (This essentially sums up to performing the intuitive /// merging operation depicted above.) +/// +/// `hir_id` is `None` when we're evaluating the wildcard pattern, do not lint for overlapping in +/// ranges that case. fn split_grouped_constructors<'p, 'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ctors: Vec>, &Matrix(ref m): &Matrix<'p, 'tcx>, ty: Ty<'tcx>, + span: Span, + hir_id: Option, ) -> Vec> { let mut split_ctors = Vec::with_capacity(ctors.len()); @@ -1621,7 +1693,7 @@ fn split_grouped_constructors<'p, 'tcx>( /// Represents a border between 2 integers. Because the intervals spanning borders /// must be able to cover every integer, we need to be able to represent /// 2^128 + 1 such borders. - #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)] enum Border { JustBefore(u128), AfterMax, @@ -1638,16 +1710,54 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator { vec![from, to].into_iter() } + // Collect the span and range of all the intersecting ranges to lint on likely + // incorrect range patterns. (#63987) + let mut overlaps = vec![]; // `borders` is the set of borders between equivalence classes: each equivalence // class lies between 2 borders. let row_borders = m.iter() - .flat_map(|row| IntRange::from_pat(tcx, param_env, row[0])) - .flat_map(|range| ctor_range.intersection(&range)) + .flat_map(|row| { + IntRange::from_pat(tcx, param_env, row[0]).map(|r| (r, row.len())) + }) + .flat_map(|(range, row_len)| { + let intersection = ctor_range.intersection(&range); + if let (Some(range), 1) = (&intersection, row_len) { + // FIXME: for now, only check for overlapping ranges on simple range + // patterns. Otherwise with the current logic the following is detected + // as overlapping: + // match (10u8, true) { + // (0 ..= 125, false) => {} + // (126 ..= 255, false) => {} + // (0 ..= 255, true) => {} + // } + overlaps.push(range.clone()); + } + intersection + }) .flat_map(|range| range_borders(range)); let ctor_borders = range_borders(ctor_range.clone()); let mut borders: Vec<_> = row_borders.chain(ctor_borders).collect(); borders.sort_unstable(); + if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) { + let mut err = tcx.struct_span_lint_hir( + lint::builtin::UNREACHABLE_PATTERNS, + hir_id, + ctor_range.span, + "multiple patterns covering the same range", + ); + err.span_label(ctor_range.span, "overlapping patterns"); + for int_range in overlaps { + // Use the real type for user display of the ranges: + err.span_label(int_range.span, &format!( + "this range overlaps on `{}`", + IntRange::range_to_ctor(tcx, ty, int_range.range, DUMMY_SP) + .display(tcx), + )); + } + err.emit(); + } + // We're going to iterate through every pair of borders, making sure that each // represents an interval of nonnegative length, and convert each such interval // into a constructor. @@ -1655,18 +1765,18 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator { match (window[0], window[1]) { (Border::JustBefore(n), Border::JustBefore(m)) => { if n < m { - Some(IntRange { range: n..=(m - 1), ty }) + Some(IntRange { range: n..=(m - 1), ty, span }) } else { None } } (Border::JustBefore(n), Border::AfterMax) => { - Some(IntRange { range: n..=u128::MAX, ty }) + Some(IntRange { range: n..=u128::MAX, ty, span }) } (Border::AfterMax, _) => None, } }) { - split_ctors.push(IntRange::range_to_ctor(tcx, ty, range)); + split_ctors.push(IntRange::range_to_ctor(tcx, ty, range, span)); } } // Any other constructor can be used unchanged. @@ -1701,13 +1811,13 @@ macro_rules! some_or_ok { }; } match *ctor { - ConstantValue(value) => { + ConstantValue(value, _) => { let to = some_or_ok!(cmp_to(value)); let end = (to == Ordering::Less) || (end == RangeEnd::Included && to == Ordering::Equal); Ok(some_or_ok!(cmp_from(value)) && end) }, - ConstantRange(from, to, ty, RangeEnd::Included) => { + ConstantRange(from, to, ty, RangeEnd::Included, _) => { let to = some_or_ok!(cmp_to(ty::Const::from_bits( tcx, to, @@ -1721,7 +1831,7 @@ macro_rules! some_or_ok { ty::ParamEnv::empty().and(ty), ))) && end) }, - ConstantRange(from, to, ty, RangeEnd::Excluded) => { + ConstantRange(from, to, ty, RangeEnd::Excluded, _) => { let to = some_or_ok!(cmp_to(ty::Const::from_bits( tcx, to, @@ -1915,7 +2025,7 @@ fn specialize<'p, 'a: 'p, 'tcx>( None } } - ConstantValue(cv) => { + ConstantValue(cv, _) => { match slice_pat_covered_by_const( cx.tcx, pat.span, cv, prefix, slice, suffix, cx.param_env, ) { diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 9bed4fb66ea9..fe57e12bcfcc 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -10,6 +10,7 @@ use rustc::lint; use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc::hir::HirId; use rustc::hir::def::*; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; @@ -239,7 +240,7 @@ fn check_match( .map(|pat| smallvec![pat.0]) .collect(); let scrut_ty = self.tables.node_type(scrut.hir_id); - check_exhaustive(cx, scrut_ty, scrut.span, &matrix); + check_exhaustive(cx, scrut_ty, scrut.span, &matrix, scrut.hir_id); }) } @@ -256,7 +257,7 @@ fn check_irrefutable(&self, pat: &'tcx Pat, origin: &str, sp: Option) { expand_pattern(cx, pattern) ]].into_iter().collect(); - let witnesses = match check_not_useful(cx, pattern_ty, &pats) { + let witnesses = match check_not_useful(cx, pattern_ty, &pats, pat.hir_id) { Ok(_) => return, Err(err) => err, }; @@ -389,7 +390,7 @@ fn check_arms<'tcx>( for &(pat, hir_pat) in pats { let v = smallvec![pat]; - match is_useful(cx, &seen, &v, LeaveOutWitness) { + match is_useful(cx, &seen, &v, LeaveOutWitness, hir_pat.hir_id) { NotUseful => { match source { hir::MatchSource::IfDesugar { .. } | @@ -428,6 +429,13 @@ fn check_arms<'tcx>( hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { + match pat.kind { + box PatternKind::Range(..) => { + // Covered in `is_useful() with more context` + break; + } + _ => {} + } let mut err = cx.tcx.struct_span_lint_hir( lint::builtin::UNREACHABLE_PATTERNS, hir_pat.hir_id, @@ -465,9 +473,10 @@ fn check_not_useful( cx: &mut MatchCheckCtxt<'_, 'tcx>, ty: Ty<'tcx>, matrix: &Matrix<'_, 'tcx>, + hir_id: HirId, ) -> Result<(), Vec>> { let wild_pattern = super::Pat { ty, span: DUMMY_SP, kind: box PatKind::Wild }; - match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness) { + match is_useful(cx, matrix, &[&wild_pattern], ConstructWitness, hir_id) { NotUseful => Ok(()), // This is good, wildcard pattern isn't reachable. UsefulWithWitness(pats) => Err(if pats.is_empty() { vec![wild_pattern] @@ -483,8 +492,9 @@ fn check_exhaustive<'tcx>( scrut_ty: Ty<'tcx>, sp: Span, matrix: &Matrix<'_, 'tcx>, + hir_id: HirId, ) { - let witnesses = match check_not_useful(cx, scrut_ty, matrix) { + let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) { Ok(_) => return, Err(err) => err, }; diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/check_match/issue-43253.rs index a4d6e9b777f0..548300da0340 100644 --- a/src/test/ui/check_match/issue-43253.rs +++ b/src/test/ui/check_match/issue-43253.rs @@ -1,4 +1,4 @@ -// build-pass (FIXME(62277): could be check-pass?) +// check-pass #![feature(exclusive_range_pattern)] #![warn(unreachable_patterns)] @@ -13,7 +13,7 @@ fn main() { match 10 { 1..10 => {}, - 9..=10 => {}, + 9..=10 => {}, //~ WARNING multiple patterns covering the same range _ => {}, } @@ -23,22 +23,25 @@ fn main() { _ => {}, } - // These cases should generate an "unreachable pattern" warning. + // These cases should generate "unreachable pattern" warnings. match 10 { 1..10 => {}, - 9 => {}, + 9 => {}, //~ WARNING unreachable pattern _ => {}, } match 10 { 1..10 => {}, - 8..=9 => {}, + 8..=9 => {}, //~ WARNING multiple patterns covering the same range _ => {}, } match 10 { - 1..10 => {}, - 9..=9 => {}, + 5..7 => {}, + 6 => {}, //~ WARNING unreachable pattern + 1..10 => {}, //~ WARNING multiple patterns covering the same range + 9..=9 => {}, //~ WARNING unreachable pattern + 6 => {}, //~ WARNING unreachable pattern _ => {}, } } diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr index d961f623e1fa..24dfa52beb68 100644 --- a/src/test/ui/check_match/issue-43253.stderr +++ b/src/test/ui/check_match/issue-43253.stderr @@ -1,8 +1,10 @@ -warning: unreachable pattern - --> $DIR/issue-43253.rs:29:9 +warning: multiple patterns covering the same range + --> $DIR/issue-43253.rs:16:9 | -LL | 9 => {}, - | ^ +LL | 1..10 => {}, + | ----- this range overlaps on `9i32` +LL | 9..=10 => {}, + | ^^^^^^ overlapping patterns | note: lint level defined here --> $DIR/issue-43253.rs:4:9 @@ -11,14 +13,44 @@ LL | #![warn(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ warning: unreachable pattern + --> $DIR/issue-43253.rs:29:9 + | +LL | 9 => {}, + | ^ + +warning: multiple patterns covering the same range --> $DIR/issue-43253.rs:35:9 | +LL | 1..10 => {}, + | ----- this range overlaps on `8i32..=9i32` LL | 8..=9 => {}, - | ^^^^^ + | ^^^^^ overlapping patterns warning: unreachable pattern --> $DIR/issue-43253.rs:41:9 | +LL | 6 => {}, + | ^ + +warning: multiple patterns covering the same range + --> $DIR/issue-43253.rs:42:9 + | +LL | 5..7 => {}, + | ---- this range overlaps on `5i32..=6i32` +LL | 6 => {}, + | - this range overlaps on `6i32` +LL | 1..10 => {}, + | ^^^^^ overlapping patterns + +warning: unreachable pattern + --> $DIR/issue-43253.rs:43:9 + | LL | 9..=9 => {}, | ^^^^^ +warning: unreachable pattern + --> $DIR/issue-43253.rs:44:9 + | +LL | 6 => {}, + | ^ + diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/exhaustive_integer_patterns.rs index 2570bc8a5607..ce2b44b8ef16 100644 --- a/src/test/ui/exhaustive_integer_patterns.rs +++ b/src/test/ui/exhaustive_integer_patterns.rs @@ -19,7 +19,7 @@ fn main() { 0 ..= 32 => {} 33 => {} 34 .. 128 => {} - 100 ..= 200 => {} + 100 ..= 200 => {} //~ ERROR multiple patterns covering the same range 200 => {} //~ ERROR unreachable pattern 201 ..= 255 => {} } @@ -41,7 +41,7 @@ fn main() { match x { //~ ERROR non-exhaustive patterns -7 => {} -5..=120 => {} - -2..=20 => {} //~ ERROR unreachable pattern + -2..=20 => {} //~ ERROR multiple patterns covering the same range 125 => {} } @@ -135,9 +135,9 @@ fn main() { (125 .. 128, false) => {} } - match 0u8 { // ok + match 0u8 { 0 .. 2 => {} - 1 ..= 2 => {} + 1 ..= 2 => {} //~ ERROR multiple patterns covering the same range _ => {} } diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr index 6c4b7b0cc035..ef3faceaa7e1 100644 --- a/src/test/ui/exhaustive_integer_patterns.stderr +++ b/src/test/ui/exhaustive_integer_patterns.stderr @@ -1,8 +1,10 @@ -error: unreachable pattern - --> $DIR/exhaustive_integer_patterns.rs:23:9 +error: multiple patterns covering the same range + --> $DIR/exhaustive_integer_patterns.rs:22:9 | -LL | 200 => {} - | ^^^ +LL | 34 .. 128 => {} + | --------- this range overlaps on `100u8..=127u8` +LL | 100 ..= 200 => {} + | ^^^^^^^^^^^ overlapping patterns | note: lint level defined here --> $DIR/exhaustive_integer_patterns.rs:4:9 @@ -10,6 +12,12 @@ note: lint level defined here LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ +error: unreachable pattern + --> $DIR/exhaustive_integer_patterns.rs:23:9 + | +LL | 200 => {} + | ^^^ + error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered --> $DIR/exhaustive_integer_patterns.rs:28:11 | @@ -26,11 +34,13 @@ LL | match x { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: unreachable pattern +error: multiple patterns covering the same range --> $DIR/exhaustive_integer_patterns.rs:44:9 | +LL | -5..=120 => {} + | -------- this range overlaps on `-2i8..=20i8` LL | -2..=20 => {} - | ^^^^^^^ + | ^^^^^^^ overlapping patterns error[E0004]: non-exhaustive patterns: `std::i8::MIN..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered --> $DIR/exhaustive_integer_patterns.rs:41:11 @@ -80,6 +90,14 @@ LL | match (0u8, true) { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms +error: multiple patterns covering the same range + --> $DIR/exhaustive_integer_patterns.rs:140:9 + | +LL | 0 .. 2 => {} + | ------ this range overlaps on `1u8` +LL | 1 ..= 2 => {} + | ^^^^^^^ overlapping patterns + error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered --> $DIR/exhaustive_integer_patterns.rs:145:11 | @@ -104,6 +122,6 @@ LL | match 0u128 { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to 13 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/match/match-range-fail-dominate.rs b/src/test/ui/match/match-range-fail-dominate.rs index a0cc773d20ed..4c0f57ffbeed 100644 --- a/src/test/ui/match/match-range-fail-dominate.rs +++ b/src/test/ui/match/match-range-fail-dominate.rs @@ -1,39 +1,41 @@ -//error-pattern: unreachable -//error-pattern: unreachable -//error-pattern: unreachable -//error-pattern: unreachable -//error-pattern: unreachable - #![deny(unreachable_patterns)] fn main() { match 5 { 1 ..= 10 => { } - 5 ..= 6 => { } + 5 ..= 6 => { } //~ ERROR multiple patterns covering the same range _ => {} }; match 5 { 3 ..= 6 => { } - 4 ..= 6 => { } + 4 ..= 6 => { } //~ ERROR multiple patterns covering the same range _ => {} }; match 5 { 4 ..= 6 => { } - 4 ..= 6 => { } + 4 ..= 6 => { } //~ ERROR multiple patterns covering the same range _ => {} }; match 'c' { 'A' ..= 'z' => {} - 'a' ..= 'z' => {} + 'a' ..= 'z' => {} //~ ERROR multiple patterns covering the same range _ => {} }; match 1.0f64 { 0.01f64 ..= 6.5f64 => {} - 0.02f64 => {} + //~^ WARNING floating-point types cannot be used in patterns + //~| WARNING floating-point types cannot be used in patterns + //~| WARNING floating-point types cannot be used in patterns + //~| WARNING this was previously accepted by the compiler + //~| WARNING this was previously accepted by the compiler + //~| WARNING this was previously accepted by the compiler + 0.02f64 => {} //~ ERROR unreachable pattern + //~^ WARNING floating-point types cannot be used in patterns + //~| WARNING this was previously accepted by the compiler _ => {} }; } diff --git a/src/test/ui/match/match-range-fail-dominate.stderr b/src/test/ui/match/match-range-fail-dominate.stderr index d0ff4930a451..af667be317de 100644 --- a/src/test/ui/match/match-range-fail-dominate.stderr +++ b/src/test/ui/match/match-range-fail-dominate.stderr @@ -1,35 +1,43 @@ -error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:12:7 +error: multiple patterns covering the same range + --> $DIR/match-range-fail-dominate.rs:6:7 | +LL | 1 ..= 10 => { } + | -------- this range overlaps on `5i32..=6i32` LL | 5 ..= 6 => { } - | ^^^^^^^ + | ^^^^^^^ overlapping patterns | note: lint level defined here - --> $DIR/match-range-fail-dominate.rs:7:9 + --> $DIR/match-range-fail-dominate.rs:1:9 | LL | #![deny(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: unreachable pattern +error: multiple patterns covering the same range + --> $DIR/match-range-fail-dominate.rs:12:7 + | +LL | 3 ..= 6 => { } + | ------- this range overlaps on `4i32..=6i32` +LL | 4 ..= 6 => { } + | ^^^^^^^ overlapping patterns + +error: multiple patterns covering the same range --> $DIR/match-range-fail-dominate.rs:18:7 | LL | 4 ..= 6 => { } - | ^^^^^^^ + | ------- this range overlaps on `4i32..=6i32` +LL | 4 ..= 6 => { } + | ^^^^^^^ overlapping patterns -error: unreachable pattern +error: multiple patterns covering the same range --> $DIR/match-range-fail-dominate.rs:24:7 | -LL | 4 ..= 6 => { } - | ^^^^^^^ - -error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:30:7 - | +LL | 'A' ..= 'z' => {} + | ----------- this range overlaps on `'a'..='z'` LL | 'a' ..= 'z' => {} - | ^^^^^^^^^^^ + | ^^^^^^^^^^^ overlapping patterns warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:35:7 + --> $DIR/match-range-fail-dominate.rs:29:7 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ @@ -39,7 +47,7 @@ LL | 0.01f64 ..= 6.5f64 => {} = note: for more information, see issue #41620 warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:35:19 + --> $DIR/match-range-fail-dominate.rs:29:19 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^ @@ -63,7 +71,7 @@ LL | 0.02f64 => {} | ^^^^^^^ warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:35:7 + --> $DIR/match-range-fail-dominate.rs:29:7 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ diff --git a/src/test/ui/precise_pointer_size_matching.rs b/src/test/ui/precise_pointer_size_matching.rs index 759b63b188b3..239197af2ca1 100644 --- a/src/test/ui/precise_pointer_size_matching.rs +++ b/src/test/ui/precise_pointer_size_matching.rs @@ -23,11 +23,11 @@ fn main() { match 0isize { //~ ERROR non-exhaustive patterns 1 ..= 8 => {} - -5 ..= 20 => {} + -5 ..= 20 => {} //~ ERROR multiple patterns covering the same range } match 0usize { //~ ERROR non-exhaustive patterns 1 ..= 8 => {} - 5 ..= 20 => {} + 5 ..= 20 => {} //~ ERROR multiple patterns covering the same range } } diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr index 2c2c2aa04c23..06b0e73c5a3b 100644 --- a/src/test/ui/precise_pointer_size_matching.stderr +++ b/src/test/ui/precise_pointer_size_matching.stderr @@ -1,3 +1,17 @@ +error: multiple patterns covering the same range + --> $DIR/precise_pointer_size_matching.rs:26:9 + | +LL | 1 ..= 8 => {} + | ------- this range overlaps on `1isize..=8isize` +LL | -5 ..= 20 => {} + | ^^^^^^^^^ overlapping patterns + | +note: lint level defined here + --> $DIR/precise_pointer_size_matching.rs:11:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + error[E0004]: non-exhaustive patterns: `std::isize::MIN..=-6isize` and `21isize..=std::isize::MAX` not covered --> $DIR/precise_pointer_size_matching.rs:24:11 | @@ -6,6 +20,14 @@ LL | match 0isize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms +error: multiple patterns covering the same range + --> $DIR/precise_pointer_size_matching.rs:31:9 + | +LL | 1 ..= 8 => {} + | ------- this range overlaps on `5usize..=8usize` +LL | 5 ..= 20 => {} + | ^^^^^^^^ overlapping patterns + error[E0004]: non-exhaustive patterns: `0usize` and `21usize..=std::usize::MAX` not covered --> $DIR/precise_pointer_size_matching.rs:29:11 | @@ -14,6 +36,6 @@ LL | match 0usize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0004`. From 220b9b29c26953ff14eb94be70e9741365783aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 29 Aug 2019 17:16:39 -0700 Subject: [PATCH 456/545] Move overlapping patterns to its own lint --- src/libcore/ascii.rs | 2 +- src/librustc/lint/builtin.rs | 7 +++++++ src/librustc_lint/lib.rs | 1 + src/librustc_mir/hair/pattern/_match.rs | 2 +- src/test/ui/check_match/issue-43253.rs | 2 +- src/test/ui/check_match/issue-43253.stderr | 8 +++++++- src/test/ui/exhaustive_integer_patterns.rs | 2 +- src/test/ui/exhaustive_integer_patterns.stderr | 8 +++++++- src/test/ui/match/match-range-fail-dominate.rs | 2 +- src/test/ui/match/match-range-fail-dominate.stderr | 12 +++++++++--- src/test/ui/precise_pointer_size_matching.rs | 2 +- src/test/ui/precise_pointer_size_matching.stderr | 6 +++--- 12 files changed, 40 insertions(+), 14 deletions(-) diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index 0492fbd55faf..04aefd57ca2e 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -101,7 +101,7 @@ pub fn escape_default(c: u8) -> EscapeDefault { b'\'' => ([b'\\', b'\'', 0, 0], 2), b'"' => ([b'\\', b'"', 0, 0], 2), // The three arms above are in the following range - #[allow(unreachable_patterns)] + #[allow(overlapping_patterns)] b'\x20' ..= b'\x7e' => ([c, 0, 0, 0], 1), _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4), }; diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 983e3a9922ec..4c28f6372fe2 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -80,6 +80,12 @@ "detects unreachable patterns" } +declare_lint! { + pub OVERLAPPING_PATTERNS, + Warn, + "detects overlapping patterns" +} + declare_lint! { pub UNUSED_MACROS, Warn, @@ -423,6 +429,7 @@ pub mod parser { DEAD_CODE, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, + OVERLAPPING_PATTERNS, UNUSED_MACROS, WARNINGS, UNUSED_FEATURES, diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 0e054013cd77..e3860e229d6b 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -255,6 +255,7 @@ macro_rules! register_passes { UNUSED_MUT, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, + OVERLAPPING_PATTERNS, UNUSED_MUST_USE, UNUSED_UNSAFE, PATH_STATEMENTS, diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 542f0ba5c9ca..1b3c824458e7 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1741,7 +1741,7 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator { if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) { let mut err = tcx.struct_span_lint_hir( - lint::builtin::UNREACHABLE_PATTERNS, + lint::builtin::OVERLAPPING_PATTERNS, hir_id, ctor_range.span, "multiple patterns covering the same range", diff --git a/src/test/ui/check_match/issue-43253.rs b/src/test/ui/check_match/issue-43253.rs index 548300da0340..5c6834459f0d 100644 --- a/src/test/ui/check_match/issue-43253.rs +++ b/src/test/ui/check_match/issue-43253.rs @@ -1,7 +1,7 @@ // check-pass - #![feature(exclusive_range_pattern)] #![warn(unreachable_patterns)] +#![warn(overlapping_patterns)] fn main() { // These cases should generate no warning. diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr index 24dfa52beb68..2f6888c0118a 100644 --- a/src/test/ui/check_match/issue-43253.stderr +++ b/src/test/ui/check_match/issue-43253.stderr @@ -9,7 +9,7 @@ LL | 9..=10 => {}, note: lint level defined here --> $DIR/issue-43253.rs:4:9 | -LL | #![warn(unreachable_patterns)] +LL | #![warn(overlapping_patterns)] | ^^^^^^^^^^^^^^^^^^^^ warning: unreachable pattern @@ -17,6 +17,12 @@ warning: unreachable pattern | LL | 9 => {}, | ^ + | +note: lint level defined here + --> $DIR/issue-43253.rs:3:9 + | +LL | #![warn(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ warning: multiple patterns covering the same range --> $DIR/issue-43253.rs:35:9 diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/exhaustive_integer_patterns.rs index ce2b44b8ef16..ef88ce94aa6a 100644 --- a/src/test/ui/exhaustive_integer_patterns.rs +++ b/src/test/ui/exhaustive_integer_patterns.rs @@ -1,7 +1,7 @@ #![feature(precise_pointer_size_matching)] #![feature(exclusive_range_pattern)] - #![deny(unreachable_patterns)] +#![deny(overlapping_patterns)] use std::{char, u8, u16, u32, u64, u128, i8, i16, i32, i64, i128}; diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr index ef3faceaa7e1..59cd3fffa8df 100644 --- a/src/test/ui/exhaustive_integer_patterns.stderr +++ b/src/test/ui/exhaustive_integer_patterns.stderr @@ -9,7 +9,7 @@ LL | 100 ..= 200 => {} note: lint level defined here --> $DIR/exhaustive_integer_patterns.rs:4:9 | -LL | #![deny(unreachable_patterns)] +LL | #![deny(overlapping_patterns)] | ^^^^^^^^^^^^^^^^^^^^ error: unreachable pattern @@ -17,6 +17,12 @@ error: unreachable pattern | LL | 200 => {} | ^^^ + | +note: lint level defined here + --> $DIR/exhaustive_integer_patterns.rs:3:9 + | +LL | #![deny(unreachable_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered --> $DIR/exhaustive_integer_patterns.rs:28:11 diff --git a/src/test/ui/match/match-range-fail-dominate.rs b/src/test/ui/match/match-range-fail-dominate.rs index 4c0f57ffbeed..bdbb1f050a7a 100644 --- a/src/test/ui/match/match-range-fail-dominate.rs +++ b/src/test/ui/match/match-range-fail-dominate.rs @@ -1,4 +1,4 @@ -#![deny(unreachable_patterns)] +#![deny(unreachable_patterns, overlapping_patterns)] fn main() { match 5 { diff --git a/src/test/ui/match/match-range-fail-dominate.stderr b/src/test/ui/match/match-range-fail-dominate.stderr index af667be317de..b14e9b5008d9 100644 --- a/src/test/ui/match/match-range-fail-dominate.stderr +++ b/src/test/ui/match/match-range-fail-dominate.stderr @@ -7,10 +7,10 @@ LL | 5 ..= 6 => { } | ^^^^^^^ overlapping patterns | note: lint level defined here - --> $DIR/match-range-fail-dominate.rs:1:9 + --> $DIR/match-range-fail-dominate.rs:1:31 | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(unreachable_patterns, overlapping_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ error: multiple patterns covering the same range --> $DIR/match-range-fail-dominate.rs:12:7 @@ -69,6 +69,12 @@ error: unreachable pattern | LL | 0.02f64 => {} | ^^^^^^^ + | +note: lint level defined here + --> $DIR/match-range-fail-dominate.rs:1:9 + | +LL | #![deny(unreachable_patterns, overlapping_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ warning: floating-point types cannot be used in patterns --> $DIR/match-range-fail-dominate.rs:29:7 diff --git a/src/test/ui/precise_pointer_size_matching.rs b/src/test/ui/precise_pointer_size_matching.rs index 239197af2ca1..be2a140ddc3d 100644 --- a/src/test/ui/precise_pointer_size_matching.rs +++ b/src/test/ui/precise_pointer_size_matching.rs @@ -8,7 +8,7 @@ #![feature(precise_pointer_size_matching)] #![feature(exclusive_range_pattern)] -#![deny(unreachable_patterns)] +#![deny(unreachable_patterns, overlapping_patterns)] use std::{usize, isize}; diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr index 06b0e73c5a3b..4930047fc1e9 100644 --- a/src/test/ui/precise_pointer_size_matching.stderr +++ b/src/test/ui/precise_pointer_size_matching.stderr @@ -7,10 +7,10 @@ LL | -5 ..= 20 => {} | ^^^^^^^^^ overlapping patterns | note: lint level defined here - --> $DIR/precise_pointer_size_matching.rs:11:9 + --> $DIR/precise_pointer_size_matching.rs:11:31 | -LL | #![deny(unreachable_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ +LL | #![deny(unreachable_patterns, overlapping_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `std::isize::MIN..=-6isize` and `21isize..=std::isize::MAX` not covered --> $DIR/precise_pointer_size_matching.rs:24:11 From 916936c77488d0a75cc254b5bdc9a787c8ed8768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 29 Aug 2019 17:20:20 -0700 Subject: [PATCH 457/545] Silence lint in `fit_signed` and `fit_unsigned` --- src/librustc_target/abi/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index fde5c5bed4d9..2feee73847df 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -488,6 +488,7 @@ pub fn align(self, cx: &C) -> AbiAndPrefAlign { /// Finds the smallest Integer type which can represent the signed value. pub fn fit_signed(x: i128) -> Integer { + #[cfg_attr(not(stage0), allow(overlapping_patterns))] match x { -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8, -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16, @@ -499,6 +500,7 @@ pub fn fit_signed(x: i128) -> Integer { /// Finds the smallest Integer type which can represent the unsigned value. pub fn fit_unsigned(x: u128) -> Integer { + #[cfg_attr(not(stage0), allow(overlapping_patterns))] match x { 0..=0x0000_0000_0000_00ff => I8, 0..=0x0000_0000_0000_ffff => I16, From d2cb5a8c35cd40909f097bdbbc59fc870f0a8e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 29 Aug 2019 17:41:25 -0700 Subject: [PATCH 458/545] Move lint emitter to its own method --- src/librustc_mir/hair/pattern/_match.rs | 45 +++++++++++++++---------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 1b3c824458e7..48ff7fff5edf 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1739,24 +1739,7 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator { let mut borders: Vec<_> = row_borders.chain(ctor_borders).collect(); borders.sort_unstable(); - if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) { - let mut err = tcx.struct_span_lint_hir( - lint::builtin::OVERLAPPING_PATTERNS, - hir_id, - ctor_range.span, - "multiple patterns covering the same range", - ); - err.span_label(ctor_range.span, "overlapping patterns"); - for int_range in overlaps { - // Use the real type for user display of the ranges: - err.span_label(int_range.span, &format!( - "this range overlaps on `{}`", - IntRange::range_to_ctor(tcx, ty, int_range.range, DUMMY_SP) - .display(tcx), - )); - } - err.emit(); - } + lint_unreachable_patterns(tcx, hir_id, ctor_range, ty, overlaps); // We're going to iterate through every pair of borders, making sure that each // represents an interval of nonnegative length, and convert each such interval @@ -1787,6 +1770,32 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator { split_ctors } +fn lint_unreachable_patterns( + tcx: TyCtxt<'tcx>, + hir_id: Option, + ctor_range: IntRange<'tcx>, + ty: Ty<'tcx>, + overlaps: Vec>, +) { + if let (true, Some(hir_id)) = (!overlaps.is_empty(), hir_id) { + let mut err = tcx.struct_span_lint_hir( + lint::builtin::OVERLAPPING_PATTERNS, + hir_id, + ctor_range.span, + "multiple patterns covering the same range", + ); + err.span_label(ctor_range.span, "overlapping patterns"); + for int_range in overlaps { + // Use the real type for user display of the ranges: + err.span_label(int_range.span, &format!( + "this range overlaps on `{}`", + IntRange::range_to_ctor(tcx, ty, int_range.range, DUMMY_SP).display(tcx), + )); + } + err.emit(); + } +} + fn constructor_covered_by_range<'tcx>( tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, From be9e6af65e5cd4811725c6f29fe99b7bf6e6611d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 29 Aug 2019 17:41:41 -0700 Subject: [PATCH 459/545] review comments: use if let --- src/librustc_mir/hair/pattern/check_match.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index fe57e12bcfcc..d6ec155c9630 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -429,12 +429,9 @@ fn check_arms<'tcx>( hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { - match pat.kind { - box PatternKind::Range(..) => { - // Covered in `is_useful() with more context` - break; - } - _ => {} + if let box PatternKind::Range(..) = pat.kind { + // Covered by `overlapping_patterns` with more context + break; } let mut err = cx.tcx.struct_span_lint_hir( lint::builtin::UNREACHABLE_PATTERNS, From 1ec60730fecfc72eb7454f2b8d37f7de7068cd20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 29 Aug 2019 17:42:45 -0700 Subject: [PATCH 460/545] Deduplicate code for formatting `RangeEnd` --- src/librustc/hir/mod.rs | 9 +++++++++ src/librustc_mir/hair/pattern/_match.rs | 7 ++----- src/librustc_mir/hair/pattern/mod.rs | 5 +---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 7350f89018be..02b391615b62 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -989,6 +989,15 @@ pub enum RangeEnd { Excluded, } +impl fmt::Display for RangeEnd { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + RangeEnd::Included => "..=", + RangeEnd::Excluded => "..", + }) + } +} + #[derive(RustcEncodable, RustcDecodable, Debug, HashStable)] pub enum PatKind { /// Represents a wildcard pattern (i.e., `_`). diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 48ff7fff5edf..636bb2ed6179 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -482,12 +482,9 @@ fn display(&self, tcx: TyCtxt<'tcx>) -> String { // Get the right sign on the output: let ty = ty::ParamEnv::empty().and(*ty); format!( - "{}..{}{}", + "{}{}{}", ty::Const::from_bits(tcx, *lo, ty), - match range_end { - RangeEnd::Included => "=", - RangeEnd::Excluded => "", - }, + range_end, ty::Const::from_bits(tcx, *hi, ty), ) } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 58d741b9295a..7e17162dfb3e 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -312,10 +312,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } PatKind::Range(PatRange { lo, hi, end }) => { write!(f, "{}", lo)?; - match end { - RangeEnd::Included => write!(f, "..=")?, - RangeEnd::Excluded => write!(f, "..")?, - } + write!(f, "{}", end)?; write!(f, "{}", hi) } PatKind::Slice { ref prefix, ref slice, ref suffix } | From 6832da85c2241c9d75d01f1779f54cd9054d7a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 29 Aug 2019 18:00:29 -0700 Subject: [PATCH 461/545] rename method --- src/librustc_mir/hair/pattern/_match.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 636bb2ed6179..04a42d85aff6 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1736,7 +1736,7 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator { let mut borders: Vec<_> = row_borders.chain(ctor_borders).collect(); borders.sort_unstable(); - lint_unreachable_patterns(tcx, hir_id, ctor_range, ty, overlaps); + lint_overlapping_patterns(tcx, hir_id, ctor_range, ty, overlaps); // We're going to iterate through every pair of borders, making sure that each // represents an interval of nonnegative length, and convert each such interval @@ -1767,7 +1767,7 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator { split_ctors } -fn lint_unreachable_patterns( +fn lint_overlapping_patterns( tcx: TyCtxt<'tcx>, hir_id: Option, ctor_range: IntRange<'tcx>, From 89b19ccfdc6117f4df4d8c765464d6d929d483e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 30 Aug 2019 13:37:59 -0700 Subject: [PATCH 462/545] Continue to emit unreachable pattern on cases caught by overlapping patterns --- src/librustc_mir/hair/pattern/check_match.rs | 4 -- src/test/ui/check_match/issue-43253.stderr | 6 +++ src/test/ui/exhaustive_integer_patterns.rs | 4 +- .../ui/exhaustive_integer_patterns.stderr | 26 +++++---- .../ui/match/match-range-fail-dominate.rs | 16 ++++-- .../ui/match/match-range-fail-dominate.stderr | 54 +++++++++++++------ 6 files changed, 76 insertions(+), 34 deletions(-) diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index d6ec155c9630..7bc4bf291ee4 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -429,10 +429,6 @@ fn check_arms<'tcx>( hir::MatchSource::ForLoopDesugar | hir::MatchSource::Normal => { - if let box PatternKind::Range(..) = pat.kind { - // Covered by `overlapping_patterns` with more context - break; - } let mut err = cx.tcx.struct_span_lint_hir( lint::builtin::UNREACHABLE_PATTERNS, hir_pat.hir_id, diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr index 2f6888c0118a..ca4cd8973227 100644 --- a/src/test/ui/check_match/issue-43253.stderr +++ b/src/test/ui/check_match/issue-43253.stderr @@ -32,6 +32,12 @@ LL | 1..10 => {}, LL | 8..=9 => {}, | ^^^^^ overlapping patterns +warning: unreachable pattern + --> $DIR/issue-43253.rs:35:9 + | +LL | 8..=9 => {}, + | ^^^^^ + warning: unreachable pattern --> $DIR/issue-43253.rs:41:9 | diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/exhaustive_integer_patterns.rs index ef88ce94aa6a..a0c1b013f390 100644 --- a/src/test/ui/exhaustive_integer_patterns.rs +++ b/src/test/ui/exhaustive_integer_patterns.rs @@ -41,7 +41,9 @@ fn main() { match x { //~ ERROR non-exhaustive patterns -7 => {} -5..=120 => {} - -2..=20 => {} //~ ERROR multiple patterns covering the same range + -2..=20 => {} + //~^ ERROR unreachable pattern + //~| ERROR multiple patterns covering the same range 125 => {} } diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr index 59cd3fffa8df..44fbc9692257 100644 --- a/src/test/ui/exhaustive_integer_patterns.stderr +++ b/src/test/ui/exhaustive_integer_patterns.stderr @@ -48,6 +48,12 @@ LL | -5..=120 => {} LL | -2..=20 => {} | ^^^^^^^ overlapping patterns +error: unreachable pattern + --> $DIR/exhaustive_integer_patterns.rs:44:9 + | +LL | -2..=20 => {} + | ^^^^^^^ + error[E0004]: non-exhaustive patterns: `std::i8::MIN..=-8i8`, `-6i8`, `121i8..=124i8` and 1 more not covered --> $DIR/exhaustive_integer_patterns.rs:41:11 | @@ -57,7 +63,7 @@ LL | match x { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered - --> $DIR/exhaustive_integer_patterns.rs:82:11 + --> $DIR/exhaustive_integer_patterns.rs:84:11 | LL | match 0i8 { | ^^^ pattern `std::i8::MIN` not covered @@ -65,7 +71,7 @@ LL | match 0i8 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `0i16` not covered - --> $DIR/exhaustive_integer_patterns.rs:90:11 + --> $DIR/exhaustive_integer_patterns.rs:92:11 | LL | match 0i16 { | ^^^^ pattern `0i16` not covered @@ -73,7 +79,7 @@ LL | match 0i16 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered - --> $DIR/exhaustive_integer_patterns.rs:108:11 + --> $DIR/exhaustive_integer_patterns.rs:110:11 | LL | match 0u8 { | ^^^ pattern `128u8..=std::u8::MAX` not covered @@ -81,7 +87,7 @@ LL | match 0u8 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered - --> $DIR/exhaustive_integer_patterns.rs:120:11 + --> $DIR/exhaustive_integer_patterns.rs:122:11 | LL | match (0u8, Some(())) { | ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered @@ -89,7 +95,7 @@ LL | match (0u8, Some(())) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered - --> $DIR/exhaustive_integer_patterns.rs:125:11 + --> $DIR/exhaustive_integer_patterns.rs:127:11 | LL | match (0u8, true) { | ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered @@ -97,7 +103,7 @@ LL | match (0u8, true) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error: multiple patterns covering the same range - --> $DIR/exhaustive_integer_patterns.rs:140:9 + --> $DIR/exhaustive_integer_patterns.rs:142:9 | LL | 0 .. 2 => {} | ------ this range overlaps on `1u8` @@ -105,7 +111,7 @@ LL | 1 ..= 2 => {} | ^^^^^^^ overlapping patterns error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered - --> $DIR/exhaustive_integer_patterns.rs:145:11 + --> $DIR/exhaustive_integer_patterns.rs:147:11 | LL | match 0u128 { | ^^^^^ pattern `std::u128::MAX` not covered @@ -113,7 +119,7 @@ LL | match 0u128 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `5u128..=std::u128::MAX` not covered - --> $DIR/exhaustive_integer_patterns.rs:149:11 + --> $DIR/exhaustive_integer_patterns.rs:151:11 | LL | match 0u128 { | ^^^^^ pattern `5u128..=std::u128::MAX` not covered @@ -121,13 +127,13 @@ LL | match 0u128 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered - --> $DIR/exhaustive_integer_patterns.rs:153:11 + --> $DIR/exhaustive_integer_patterns.rs:155:11 | LL | match 0u128 { | ^^^^^ pattern `0u128..=3u128` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/match/match-range-fail-dominate.rs b/src/test/ui/match/match-range-fail-dominate.rs index bdbb1f050a7a..b6a89b8910c4 100644 --- a/src/test/ui/match/match-range-fail-dominate.rs +++ b/src/test/ui/match/match-range-fail-dominate.rs @@ -3,25 +3,33 @@ fn main() { match 5 { 1 ..= 10 => { } - 5 ..= 6 => { } //~ ERROR multiple patterns covering the same range + 5 ..= 6 => { } + //~^ ERROR unreachable pattern + //~| ERROR multiple patterns covering the same range _ => {} }; match 5 { 3 ..= 6 => { } - 4 ..= 6 => { } //~ ERROR multiple patterns covering the same range + 4 ..= 6 => { } + //~^ ERROR unreachable pattern + //~| ERROR multiple patterns covering the same range _ => {} }; match 5 { 4 ..= 6 => { } - 4 ..= 6 => { } //~ ERROR multiple patterns covering the same range + 4 ..= 6 => { } + //~^ ERROR unreachable pattern + //~| ERROR multiple patterns covering the same range _ => {} }; match 'c' { 'A' ..= 'z' => {} - 'a' ..= 'z' => {} //~ ERROR multiple patterns covering the same range + 'a' ..= 'z' => {} + //~^ ERROR unreachable pattern + //~| ERROR multiple patterns covering the same range _ => {} }; diff --git a/src/test/ui/match/match-range-fail-dominate.stderr b/src/test/ui/match/match-range-fail-dominate.stderr index b14e9b5008d9..4a76e05fab53 100644 --- a/src/test/ui/match/match-range-fail-dominate.stderr +++ b/src/test/ui/match/match-range-fail-dominate.stderr @@ -12,32 +12,62 @@ note: lint level defined here LL | #![deny(unreachable_patterns, overlapping_patterns)] | ^^^^^^^^^^^^^^^^^^^^ +error: unreachable pattern + --> $DIR/match-range-fail-dominate.rs:6:7 + | +LL | 5 ..= 6 => { } + | ^^^^^^^ + | +note: lint level defined here + --> $DIR/match-range-fail-dominate.rs:1:9 + | +LL | #![deny(unreachable_patterns, overlapping_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ + error: multiple patterns covering the same range - --> $DIR/match-range-fail-dominate.rs:12:7 + --> $DIR/match-range-fail-dominate.rs:14:7 | LL | 3 ..= 6 => { } | ------- this range overlaps on `4i32..=6i32` LL | 4 ..= 6 => { } | ^^^^^^^ overlapping patterns +error: unreachable pattern + --> $DIR/match-range-fail-dominate.rs:14:7 + | +LL | 4 ..= 6 => { } + | ^^^^^^^ + error: multiple patterns covering the same range - --> $DIR/match-range-fail-dominate.rs:18:7 + --> $DIR/match-range-fail-dominate.rs:22:7 | LL | 4 ..= 6 => { } | ------- this range overlaps on `4i32..=6i32` LL | 4 ..= 6 => { } | ^^^^^^^ overlapping patterns +error: unreachable pattern + --> $DIR/match-range-fail-dominate.rs:22:7 + | +LL | 4 ..= 6 => { } + | ^^^^^^^ + error: multiple patterns covering the same range - --> $DIR/match-range-fail-dominate.rs:24:7 + --> $DIR/match-range-fail-dominate.rs:30:7 | LL | 'A' ..= 'z' => {} | ----------- this range overlaps on `'a'..='z'` LL | 'a' ..= 'z' => {} | ^^^^^^^^^^^ overlapping patterns +error: unreachable pattern + --> $DIR/match-range-fail-dominate.rs:30:7 + | +LL | 'a' ..= 'z' => {} + | ^^^^^^^^^^^ + warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:29:7 + --> $DIR/match-range-fail-dominate.rs:37:7 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ @@ -47,7 +77,7 @@ LL | 0.01f64 ..= 6.5f64 => {} = note: for more information, see issue #41620 warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:29:19 + --> $DIR/match-range-fail-dominate.rs:37:19 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^ @@ -56,7 +86,7 @@ LL | 0.01f64 ..= 6.5f64 => {} = note: for more information, see issue #41620 warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:36:7 + --> $DIR/match-range-fail-dominate.rs:44:7 | LL | 0.02f64 => {} | ^^^^^^^ @@ -65,19 +95,13 @@ LL | 0.02f64 => {} = note: for more information, see issue #41620 error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:36:7 + --> $DIR/match-range-fail-dominate.rs:44:7 | LL | 0.02f64 => {} | ^^^^^^^ - | -note: lint level defined here - --> $DIR/match-range-fail-dominate.rs:1:9 - | -LL | #![deny(unreachable_patterns, overlapping_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:29:7 + --> $DIR/match-range-fail-dominate.rs:37:7 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ @@ -85,5 +109,5 @@ LL | 0.01f64 ..= 6.5f64 => {} = 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 #41620 -error: aborting due to 5 previous errors +error: aborting due to 9 previous errors From 73d6efc43e0629b2028e7d031306088f44f84782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 6 Oct 2019 21:47:01 -0700 Subject: [PATCH 463/545] Only emit overlapping patterns lint if the overlap is partial --- src/libcore/ascii.rs | 2 - src/librustc_mir/hair/pattern/_match.rs | 35 +++++++++++- src/librustc_target/abi/mod.rs | 2 - src/test/ui/check_match/issue-43253.stderr | 18 ------ src/test/ui/exhaustive_integer_patterns.rs | 1 - .../ui/exhaustive_integer_patterns.stderr | 28 ++++------ src/test/ui/issues/issue-13867.rs | 1 + src/test/ui/issues/issue-21475.rs | 2 +- src/test/ui/issues/issue-26251.rs | 2 + .../ui/match/match-range-fail-dominate.rs | 4 -- .../ui/match/match-range-fail-dominate.stderr | 56 +++---------------- src/test/ui/precise_pointer_size_matching.rs | 2 +- .../ui/precise_pointer_size_matching.stderr | 22 +++----- .../rfc-2005-default-binding-mode/range.rs | 2 +- 14 files changed, 66 insertions(+), 111 deletions(-) diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index 04aefd57ca2e..4087333e2cf6 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -100,8 +100,6 @@ pub fn escape_default(c: u8) -> EscapeDefault { b'\\' => ([b'\\', b'\\', 0, 0], 2), b'\'' => ([b'\\', b'\'', 0, 0], 2), b'"' => ([b'\\', b'"', 0, 0], 2), - // The three arms above are in the following range - #[allow(overlapping_patterns)] b'\x20' ..= b'\x7e' => ([c, 0, 0, 0], 1), _ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4), }; diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 04a42d85aff6..580ded50b05c 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1075,6 +1075,38 @@ fn intersection(&self, other: &Self) -> Option { None } } + + fn suspicious_intersection(&self, other: &Self) -> bool { + let (lo, hi) = (*self.range.start(), *self.range.end()); + let (other_lo, other_hi) = (*other.range.start(), *other.range.end()); + + // `false` in the following cases: + // 1 ---- + // 2 ---------- + // + // 1 ---------- + // 2 ---- + // + // 1 ---- + // 2 ---- + // + // 1 ---- + // 2 ---- + + // `true` in the following cases: + // 1 --------- + // 2 ---------- + lo < other_lo && hi > other_lo && hi < other_hi || + // 1 --------- + // 2 ---------- + lo > other_lo && lo < other_hi && hi > other_hi || + // 1 ---- + // 2 ---- + lo == other_hi && other_lo < lo || + // 1 ---- + // 2 ----- + hi == other_lo && lo < other_lo + } } // A request for missing constructor data in terms of either: @@ -1718,7 +1750,8 @@ fn range_borders(r: IntRange<'_>) -> impl Iterator { }) .flat_map(|(range, row_len)| { let intersection = ctor_range.intersection(&range); - if let (Some(range), 1) = (&intersection, row_len) { + let should_lint = ctor_range.suspicious_intersection(&range); + if let (Some(range), 1, true) = (&intersection, row_len, should_lint) { // FIXME: for now, only check for overlapping ranges on simple range // patterns. Otherwise with the current logic the following is detected // as overlapping: diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 2feee73847df..fde5c5bed4d9 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -488,7 +488,6 @@ pub fn align(self, cx: &C) -> AbiAndPrefAlign { /// Finds the smallest Integer type which can represent the signed value. pub fn fit_signed(x: i128) -> Integer { - #[cfg_attr(not(stage0), allow(overlapping_patterns))] match x { -0x0000_0000_0000_0080..=0x0000_0000_0000_007f => I8, -0x0000_0000_0000_8000..=0x0000_0000_0000_7fff => I16, @@ -500,7 +499,6 @@ pub fn fit_signed(x: i128) -> Integer { /// Finds the smallest Integer type which can represent the unsigned value. pub fn fit_unsigned(x: u128) -> Integer { - #[cfg_attr(not(stage0), allow(overlapping_patterns))] match x { 0..=0x0000_0000_0000_00ff => I8, 0..=0x0000_0000_0000_ffff => I16, diff --git a/src/test/ui/check_match/issue-43253.stderr b/src/test/ui/check_match/issue-43253.stderr index ca4cd8973227..cb4a0486eef9 100644 --- a/src/test/ui/check_match/issue-43253.stderr +++ b/src/test/ui/check_match/issue-43253.stderr @@ -24,14 +24,6 @@ note: lint level defined here LL | #![warn(unreachable_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -warning: multiple patterns covering the same range - --> $DIR/issue-43253.rs:35:9 - | -LL | 1..10 => {}, - | ----- this range overlaps on `8i32..=9i32` -LL | 8..=9 => {}, - | ^^^^^ overlapping patterns - warning: unreachable pattern --> $DIR/issue-43253.rs:35:9 | @@ -44,16 +36,6 @@ warning: unreachable pattern LL | 6 => {}, | ^ -warning: multiple patterns covering the same range - --> $DIR/issue-43253.rs:42:9 - | -LL | 5..7 => {}, - | ---- this range overlaps on `5i32..=6i32` -LL | 6 => {}, - | - this range overlaps on `6i32` -LL | 1..10 => {}, - | ^^^^^ overlapping patterns - warning: unreachable pattern --> $DIR/issue-43253.rs:43:9 | diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/exhaustive_integer_patterns.rs index a0c1b013f390..442b2f772572 100644 --- a/src/test/ui/exhaustive_integer_patterns.rs +++ b/src/test/ui/exhaustive_integer_patterns.rs @@ -43,7 +43,6 @@ fn main() { -5..=120 => {} -2..=20 => {} //~^ ERROR unreachable pattern - //~| ERROR multiple patterns covering the same range 125 => {} } diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr index 44fbc9692257..4c5806f9606f 100644 --- a/src/test/ui/exhaustive_integer_patterns.stderr +++ b/src/test/ui/exhaustive_integer_patterns.stderr @@ -40,14 +40,6 @@ LL | match x { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: multiple patterns covering the same range - --> $DIR/exhaustive_integer_patterns.rs:44:9 - | -LL | -5..=120 => {} - | -------- this range overlaps on `-2i8..=20i8` -LL | -2..=20 => {} - | ^^^^^^^ overlapping patterns - error: unreachable pattern --> $DIR/exhaustive_integer_patterns.rs:44:9 | @@ -63,7 +55,7 @@ LL | match x { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `std::i8::MIN` not covered - --> $DIR/exhaustive_integer_patterns.rs:84:11 + --> $DIR/exhaustive_integer_patterns.rs:83:11 | LL | match 0i8 { | ^^^ pattern `std::i8::MIN` not covered @@ -71,7 +63,7 @@ LL | match 0i8 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `0i16` not covered - --> $DIR/exhaustive_integer_patterns.rs:92:11 + --> $DIR/exhaustive_integer_patterns.rs:91:11 | LL | match 0i16 { | ^^^^ pattern `0i16` not covered @@ -79,7 +71,7 @@ LL | match 0i16 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `128u8..=std::u8::MAX` not covered - --> $DIR/exhaustive_integer_patterns.rs:110:11 + --> $DIR/exhaustive_integer_patterns.rs:109:11 | LL | match 0u8 { | ^^^ pattern `128u8..=std::u8::MAX` not covered @@ -87,7 +79,7 @@ LL | match 0u8 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered - --> $DIR/exhaustive_integer_patterns.rs:122:11 + --> $DIR/exhaustive_integer_patterns.rs:121:11 | LL | match (0u8, Some(())) { | ^^^^^^^^^^^^^^^ patterns `(0u8, Some(_))` and `(2u8..=std::u8::MAX, Some(_))` not covered @@ -95,7 +87,7 @@ LL | match (0u8, Some(())) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `(126u8..=127u8, false)` not covered - --> $DIR/exhaustive_integer_patterns.rs:127:11 + --> $DIR/exhaustive_integer_patterns.rs:126:11 | LL | match (0u8, true) { | ^^^^^^^^^^^ pattern `(126u8..=127u8, false)` not covered @@ -103,7 +95,7 @@ LL | match (0u8, true) { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error: multiple patterns covering the same range - --> $DIR/exhaustive_integer_patterns.rs:142:9 + --> $DIR/exhaustive_integer_patterns.rs:141:9 | LL | 0 .. 2 => {} | ------ this range overlaps on `1u8` @@ -111,7 +103,7 @@ LL | 1 ..= 2 => {} | ^^^^^^^ overlapping patterns error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered - --> $DIR/exhaustive_integer_patterns.rs:147:11 + --> $DIR/exhaustive_integer_patterns.rs:146:11 | LL | match 0u128 { | ^^^^^ pattern `std::u128::MAX` not covered @@ -119,7 +111,7 @@ LL | match 0u128 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `5u128..=std::u128::MAX` not covered - --> $DIR/exhaustive_integer_patterns.rs:151:11 + --> $DIR/exhaustive_integer_patterns.rs:150:11 | LL | match 0u128 { | ^^^^^ pattern `5u128..=std::u128::MAX` not covered @@ -127,13 +119,13 @@ LL | match 0u128 { = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms error[E0004]: non-exhaustive patterns: `0u128..=3u128` not covered - --> $DIR/exhaustive_integer_patterns.rs:155:11 + --> $DIR/exhaustive_integer_patterns.rs:154:11 | LL | match 0u128 { | ^^^^^ pattern `0u128..=3u128` not covered | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to 16 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/issues/issue-13867.rs b/src/test/ui/issues/issue-13867.rs index e66368f9ba8f..809205685634 100644 --- a/src/test/ui/issues/issue-13867.rs +++ b/src/test/ui/issues/issue-13867.rs @@ -1,6 +1,7 @@ // run-pass // Test that codegen works correctly when there are multiple refutable // patterns in match expression. +#![allow(overlapping_patterns)] enum Foo { diff --git a/src/test/ui/issues/issue-21475.rs b/src/test/ui/issues/issue-21475.rs index 16d003aba7ca..ab0a18869632 100644 --- a/src/test/ui/issues/issue-21475.rs +++ b/src/test/ui/issues/issue-21475.rs @@ -1,5 +1,5 @@ // run-pass -#![allow(unused_imports)] +#![allow(unused_imports, overlapping_patterns)] // pretty-expanded FIXME #23616 use m::{START, END}; diff --git a/src/test/ui/issues/issue-26251.rs b/src/test/ui/issues/issue-26251.rs index 0434ef9e5a95..edb06fea8ad5 100644 --- a/src/test/ui/issues/issue-26251.rs +++ b/src/test/ui/issues/issue-26251.rs @@ -1,4 +1,6 @@ // run-pass +#![allow(overlapping_patterns)] + fn main() { let x = 'a'; diff --git a/src/test/ui/match/match-range-fail-dominate.rs b/src/test/ui/match/match-range-fail-dominate.rs index b6a89b8910c4..7de7b7e79be4 100644 --- a/src/test/ui/match/match-range-fail-dominate.rs +++ b/src/test/ui/match/match-range-fail-dominate.rs @@ -5,7 +5,6 @@ fn main() { 1 ..= 10 => { } 5 ..= 6 => { } //~^ ERROR unreachable pattern - //~| ERROR multiple patterns covering the same range _ => {} }; @@ -13,7 +12,6 @@ fn main() { 3 ..= 6 => { } 4 ..= 6 => { } //~^ ERROR unreachable pattern - //~| ERROR multiple patterns covering the same range _ => {} }; @@ -21,7 +19,6 @@ fn main() { 4 ..= 6 => { } 4 ..= 6 => { } //~^ ERROR unreachable pattern - //~| ERROR multiple patterns covering the same range _ => {} }; @@ -29,7 +26,6 @@ fn main() { 'A' ..= 'z' => {} 'a' ..= 'z' => {} //~^ ERROR unreachable pattern - //~| ERROR multiple patterns covering the same range _ => {} }; diff --git a/src/test/ui/match/match-range-fail-dominate.stderr b/src/test/ui/match/match-range-fail-dominate.stderr index 4a76e05fab53..c15186d2558f 100644 --- a/src/test/ui/match/match-range-fail-dominate.stderr +++ b/src/test/ui/match/match-range-fail-dominate.stderr @@ -1,17 +1,3 @@ -error: multiple patterns covering the same range - --> $DIR/match-range-fail-dominate.rs:6:7 - | -LL | 1 ..= 10 => { } - | -------- this range overlaps on `5i32..=6i32` -LL | 5 ..= 6 => { } - | ^^^^^^^ overlapping patterns - | -note: lint level defined here - --> $DIR/match-range-fail-dominate.rs:1:31 - | -LL | #![deny(unreachable_patterns, overlapping_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - error: unreachable pattern --> $DIR/match-range-fail-dominate.rs:6:7 | @@ -24,50 +10,26 @@ note: lint level defined here LL | #![deny(unreachable_patterns, overlapping_patterns)] | ^^^^^^^^^^^^^^^^^^^^ -error: multiple patterns covering the same range - --> $DIR/match-range-fail-dominate.rs:14:7 - | -LL | 3 ..= 6 => { } - | ------- this range overlaps on `4i32..=6i32` -LL | 4 ..= 6 => { } - | ^^^^^^^ overlapping patterns - error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:14:7 + --> $DIR/match-range-fail-dominate.rs:13:7 | LL | 4 ..= 6 => { } | ^^^^^^^ -error: multiple patterns covering the same range - --> $DIR/match-range-fail-dominate.rs:22:7 - | -LL | 4 ..= 6 => { } - | ------- this range overlaps on `4i32..=6i32` -LL | 4 ..= 6 => { } - | ^^^^^^^ overlapping patterns - error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:22:7 + --> $DIR/match-range-fail-dominate.rs:20:7 | LL | 4 ..= 6 => { } | ^^^^^^^ -error: multiple patterns covering the same range - --> $DIR/match-range-fail-dominate.rs:30:7 - | -LL | 'A' ..= 'z' => {} - | ----------- this range overlaps on `'a'..='z'` -LL | 'a' ..= 'z' => {} - | ^^^^^^^^^^^ overlapping patterns - error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:30:7 + --> $DIR/match-range-fail-dominate.rs:27:7 | LL | 'a' ..= 'z' => {} | ^^^^^^^^^^^ warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:37:7 + --> $DIR/match-range-fail-dominate.rs:33:7 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ @@ -77,7 +39,7 @@ LL | 0.01f64 ..= 6.5f64 => {} = note: for more information, see issue #41620 warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:37:19 + --> $DIR/match-range-fail-dominate.rs:33:19 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^ @@ -86,7 +48,7 @@ LL | 0.01f64 ..= 6.5f64 => {} = note: for more information, see issue #41620 warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:44:7 + --> $DIR/match-range-fail-dominate.rs:40:7 | LL | 0.02f64 => {} | ^^^^^^^ @@ -95,13 +57,13 @@ LL | 0.02f64 => {} = note: for more information, see issue #41620 error: unreachable pattern - --> $DIR/match-range-fail-dominate.rs:44:7 + --> $DIR/match-range-fail-dominate.rs:40:7 | LL | 0.02f64 => {} | ^^^^^^^ warning: floating-point types cannot be used in patterns - --> $DIR/match-range-fail-dominate.rs:37:7 + --> $DIR/match-range-fail-dominate.rs:33:7 | LL | 0.01f64 ..= 6.5f64 => {} | ^^^^^^^ @@ -109,5 +71,5 @@ LL | 0.01f64 ..= 6.5f64 => {} = 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 #41620 -error: aborting due to 9 previous errors +error: aborting due to 5 previous errors diff --git a/src/test/ui/precise_pointer_size_matching.rs b/src/test/ui/precise_pointer_size_matching.rs index be2a140ddc3d..ee91088c0c36 100644 --- a/src/test/ui/precise_pointer_size_matching.rs +++ b/src/test/ui/precise_pointer_size_matching.rs @@ -23,7 +23,7 @@ fn main() { match 0isize { //~ ERROR non-exhaustive patterns 1 ..= 8 => {} - -5 ..= 20 => {} //~ ERROR multiple patterns covering the same range + -5 ..= 20 => {} } match 0usize { //~ ERROR non-exhaustive patterns diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr index 4930047fc1e9..98d347e06b60 100644 --- a/src/test/ui/precise_pointer_size_matching.stderr +++ b/src/test/ui/precise_pointer_size_matching.stderr @@ -1,17 +1,3 @@ -error: multiple patterns covering the same range - --> $DIR/precise_pointer_size_matching.rs:26:9 - | -LL | 1 ..= 8 => {} - | ------- this range overlaps on `1isize..=8isize` -LL | -5 ..= 20 => {} - | ^^^^^^^^^ overlapping patterns - | -note: lint level defined here - --> $DIR/precise_pointer_size_matching.rs:11:31 - | -LL | #![deny(unreachable_patterns, overlapping_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - error[E0004]: non-exhaustive patterns: `std::isize::MIN..=-6isize` and `21isize..=std::isize::MAX` not covered --> $DIR/precise_pointer_size_matching.rs:24:11 | @@ -27,6 +13,12 @@ LL | 1 ..= 8 => {} | ------- this range overlaps on `5usize..=8usize` LL | 5 ..= 20 => {} | ^^^^^^^^ overlapping patterns + | +note: lint level defined here + --> $DIR/precise_pointer_size_matching.rs:11:31 + | +LL | #![deny(unreachable_patterns, overlapping_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `0usize` and `21usize..=std::usize::MAX` not covered --> $DIR/precise_pointer_size_matching.rs:29:11 @@ -36,6 +28,6 @@ LL | match 0usize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/rfcs/rfc-2005-default-binding-mode/range.rs b/src/test/ui/rfcs/rfc-2005-default-binding-mode/range.rs index 580e67513b39..f8abd1b96d80 100644 --- a/src/test/ui/rfcs/rfc-2005-default-binding-mode/range.rs +++ b/src/test/ui/rfcs/rfc-2005-default-binding-mode/range.rs @@ -3,7 +3,7 @@ pub fn main() { let i = 5; match &&&&i { 1 ..= 3 => panic!(), - 3 ..= 8 => {}, + 4 ..= 8 => {}, _ => panic!(), } } From 593cdcccf28361df155c37916dcfcbe1bf19d9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 16 Oct 2019 12:22:23 -0700 Subject: [PATCH 464/545] Lint only on single element overlap --- src/librustc_mir/hair/pattern/_match.rs | 39 ++++++------------- src/test/ui/exhaustive_integer_patterns.rs | 2 +- .../ui/exhaustive_integer_patterns.stderr | 22 ++++------- src/test/ui/issues/issue-13867.rs | 2 - src/test/ui/precise_pointer_size_matching.rs | 2 +- .../ui/precise_pointer_size_matching.stderr | 16 +------- 6 files changed, 22 insertions(+), 61 deletions(-) diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 580ded50b05c..1d83b104177e 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -1077,35 +1077,20 @@ fn intersection(&self, other: &Self) -> Option { } fn suspicious_intersection(&self, other: &Self) -> bool { + // `false` in the following cases: + // 1 ---- // 1 ---------- // 1 ---- // 1 ---- + // 2 ---------- // 2 ---- // 2 ---- // 2 ---- + // + // The following are currently `false`, but could be `true` in the future (#64007): + // 1 --------- // 1 --------- + // 2 ---------- // 2 ---------- + // + // `true` in the following cases: + // 1 ------- // 1 ------- + // 2 -------- // 2 ------- let (lo, hi) = (*self.range.start(), *self.range.end()); let (other_lo, other_hi) = (*other.range.start(), *other.range.end()); - - // `false` in the following cases: - // 1 ---- - // 2 ---------- - // - // 1 ---------- - // 2 ---- - // - // 1 ---- - // 2 ---- - // - // 1 ---- - // 2 ---- - - // `true` in the following cases: - // 1 --------- - // 2 ---------- - lo < other_lo && hi > other_lo && hi < other_hi || - // 1 --------- - // 2 ---------- - lo > other_lo && lo < other_hi && hi > other_hi || - // 1 ---- - // 2 ---- - lo == other_hi && other_lo < lo || - // 1 ---- - // 2 ----- - hi == other_lo && lo < other_lo + (lo == other_hi || hi == other_lo) } } diff --git a/src/test/ui/exhaustive_integer_patterns.rs b/src/test/ui/exhaustive_integer_patterns.rs index 442b2f772572..59f749198971 100644 --- a/src/test/ui/exhaustive_integer_patterns.rs +++ b/src/test/ui/exhaustive_integer_patterns.rs @@ -19,7 +19,7 @@ fn main() { 0 ..= 32 => {} 33 => {} 34 .. 128 => {} - 100 ..= 200 => {} //~ ERROR multiple patterns covering the same range + 100 ..= 200 => {} 200 => {} //~ ERROR unreachable pattern 201 ..= 255 => {} } diff --git a/src/test/ui/exhaustive_integer_patterns.stderr b/src/test/ui/exhaustive_integer_patterns.stderr index 4c5806f9606f..7a3a36a820c6 100644 --- a/src/test/ui/exhaustive_integer_patterns.stderr +++ b/src/test/ui/exhaustive_integer_patterns.stderr @@ -1,17 +1,3 @@ -error: multiple patterns covering the same range - --> $DIR/exhaustive_integer_patterns.rs:22:9 - | -LL | 34 .. 128 => {} - | --------- this range overlaps on `100u8..=127u8` -LL | 100 ..= 200 => {} - | ^^^^^^^^^^^ overlapping patterns - | -note: lint level defined here - --> $DIR/exhaustive_integer_patterns.rs:4:9 - | -LL | #![deny(overlapping_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - error: unreachable pattern --> $DIR/exhaustive_integer_patterns.rs:23:9 | @@ -101,6 +87,12 @@ LL | 0 .. 2 => {} | ------ this range overlaps on `1u8` LL | 1 ..= 2 => {} | ^^^^^^^ overlapping patterns + | +note: lint level defined here + --> $DIR/exhaustive_integer_patterns.rs:4:9 + | +LL | #![deny(overlapping_patterns)] + | ^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `std::u128::MAX` not covered --> $DIR/exhaustive_integer_patterns.rs:146:11 @@ -126,6 +118,6 @@ LL | match 0u128 { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to 15 previous errors +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0004`. diff --git a/src/test/ui/issues/issue-13867.rs b/src/test/ui/issues/issue-13867.rs index 809205685634..9510aae77534 100644 --- a/src/test/ui/issues/issue-13867.rs +++ b/src/test/ui/issues/issue-13867.rs @@ -1,8 +1,6 @@ // run-pass // Test that codegen works correctly when there are multiple refutable // patterns in match expression. -#![allow(overlapping_patterns)] - enum Foo { FooUint(usize), diff --git a/src/test/ui/precise_pointer_size_matching.rs b/src/test/ui/precise_pointer_size_matching.rs index ee91088c0c36..54aeb8616d95 100644 --- a/src/test/ui/precise_pointer_size_matching.rs +++ b/src/test/ui/precise_pointer_size_matching.rs @@ -28,6 +28,6 @@ fn main() { match 0usize { //~ ERROR non-exhaustive patterns 1 ..= 8 => {} - 5 ..= 20 => {} //~ ERROR multiple patterns covering the same range + 5 ..= 20 => {} } } diff --git a/src/test/ui/precise_pointer_size_matching.stderr b/src/test/ui/precise_pointer_size_matching.stderr index 98d347e06b60..2c2c2aa04c23 100644 --- a/src/test/ui/precise_pointer_size_matching.stderr +++ b/src/test/ui/precise_pointer_size_matching.stderr @@ -6,20 +6,6 @@ LL | match 0isize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: multiple patterns covering the same range - --> $DIR/precise_pointer_size_matching.rs:31:9 - | -LL | 1 ..= 8 => {} - | ------- this range overlaps on `5usize..=8usize` -LL | 5 ..= 20 => {} - | ^^^^^^^^ overlapping patterns - | -note: lint level defined here - --> $DIR/precise_pointer_size_matching.rs:11:31 - | -LL | #![deny(unreachable_patterns, overlapping_patterns)] - | ^^^^^^^^^^^^^^^^^^^^ - error[E0004]: non-exhaustive patterns: `0usize` and `21usize..=std::usize::MAX` not covered --> $DIR/precise_pointer_size_matching.rs:29:11 | @@ -28,6 +14,6 @@ LL | match 0usize { | = help: ensure that all possible cases are being handled, possibly by adding wildcards or more match arms -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0004`. From 70b136d532460d2e35456d303726be736a3adb3d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 15 Oct 2019 15:16:51 +1100 Subject: [PATCH 465/545] Use a `BitSet` in `LexicalResolver::iterate_until_fixed_point()`. This wins 3% on `unicode_normalization`. --- .../infer/lexical_region_resolve/mod.rs | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index 6f55ade1e861..a8d1b2647606 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -19,8 +19,8 @@ use rustc_data_structures::graph::implementation::{ Direction, Graph, NodeIndex, INCOMING, OUTGOING, }; +use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; -use smallvec::SmallVec; use std::fmt; use syntax_pos::Span; @@ -870,21 +870,34 @@ fn iterate_until_fixed_point(&self, mut body: F) where F: FnMut(&Constraint<'tcx>) -> (bool, bool), { - let mut constraints: SmallVec<[_; 16]> = self.data.constraints.keys().collect(); + // Using bitsets to track the remaining elements is faster than using a + // `Vec` by itself (which requires removing elements, which requires + // element shuffling, which is slow). + let constraints: Vec<_> = self.data.constraints.keys().collect(); + let mut live_indices: BitSet = BitSet::new_filled(constraints.len()); + let mut killed_indices: BitSet = BitSet::new_empty(constraints.len()); let mut iteration = 0; let mut changed = true; while changed { changed = false; iteration += 1; debug!("---- Expansion iteration {}", iteration); - constraints.retain(|constraint| { + for index in live_indices.iter() { + let constraint = constraints[index]; let (edge_changed, retain) = body(constraint); if edge_changed { debug!("updated due to constraint {:?}", constraint); changed = true; } - retain - }); + if !retain { + let changed = killed_indices.insert(index); + debug_assert!(changed); + } + } + live_indices.subtract(&killed_indices); + + // We could clear `killed_indices` here, but we don't need to and + // it's cheaper not to. } debug!("---- Expansion complete after {} iteration(s)", iteration); } From 8ca16ddfd4d92b4aca970478eeffa4d1e5fe30be Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 16 Oct 2019 19:22:56 +0200 Subject: [PATCH 466/545] panictry!(..) -> .unwrap() --- src/libsyntax/tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/tests.rs b/src/libsyntax/tests.rs index fbcf368ccb7b..881bdaa84d09 100644 --- a/src/libsyntax/tests.rs +++ b/src/libsyntax/tests.rs @@ -1,4 +1,4 @@ -use crate::{ast, panictry}; +use crate::ast; use crate::parse::{PResult, source_file_to_stream}; use crate::parse::new_parser_from_source_str; use crate::parse::parser::Parser; @@ -28,7 +28,7 @@ fn string_to_parser(ps: &ParseSess, source_str: String) -> Parser<'_> { F: FnOnce(&mut Parser<'a>) -> PResult<'a, T>, { let mut p = string_to_parser(&ps, s); - let x = panictry!(f(&mut p)); + let x = f(&mut p).unwrap(); p.sess.span_diagnostic.abort_if_errors(); x } From e490aaea7ee448d3eaacca291257735dfcf37c1d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 16 Oct 2019 23:24:38 +0200 Subject: [PATCH 467/545] fmt::Write is about string slices, not byte slices --- src/libcore/fmt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 5dfdd1623061..8413b2e0ac49 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -108,10 +108,10 @@ pub mod rt { /// [`io::Write`]: ../../std/io/trait.Write.html #[stable(feature = "rust1", since = "1.0.0")] pub trait Write { - /// Writes a slice of bytes into this writer, returning whether the write + /// Writes a string slice into this writer, returning whether the write /// succeeded. /// - /// This method can only succeed if the entire byte slice was successfully + /// This method can only succeed if the entire string slice was successfully /// written, and this method will not return until all data has been /// written or an error occurs. /// From d51fee092c76016f973a4a73e52a14e44c92b1c7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 17 Oct 2019 09:30:25 +1100 Subject: [PATCH 468/545] Inline and remove `iterate_until_fixed_point()`. The commit also removes the debug statement, because they annoyed me. This change wins another 1% on `unicode_normalization`, at least partly because it no longer needs to increment `iteration`. --- .../infer/lexical_region_resolve/mod.rs | 67 ++++++++----------- 1 file changed, 28 insertions(+), 39 deletions(-) diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index a8d1b2647606..f30f19d41509 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -304,8 +304,7 @@ fn enforce_member_constraint( } fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) { - self.iterate_until_fixed_point(|constraint| { - debug!("expansion: constraint={:?}", constraint); + let mut process_constraint = |constraint: &Constraint<'tcx>| { let (a_region, b_vid, b_data, retain) = match *constraint { Constraint::RegSubVar(a_region, b_vid) => { let b_data = var_values.value_mut(b_vid); @@ -331,7 +330,33 @@ fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) { let changed = self.expand_node(a_region, b_vid, b_data); (changed, retain) - }) + }; + + // Using bitsets to track the remaining elements is faster than using a + // `Vec` by itself (which requires removing elements, which requires + // element shuffling, which is slow). + let constraints: Vec<_> = self.data.constraints.keys().collect(); + let mut live_indices: BitSet = BitSet::new_filled(constraints.len()); + let mut killed_indices: BitSet = BitSet::new_empty(constraints.len()); + let mut changed = true; + while changed { + changed = false; + for index in live_indices.iter() { + let constraint = constraints[index]; + let (edge_changed, retain) = process_constraint(constraint); + if edge_changed { + changed = true; + } + if !retain { + let changed = killed_indices.insert(index); + debug_assert!(changed); + } + } + live_indices.subtract(&killed_indices); + + // We could clear `killed_indices` here, but we don't need to and + // it's cheaper not to. + } } // This function is very hot in some workloads. There's a single callsite @@ -866,42 +891,6 @@ fn process_edges<'tcx>( } } - fn iterate_until_fixed_point(&self, mut body: F) - where - F: FnMut(&Constraint<'tcx>) -> (bool, bool), - { - // Using bitsets to track the remaining elements is faster than using a - // `Vec` by itself (which requires removing elements, which requires - // element shuffling, which is slow). - let constraints: Vec<_> = self.data.constraints.keys().collect(); - let mut live_indices: BitSet = BitSet::new_filled(constraints.len()); - let mut killed_indices: BitSet = BitSet::new_empty(constraints.len()); - let mut iteration = 0; - let mut changed = true; - while changed { - changed = false; - iteration += 1; - debug!("---- Expansion iteration {}", iteration); - for index in live_indices.iter() { - let constraint = constraints[index]; - let (edge_changed, retain) = body(constraint); - if edge_changed { - debug!("updated due to constraint {:?}", constraint); - changed = true; - } - if !retain { - let changed = killed_indices.insert(index); - debug_assert!(changed); - } - } - live_indices.subtract(&killed_indices); - - // We could clear `killed_indices` here, but we don't need to and - // it's cheaper not to. - } - debug!("---- Expansion complete after {} iteration(s)", iteration); - } - fn bound_is_met( &self, bound: &VerifyBound<'tcx>, From 2bf59bea481dd4b4365cafe2e94fa8bf330a6877 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 16 Aug 2019 22:08:01 -0700 Subject: [PATCH 469/545] Upgrade Emscripten targets to use upstream LLVM backend - Compatible with Emscripten 1.38.46-upstream or later upstream. - Refactors the Emscripten target spec to share code with other wasm targets. - Replaces the old incorrect wasm32 C call ABI with the correct one, preserving the old one as wasm32_bindgen_compat for wasm-bindgen compatibility. - Updates the varargs ABI used by Emscripten and deletes the old one. - Removes the obsolete wasm32-experimental-emscripten target. - Uses EMCC_CFLAGS on CI to avoid the timeout problems with #63649. --- config.toml.example | 1 + src/bootstrap/builder.rs | 1 + src/bootstrap/test.rs | 5 +- src/ci/docker/asmjs/Dockerfile | 32 ++-- src/ci/docker/disabled/wasm32-exp/Dockerfile | 35 ---- src/ci/docker/disabled/wasm32-exp/node.sh | 9 - src/ci/docker/disabled/wasm32/Dockerfile | 23 ++- 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/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 | 15 +- src/test/codegen/c-variadic.rs | 1 + src/test/codegen/drop.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/codegen/unwind-extern-exports.rs | 1 + src/test/codegen/unwind-extern-imports.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 +- .../async-fn-size-uninit-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 +- .../feature-gate-unwind-attributes.rs | 1 + 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 +- .../never_type/panic-uninitialized-zeroed.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/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 +- 144 files changed, 378 insertions(+), 538 deletions(-) delete mode 100644 src/ci/docker/disabled/wasm32-exp/Dockerfile delete mode 100755 src/ci/docker/disabled/wasm32-exp/node.sh delete mode 100644 src/ci/docker/scripts/emscripten-wasm.sh delete mode 100644 src/librustc_target/abi/call/asmjs.rs create mode 100644 src/librustc_target/abi/call/wasm32_bindgen_compat.rs delete mode 100644 src/librustc_target/spec/wasm32_experimental_emscripten.rs diff --git a/config.toml.example b/config.toml.example index 848147c2974c..2e3b714f9228 100644 --- a/config.toml.example +++ b/config.toml.example @@ -377,6 +377,7 @@ # 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 0caf2d9b6db5..b8071b98f707 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -980,6 +980,7 @@ pub fn cargo( 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 b7ce9c7b3970..e09e25de64a3 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1047,10 +1047,11 @@ fn run(self, builder: &Builder<'_>) { // Also provide `rust_test_helpers` for the host. builder.ensure(native::TestHelpers { target: compiler.host }); - // wasm32 can't build the test helpers - if !target.contains("wasm32") { + // As well as the target, except for plain wasm32, which can't build it + if !target.contains("wasm32") || target.contains("emscripten") { 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 3abaab6b34ef..75db374907d7 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -11,7 +11,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - xz-utils + xz-utils \ + bzip2 COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh @@ -20,28 +21,21 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV PATH=$PATH:/emsdk-portable -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 PATH=$PATH:/emsdk-portable/upstream/emscripten/ +ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/ +ENV BINARYEN_ROOT=/emsdk-portable/upstream/ ENV EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=asmjs-unknown-emscripten -ENV RUST_CONFIGURE_ARGS --enable-emscripten --disable-optimize-tests +# Use -O1 optimizations in the link step to reduce time spent optimizing JS. +# FIXME: Switch to testing wasm32-unknown-emscripten and -O1 to save more time +# once the CI picks up https://github.com/rust-lang/cargo/pull/7476. +ENV EMCC_CFLAGS=-O1 -ENV SCRIPT python2.7 ../x.py test --target $TARGETS \ - src/test/ui \ - src/test/run-fail \ - src/libstd \ - src/liballoc \ - src/libcore +ENV SCRIPT python2.7 ../x.py test --target $TARGETS -# 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 +# This is almost identical to the wasm32-unknown-emscripten target, so +# running with assertions again is not useful ENV NO_DEBUG_ASSERTIONS=1 +ENV NO_LLVM_ASSERTIONS=1 diff --git a/src/ci/docker/disabled/wasm32-exp/Dockerfile b/src/ci/docker/disabled/wasm32-exp/Dockerfile deleted file mode 100644 index 420d47b314c0..000000000000 --- a/src/ci/docker/disabled/wasm32-exp/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -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 deleted file mode 100755 index aa938971c702..000000000000 --- a/src/ci/docker/disabled/wasm32-exp/node.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/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 0d2bd39303ef..aeccbb9bdc03 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 + xz-utils \ + bzip2 -# emscripten COPY scripts/emscripten.sh /scripts/ RUN bash /scripts/emscripten.sh @@ -21,12 +21,19 @@ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh ENV PATH=$PATH:/emsdk-portable -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 PATH=$PATH:/emsdk-portable/upstream/emscripten/ +ENV PATH=$PATH:/emsdk-portable/node/12.9.1_64bit/bin/ +ENV BINARYEN_ROOT=/emsdk-portable/upstream/ ENV EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=wasm32-unknown-emscripten -ENV SCRIPT python2.7 ../x.py test --target $TARGETS + +# FIXME: Re-enable these tests once https://github.com/rust-lang/cargo/pull/7476 +# is picked up by CI +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 diff --git a/src/ci/docker/scripts/emscripten-wasm.sh b/src/ci/docker/scripts/emscripten-wasm.sh deleted file mode 100644 index e4a93d7a1009..000000000000 --- a/src/ci/docker/scripts/emscripten-wasm.sh +++ /dev/null @@ -1,37 +0,0 @@ -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 47196e893962..9c7a09e227a4 100644 --- a/src/ci/docker/scripts/emscripten.sh +++ b/src/ci/docker/scripts/emscripten.sh @@ -17,20 +17,15 @@ exit 1 set -x } -cd / -curl -fL https://mozilla-games.s3.amazonaws.com/emscripten/releases/emsdk-portable.tar.gz | \ - tar -xz - +git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable cd /emsdk-portable -./emsdk update -hide_output ./emsdk install sdk-1.38.15-64bit -./emsdk activate sdk-1.38.15-64bit +hide_output ./emsdk install 1.38.46-upstream +./emsdk activate 1.38.46-upstream # 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 0685fa943c0b..b8c720264d0a 100644 --- a/src/liballoc/tests/binary_heap.rs +++ b/src/liballoc/tests/binary_heap.rs @@ -1,10 +1,5 @@ -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() { @@ -281,9 +276,15 @@ fn drain<'new>(d: Drain<'static, &'static str>) -> Drain<'new, &'new str> { // 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(miri))] // Miri does not support catching panics +#[cfg(not(any(miri, target_os = "emscripten")))] // 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 4332b2e90fda..cb73c7c179cb 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -483,7 +483,7 @@ fn simple_unicode() { } #[test] - #[cfg(not(target_arch = "asmjs"))] // hits an OOM + #[cfg(not(target_os = "emscripten"))] // 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 98d013dfa2b5..80537217697a 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -944,8 +944,10 @@ fn drain_filter_complex() { } } +// Miri does not support catching panics +// FIXME: re-enable emscripten once it can unwind again #[test] -#[cfg(not(miri))] // Miri does not support catching panics +#[cfg(not(any(miri, target_os = "emscripten")))] fn drain_filter_consumed_panic() { use std::rc::Rc; use std::sync::Mutex; @@ -995,8 +997,9 @@ fn drop(&mut self) { } } +// FIXME: Re-enable emscripten once it can catch panics #[test] -#[cfg(not(miri))] // Miri does not support catching panics +#[cfg(not(any(miri, target_os = "emscripten")))] // 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 eda0e7c518c5..0ea4187ccd48 100644 --- a/src/libcore/ffi.rs +++ b/src/libcore/ffi.rs @@ -49,8 +49,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// 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 = "asmjs")), + not(target_arch = "x86_64")), all(target_arch = "aarch64", target_os = "ios"), + target_arch = "wasm32", + target_arch = "asmjs", windows))] #[repr(transparent)] #[unstable(feature = "c_variadic", @@ -67,8 +69,10 @@ pub struct VaListImpl<'f> { } #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), - not(target_arch = "x86_64"), not(target_arch = "asmjs")), + not(target_arch = "x86_64")), 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 \ @@ -137,38 +141,6 @@ 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)] @@ -178,14 +150,18 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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 = "asmjs")), + not(target_arch = "x86_64")), 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 = "asmjs"), + target_arch = "x86_64"), any(not(target_arch = "aarch64"), not(target_os = "ios")), + not(target_arch = "wasm32"), + not(target_arch = "asmjs"), not(windows)))] inner: &'a mut VaListImpl<'f>, @@ -193,8 +169,10 @@ 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 = "asmjs")), + not(target_arch = "x86_64")), 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 \ @@ -212,8 +190,10 @@ pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> { } #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", - target_arch = "x86_64", target_arch = "asmjs"), + target_arch = "x86_64"), 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 ee4be6c91511..368a2f16b281 100644 --- a/src/libcore/hint.rs +++ b/src/libcore/hint.rs @@ -114,24 +114,8 @@ 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 541d3d98b79b..2dce9b04c9e9 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -257,8 +257,7 @@ pub fn target_feature_whitelist(sess: &Session) "hexagon" => HEXAGON_WHITELIST, "mips" | "mips64" => MIPS_WHITELIST, "powerpc" | "powerpc64" => POWERPC_WHITELIST, - // wasm32 on emscripten does not support these target features - "wasm32" if !sess.target.target.options.is_like_emscripten => WASM_WHITELIST, + "wasm32" => WASM_WHITELIST, _ => &[], } } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 5339134a2a84..0ef1844b5ace 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -143,15 +143,12 @@ fn set_flags(&mut self, sess: &Session, no_builtins: bool) { // 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.target.target.options.is_like_emscripten; + sess.opts.optimize == config::OptLevel::Aggressive); self.vectorize_slp = !sess.opts.cg.no_vectorize_slp && - sess.opts.optimize == config::OptLevel::Aggressive && - !sess.target.target.options.is_like_emscripten; + sess.opts.optimize == config::OptLevel::Aggressive; // 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 deleted file mode 100644 index 92c86372a86f..000000000000 --- a/src/librustc_target/abi/call/asmjs.rs +++ /dev/null @@ -1,47 +0,0 @@ -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 bc21113527ec..17bad189bcfd 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -5,7 +5,6 @@ mod aarch64; mod amdgpu; mod arm; -mod asmjs; mod hexagon; mod mips; mod mips64; @@ -22,6 +21,7 @@ mod x86_64; mod x86_win64; mod wasm32; +mod wasm32_bindgen_compat; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum PassMode { @@ -557,14 +557,6 @@ pub fn adjust_for_cabi(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), "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), @@ -573,6 +565,9 @@ pub fn adjust_for_cabi(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(), "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 1fdcbb8e39bd..27799edab919 100644 --- a/src/librustc_target/abi/call/wasm32.rs +++ b/src/librustc_target/abi/call/wasm32.rs @@ -1,20 +1,60 @@ -use crate::abi::call::{FnType, ArgType}; +use crate::abi::call::{FnType, ArgType, Uniform}; +use crate::abi::{HasDataLayout, LayoutOf, TyLayout, TyLayoutMethods}; -fn classify_ret_ty(ret: &mut ArgType<'_, Ty>) { +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 +{ ret.extend_integer_width_to(32); + if ret.layout.is_aggregate() { + if !unwrap_trivial_aggregate(cx, ret) { + ret.make_indirect(); + } + } } -fn classify_arg_ty(arg: &mut ArgType<'_, Ty>) { +fn classify_arg_ty<'a, Ty, C>(cx: &C, arg: &mut ArgType<'a, Ty>) + where Ty: TyLayoutMethods<'a, C> + Copy, + C: LayoutOf> + HasDataLayout +{ 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(fty: &mut FnType<'_, Ty>) { +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(&mut fty.ret); + classify_ret_ty(cx, &mut fty.ret); } for arg in &mut fty.args { if arg.is_ignore() { continue; } - classify_arg_ty(arg); + classify_arg_ty(cx, arg); } } diff --git a/src/librustc_target/abi/call/wasm32_bindgen_compat.rs b/src/librustc_target/abi/call/wasm32_bindgen_compat.rs new file mode 100644 index 000000000000..2645e30594ce --- /dev/null +++ b/src/librustc_target/abi/call/wasm32_bindgen_compat.rs @@ -0,0 +1,27 @@ +// 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 6dc140cf160e..e8f9c1f3d61d 100644 --- a/src/librustc_target/spec/asmjs_unknown_emscripten.rs +++ b/src/librustc_target/spec/asmjs_unknown_emscripten.rs @@ -1,40 +1,10 @@ -use super::{LinkArgs, LinkerFlavor, Target, TargetOptions}; +use super::{LinkerFlavor, Target, wasm32_unknown_emscripten}; pub fn target() -> Result { - 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, - }) + 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) } diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 25add0cc6a4b..cf1a84dec97b 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -462,7 +462,6 @@ fn $module() { ("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 deleted file mode 100644 index b802bee25ae7..000000000000 --- a/src/librustc_target/spec/wasm32_experimental_emscripten.rs +++ /dev/null @@ -1,44 +0,0 @@ -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 e0df36884bf5..6a2c8c495372 100644 --- a/src/librustc_target/spec/wasm32_unknown_emscripten.rs +++ b/src/librustc_target/spec/wasm32_unknown_emscripten.rs @@ -1,45 +1,46 @@ -use super::{LinkArgs, LinkerFlavor, Target, TargetOptions}; +use super::wasm32_base; +use super::{LinkArgs, LinkerFlavor, Target, TargetOptions, PanicStrategy}; 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(), - "BINARYEN_TRAP_MODE='clamp'".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(), + ]); 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 + // emcc emits two files - a .js file to instantiate the wasm and supply platform + // functionality, 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, - max_atomic_width: Some(32), + // 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, post_link_args, - limit_rdylib_exports: false, target_family: Some("unix".to_string()), - codegen_backend: "emscripten".to_string(), - .. Default::default() + .. wasm32_base::options() }; Ok(Target { - llvm_target: "asmjs-unknown-emscripten".to_string(), + llvm_target: "wasm32-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(), + 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/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index 706f52d03221..d5ce9456f7f6 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -360,7 +360,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { ("target_arch", Some(arch)) => match &*arch.as_str() { "aarch64" => "AArch64", "arm" => "ARM", - "asmjs" => "asm.js", + "asmjs" => "JavaScript", "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 952ba40ee87a..d7e733b7fa03 100644 --- a/src/libstd/sys/unix/fast_thread_local.rs +++ b/src/libstd/sys/unix/fast_thread_local.rs @@ -10,7 +10,8 @@ // 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"))] +#[cfg(any(target_os = "linux", target_os = "fuchsia", target_os = "hermit", target_os = "redox", + target_os = "emscripten"))] 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 5a77413b2cbb..4c3cbeb4acce 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -1735,9 +1735,9 @@ pub fn run_test( ) { let TestDescAndFn { desc, testfn } = test; - let ignore_because_no_process_support = cfg!(target_arch = "wasm32") - && !cfg!(target_os = "emscripten") - && desc.should_panic != ShouldPanic::No; + // 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")); 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 880d02a28ff0..5f7150a8eeba 100644 --- a/src/libtest/tests.rs +++ b/src/libtest/tests.rs @@ -2,8 +2,10 @@ use crate::test::{ filter_tests, parse_opts, run_test, DynTestFn, DynTestName, MetricMap, RunIgnored, RunStrategy, - ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TestTimeOptions, - TestType, TrFailedMsg, TrIgnored, TrOk, + // ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TestTimeOptions, + // TestType, TrFailedMsg, TrIgnored, TrOk, + ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, + TrIgnored, TrOk, }; use std::sync::mpsc::channel; use std::time::Duration; @@ -95,7 +97,9 @@ fn f() {} 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!(); @@ -116,7 +120,9 @@ fn f() { 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"); @@ -137,8 +143,11 @@ fn f() { 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"); } @@ -160,7 +169,9 @@ fn f() { 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 2acf95de97ee..7fa61d15f77c 100644 --- a/src/test/codegen/c-variadic.rs +++ b/src/test/codegen/c-variadic.rs @@ -1,3 +1,4 @@ +// 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 307c4e2c1e27..49e40d5f243f 100644 --- a/src/test/codegen/drop.rs +++ b/src/test/codegen/drop.rs @@ -1,3 +1,4 @@ +// 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 e44373926b76..ee61814678ce 100644 --- a/src/test/codegen/external-no-mangle-statics.rs +++ b/src/test/codegen/external-no-mangle-statics.rs @@ -1,3 +1,4 @@ +// 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 86c1365fdb71..88b8692b0ac5 100644 --- a/src/test/codegen/link_section.rs +++ b/src/test/codegen/link_section.rs @@ -1,3 +1,4 @@ +// 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 ad497b25a9ec..47b38d294174 100644 --- a/src/test/codegen/no-output-asm-is-volatile.rs +++ b/src/test/codegen/no-output-asm-is-volatile.rs @@ -1,7 +1,5 @@ // 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 05888c0e733a..c82ae476b1b2 100644 --- a/src/test/codegen/personality_lifetimes.rs +++ b/src/test/codegen/personality_lifetimes.rs @@ -1,4 +1,5 @@ // 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 5521c3c849f5..afefb9c9f71a 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-asmjs +// ignore-emscripten // ignore-mips64 // ignore-powerpc // ignore-powerpc64 @@ -9,7 +9,6 @@ // 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 acb993d51fb8..0a687078cd8e 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-abs.rs @@ -1,5 +1,3 @@ -// 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 58667af7e50e..9d47339d163c 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-ceil.rs @@ -1,5 +1,3 @@ -// 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 affbe17d3341..770b2a730377 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-cos.rs @@ -1,5 +1,3 @@ -// 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 43472d9dece8..33c860506668 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp.rs @@ -1,5 +1,3 @@ -// 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 471d49b7841e..f7a8986242d1 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-exp2.rs @@ -1,5 +1,3 @@ -// 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 bd8ba8b6cd77..a4070317a62b 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-floor.rs @@ -1,5 +1,3 @@ -// 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 8ad9e9004c2c..0800a498cb71 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fma.rs @@ -1,5 +1,3 @@ -// 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 ecffca960dab..adc44ffd8117 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-fsqrt.rs @@ -1,5 +1,3 @@ -// 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 79e6ed54690b..9c236f196362 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log.rs @@ -1,5 +1,3 @@ -// 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 db92a94fca84..a922161affab 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log10.rs @@ -1,5 +1,3 @@ -// 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 90d9ec3cedd6..9624acb383fb 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-log2.rs @@ -1,5 +1,3 @@ -// 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 2761392e6a92..7b9b1aec6c85 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-minmax.rs @@ -1,4 +1,3 @@ -// 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 1dd2c2ccb83d..6639e5d652b0 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-pow.rs @@ -1,5 +1,3 @@ -// 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 09f31bdd6bbd..5e82ea023d8e 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-powi.rs @@ -1,5 +1,3 @@ -// 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 dc87651c2aa1..8ca2ca860764 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-float-sin.rs @@ -1,5 +1,3 @@ -// 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 adee796d2475..237d15a5c68c 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 @@ // 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-9]+}}, <2 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.sadd.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.sadd.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.sadd.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.sadd.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <32 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.sadd.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <64 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.sadd.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.sadd.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.sadd.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.sadd.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.sadd.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <32 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.sadd.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.sadd.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.sadd.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.sadd.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.sadd.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.sadd.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.sadd.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.sadd.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i128> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.sadd.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i128> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.sadd.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.uadd.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.uadd.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.uadd.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.uadd.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <32 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.uadd.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <64 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.uadd.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.uadd.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.uadd.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.uadd.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.uadd.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <32 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.uadd.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.uadd.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.uadd.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.uadd.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.uadd.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.uadd.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.uadd.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.uadd.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i128> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.uadd.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i128> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.uadd.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.ssub.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.ssub.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.ssub.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.ssub.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <32 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.ssub.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <64 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.ssub.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.ssub.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.ssub.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.ssub.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.ssub.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <32 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.ssub.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.ssub.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.ssub.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.ssub.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.ssub.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.ssub.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.ssub.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.ssub.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i128> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i128> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.ssub.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i8> @llvm.usub.sat.v2i8(<2 x i8> %{{[0-9a-z]+}}, <2 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i8> @llvm.usub.sat.v4i8(<4 x i8> %{{[0-9a-z]+}}, <4 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i8> @llvm.usub.sat.v8i8(<8 x i8> %{{[0-9a-z]+}}, <8 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i8> @llvm.usub.sat.v16i8(<16 x i8> %{{[0-9a-z]+}}, <16 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <32 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i8> @llvm.usub.sat.v32i8(<32 x i8> %{{[0-9a-z]+}}, <32 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <64 x i8> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <64 x i8> @llvm.usub.sat.v64i8(<64 x i8> %{{[0-9a-z]+}}, <64 x i8> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i16> @llvm.usub.sat.v2i16(<2 x i16> %{{[0-9a-z]+}}, <2 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i16> @llvm.usub.sat.v4i16(<4 x i16> %{{[0-9a-z]+}}, <4 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i16> @llvm.usub.sat.v8i16(<8 x i16> %{{[0-9a-z]+}}, <8 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i16> @llvm.usub.sat.v16i16(<16 x i16> %{{[0-9a-z]+}}, <16 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <32 x i16> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <32 x i16> @llvm.usub.sat.v32i16(<32 x i16> %{{[0-9a-z]+}}, <32 x i16> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i32> @llvm.usub.sat.v2i32(<2 x i32> %{{[0-9a-z]+}}, <2 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %{{[0-9a-z]+}}, <4 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %{{[0-9a-z]+}}, <8 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <16 x i32> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <16 x i32> @llvm.usub.sat.v16i32(<16 x i32> %{{[0-9a-z]+}}, <16 x i32> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i64> @llvm.usub.sat.v2i64(<2 x i64> %{{[0-9a-z]+}}, <2 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i64> @llvm.usub.sat.v4i64(<4 x i64> %{{[0-9a-z]+}}, <4 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <8 x i64> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <8 x i64> @llvm.usub.sat.v8i64(<8 x i64> %{{[0-9a-z]+}}, <8 x i64> %{{[0-9a-z]+}}) 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-9]+}}, <2 x i128> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <2 x i128> @llvm.usub.sat.v2i128(<2 x i128> %{{[0-9a-z]+}}, <2 x i128> %{{[0-9a-z]+}}) 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-9]+}}, <4 x i128> %{{[0-9]+}}) + // CHECK: %{{[0-9]+}} = call <4 x i128> @llvm.usub.sat.v4i128(<4 x i128> %{{[0-9a-z]+}}, <4 x i128> %{{[0-9a-z]+}}) 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 cd8130f92314..543664014868 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 @@ pub struct i8x16( // CHECK-LABEL: @bitmask_int #[no_mangle] pub unsafe fn bitmask_int(x: i32x2) -> u8 { - // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9]+}}, + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9a-z]+}}, // 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-9]+}}, + // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> %{{[0-9a-z]+}}, // 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-9]+}}, + // CHECK: [[A:%[0-9]+]] = lshr <16 x i8> %{{[0-9a-z]+}}, // 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 3389104219dd..3b1f4398f900 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-gather.rs @@ -1,4 +1,3 @@ -// 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 dd0a9801bc5f..9fce849e5238 100644 --- a/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs +++ b/src/test/codegen/simd-intrinsic/simd-intrinsic-generic-scatter.rs @@ -1,4 +1,3 @@ -// 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 7339df17b057..98a9ff9cbe44 100644 --- a/src/test/codegen/union-abi.rs +++ b/src/test/codegen/union-abi.rs @@ -1,3 +1,4 @@ +// 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/codegen/unwind-extern-exports.rs b/src/test/codegen/unwind-extern-exports.rs index ddb3a4f6b4dd..d924a3b75dde 100644 --- a/src/test/codegen/unwind-extern-exports.rs +++ b/src/test/codegen/unwind-extern-exports.rs @@ -1,4 +1,5 @@ // compile-flags: -C opt-level=0 +// ignore-emscripten compiled with panic=abort by default #![crate_type = "lib"] #![feature(unwind_attributes)] diff --git a/src/test/codegen/unwind-extern-imports.rs b/src/test/codegen/unwind-extern-imports.rs index 485e8bbcd428..d88a49877564 100644 --- a/src/test/codegen/unwind-extern-imports.rs +++ b/src/test/codegen/unwind-extern-imports.rs @@ -1,4 +1,5 @@ // compile-flags: -C no-prepopulate-passes +// ignore-emscripten compiled with panic=abort by default #![crate_type = "lib"] #![feature(unwind_attributes)] diff --git a/src/test/compile-fail/weak-lang-item.rs b/src/test/compile-fail/weak-lang-item.rs index 768b936dc271..3fa3822831b5 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-wasm32-bare compiled with panic=abort, personality not required +// ignore-emscripten 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 f5d1acb621be..2bcb06d6eb8b 100644 --- a/src/test/incremental/change_crate_dep_kind.rs +++ b/src/test/incremental/change_crate_dep_kind.rs @@ -1,6 +1,7 @@ // 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 e5b84267b290..08a0232f661f 100644 --- a/src/test/incremental/commandline-args.rs +++ b/src/test/incremental/commandline-args.rs @@ -1,6 +1,7 @@ // 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 12411a928799..b01f02444eae 100644 --- a/src/test/incremental/remapped_paths_cc/main.rs +++ b/src/test/incremental/remapped_paths_cc/main.rs @@ -2,6 +2,7 @@ // 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 f1d7de145593..367416430f86 100644 --- a/src/test/incremental/span_hash_stable/main.rs +++ b/src/test/incremental/span_hash_stable/main.rs @@ -3,6 +3,7 @@ // 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 8ed469db6e63..f5cae15a4bc7 100644 --- a/src/test/incremental/spans_in_type_debuginfo.rs +++ b/src/test/incremental/spans_in_type_debuginfo.rs @@ -1,6 +1,7 @@ // 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 87c97ba06c46..e6fdc7cb3a0f 100644 --- a/src/test/incremental/spans_significant_w_debuginfo.rs +++ b/src/test/incremental/spans_significant_w_debuginfo.rs @@ -3,6 +3,7 @@ // 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 8dc6b73edf6d..4b66c07b0934 100644 --- a/src/test/mir-opt/box_expr.rs +++ b/src/test/mir-opt/box_expr.rs @@ -1,4 +1,4 @@ -// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 109304d6d22c..b595c100039d 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 e73390f52b5d..8824496fdb07 100644 --- a/src/test/mir-opt/issue-41110.rs +++ b/src/test/mir-opt/issue-41110.rs @@ -1,4 +1,4 @@ -// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 a3b517e9bca8..93250fd48d82 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 782bc31186ca..370cd593b02b 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 da73cc96348f..eaa1fbd69ecc 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 3245d38b2580..71beaa736639 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-wasm32-bare +// ignore-emscripten compiled with panic=abort by default 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 db36a1fab5f2..a0bdfb3ab8ba 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -1,4 +1,4 @@ -// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 7c64dc58bf79..2f48b852566e 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 +# only-wasm32-bare 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 fec7643d20c5..76698c0aae3b 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 +# only-wasm32-bare 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 15403d8d4109..7e47ba4850e3 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 +# only-wasm32-bare 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 255d8f1ef0e6..fe63e66f242b 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 + # only-wasm32-bare 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 b9141f93d538..68397e4bc6e1 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 +# only-wasm32-bare 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 b17e04b77177..62bd0f0872eb 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 +# only-wasm32-bare 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 b8f64e06f31e..7a923375c181 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 +# only-wasm32-bare 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 5d6fa416b989..b30e8f00e403 100644 --- a/src/test/ui/abi/statics/static-mut-foreign.rs +++ b/src/test/ui/abi/statics/static-mut-foreign.rs @@ -5,6 +5,10 @@ // 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 c266644fd702..4a413381aa30 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-wasm32-bare (sizes don't match) +// ignore-emscripten (sizes don't match) // run-pass // edition:2018 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 ad20237981c3..0558084f4f8a 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 @@ -4,7 +4,7 @@ // 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) +// ignore-emscripten (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 9ee419c4a56f..61f6ed1b7b2c 100644 --- a/src/test/ui/async-await/issue-60709.rs +++ b/src/test/ui/async-await/issue-60709.rs @@ -3,6 +3,7 @@ // 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 ea4a9e5afa50..4e0a238c5d48 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 5f7e357eeb2a..e6d17def1477 100644 --- a/src/test/ui/binding/match-arm-statics.rs +++ b/src/test/ui/binding/match-arm-statics.rs @@ -1,6 +1,7 @@ // 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 339bcfa1060a..1fd91440a788 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 f181991713b2..c2c21bca7ef7 100644 --- a/src/test/ui/catch-unwind-bang.rs +++ b/src/test/ui/catch-unwind-bang.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 394d6c17f5ad..d0a3eccd1776 100644 --- a/src/test/ui/consts/const-int-saturating-arith.rs +++ b/src/test/ui/consts/const-int-saturating-arith.rs @@ -1,5 +1,4 @@ // 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 e4beee9e737b..43f75b0344be 100644 --- a/src/test/ui/debuginfo-lto.rs +++ b/src/test/ui/debuginfo-lto.rs @@ -7,6 +7,7 @@ // 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 91063edf0f6c..bec86d6465ae 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 8516bc3d9642..7fd3f420a6d5 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 0eec9fb3ee64..9d96b4f63fb6 100644 --- a/src/test/ui/extern/extern-const.fixed +++ b/src/test/ui/extern/extern-const.fixed @@ -5,7 +5,8 @@ // compile. To sidestep this by using one that *is* defined. // run-rustfix -// ignore-wasm32 no external library to link to. +// ignore-wasm32-bare no external library to link to. +// ignore-asmjs wasm2js does not support source maps yet // 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 ca5d7ddf27e3..7cef5b3497b5 100644 --- a/src/test/ui/extern/extern-const.rs +++ b/src/test/ui/extern/extern-const.rs @@ -5,7 +5,8 @@ // compile. To sidestep this by using one that *is* defined. // run-rustfix -// ignore-wasm32 no external library to link to. +// ignore-wasm32-bare no external library to link to. +// ignore-asmjs wasm2js does not support source maps yet // 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 77406be2095c..258202b6903d 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:15:5 + --> $DIR/extern-const.rs:16:5 | LL | const rust_dbg_static_mut: libc::c_int; | ^^^^^ help: try using a static value: `static` diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs index 6d8ac7e8f291..759fb170f90d 100644 --- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs +++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.rs @@ -1,3 +1,4 @@ +// ignore-emscripten compiled with panic=abort by default // compile-flags: -C no-prepopulate-passes -Cpasses=name-anon-globals #![crate_type = "lib"] diff --git a/src/test/ui/generator/issue-58888.rs b/src/test/ui/generator/issue-58888.rs index 43b37a9afc2c..d42d09d401e8 100644 --- a/src/test/ui/generator/issue-58888.rs +++ b/src/test/ui/generator/issue-58888.rs @@ -1,5 +1,6 @@ // 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 5ac97585f4b5..b1a5cc67e86b 100644 --- a/src/test/ui/generator/panic-drops.rs +++ b/src/test/ui/generator/panic-drops.rs @@ -1,6 +1,6 @@ // run-pass -// ignore-wasm32-bare compiled as panic=abort by default +// ignore-emscripten compiled with 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 5f6778674dce..06c026180190 100644 --- a/src/test/ui/generator/panic-safe.rs +++ b/src/test/ui/generator/panic-safe.rs @@ -1,6 +1,6 @@ // run-pass -// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 71a68ff684af..ab18be58155d 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 01db971434bb..2864fbb2f3c8 100644 --- a/src/test/ui/generator/size-moved-locals.rs +++ b/src/test/ui/generator/size-moved-locals.rs @@ -11,6 +11,7 @@ // 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 0154f0499502..bac6c8d872b4 100644 --- a/src/test/ui/intrinsics/intrinsics-integer.rs +++ b/src/test/ui/intrinsics/intrinsics-integer.rs @@ -1,5 +1,4 @@ // 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 a2fd79624582..29e974ad83d1 100644 --- a/src/test/ui/issues/issue-14875.rs +++ b/src/test/ui/issues/issue-14875.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-wasm32-bare always compiled as panic=abort right now +// ignore-emscripten compiled with panic=abort by default // 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 1ce05ba390d7..988ebe03ccf6 100644 --- a/src/test/ui/issues/issue-23477.rs +++ b/src/test/ui/issues/issue-23477.rs @@ -1,4 +1,5 @@ // 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 773792c7a3f1..f08bcdfe6d16 100644 --- a/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs +++ b/src/test/ui/issues/issue-24687-embed-debuginfo/main.rs @@ -1,6 +1,7 @@ // 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 cf3834952c6a..0f92fc2f7f31 100644 --- a/src/test/ui/issues/issue-24945-repeat-dash-opts.rs +++ b/src/test/ui/issues/issue-24945-repeat-dash-opts.rs @@ -3,6 +3,7 @@ // 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 3b40b3dd8f07..2a8750d3e431 100644 --- a/src/test/ui/issues/issue-26484.rs +++ b/src/test/ui/issues/issue-26484.rs @@ -1,5 +1,6 @@ // 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 8ede8143ea65..5237a2f67bdd 100644 --- a/src/test/ui/issues/issue-29948.rs +++ b/src/test/ui/issues/issue-29948.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 f0b472e2fe82..2501e1430b3d 100644 --- a/src/test/ui/issues/issue-33096.rs +++ b/src/test/ui/issues/issue-33096.rs @@ -1,5 +1,6 @@ // 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 94fccff9fc65..a6b137ba6459 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-wasm32-bare common linkage not implemented right now +// ignore-emscripten 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 1f68560509e8..88dcdd411380 100644 --- a/src/test/ui/issues/issue-34569.rs +++ b/src/test/ui/issues/issue-34569.rs @@ -1,5 +1,6 @@ // 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 f2dfaf3dd367..5657ba69f944 100644 --- a/src/test/ui/issues/issue-36856.rs +++ b/src/test/ui/issues/issue-36856.rs @@ -2,6 +2,7 @@ // 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 318e3099f98b..01a5d563639b 100644 --- a/src/test/ui/issues/issue-42210.rs +++ b/src/test/ui/issues/issue-42210.rs @@ -2,6 +2,7 @@ // 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 47c3ab59aa2e..2a932db05af2 100644 --- a/src/test/ui/issues/issue-43853.rs +++ b/src/test/ui/issues/issue-43853.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 d20c07276a8c..5c5ac59873a3 100644 --- a/src/test/ui/issues/issue-45731.rs +++ b/src/test/ui/issues/issue-45731.rs @@ -1,6 +1,7 @@ // 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 461ea2498b0d..40c3117f01ce 100644 --- a/src/test/ui/issues/issue-46519.rs +++ b/src/test/ui/issues/issue-46519.rs @@ -1,6 +1,8 @@ // 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 385192b882ba..b7aa64228763 100644 --- a/src/test/ui/issues/issue-48508.rs +++ b/src/test/ui/issues/issue-48508.rs @@ -8,6 +8,7 @@ // 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 79cc107d4fec..767e06c4e90c 100644 --- a/src/test/ui/issues/issue-49579.rs +++ b/src/test/ui/issues/issue-49579.rs @@ -1,5 +1,4 @@ // 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 8ab845366b7b..af93f76221d4 100644 --- a/src/test/ui/issues/issue-58463.rs +++ b/src/test/ui/issues/issue-58463.rs @@ -1,5 +1,7 @@ // 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 d66120357508..fdd285dcad2a 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 f1eded31702c..b578999af8e9 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 5d67c7cbb425..3872a03b6825 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 ee4ab4d24c6a..4a9e8cdb72e7 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 429f8e0bc964..6bd1425e3246 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 9f1a31d1ae27..1c791bb1ca3d 100644 --- a/src/test/ui/macros/macro-comma-behavior-rpass.rs +++ b/src/test/ui/macros/macro-comma-behavior-rpass.rs @@ -13,6 +13,8 @@ // 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 6f13d5612ce5..de8d958af45e 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 2949437b1e4b..2bc5cf1c9763 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten compiled with panic=abort by default use std::cell::RefCell; use std::panic; diff --git a/src/test/ui/never_type/panic-uninitialized-zeroed.rs b/src/test/ui/never_type/panic-uninitialized-zeroed.rs index b0d662956180..72b844d8b488 100644 --- a/src/test/ui/never_type/panic-uninitialized-zeroed.rs +++ b/src/test/ui/never_type/panic-uninitialized-zeroed.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-wasm32-bare always compiled as panic=abort right now and this requires unwinding +// ignore-emscripten compiled with panic=abort by default // This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results // in a runtime 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 d210abdf499d..ced3c61ec162 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,5 +1,4 @@ // 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 ea0ef95e4f1a..ef558c0aa0c0 100644 --- a/src/test/ui/numbers-arithmetic/i128.rs +++ b/src/test/ui/numbers-arithmetic/i128.rs @@ -1,9 +1,6 @@ // 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 e9927304f23f..c1959866e5c2 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 bef7deb62760..2671a267f4a8 100644 --- a/src/test/ui/numbers-arithmetic/u128-as-f32.rs +++ b/src/test/ui/numbers-arithmetic/u128-as-f32.rs @@ -1,5 +1,4 @@ // 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 939407163237..0b2305c6e8b1 100644 --- a/src/test/ui/numbers-arithmetic/u128.rs +++ b/src/test/ui/numbers-arithmetic/u128.rs @@ -1,6 +1,4 @@ // 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 5d72771c2dcf..6dcb852a3669 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 4c25c09d6438..e7811d40b5b9 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 478af451e7f6..44671796c01a 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten compiled with panic=abort by default #![no_std] #![no_main] 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 418178d0f0ea..690a76ef3e0a 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 f1e53a0d8b42..26c51efea1e1 100644 --- a/src/test/ui/reachable-unnameable-items.rs +++ b/src/test/ui/reachable-unnameable-items.rs @@ -1,5 +1,5 @@ // run-pass -// ignore-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 39825c4f9a93..c8e8b9dcfc6a 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,6 +1,8 @@ // 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 7923aa7c0e22..b10b6ec11b53 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 164ae79c254f..51a572899f81 100644 --- a/src/test/ui/sepcomp/sepcomp-lib-lto.rs +++ b/src/test/ui/sepcomp/sepcomp-lib-lto.rs @@ -4,6 +4,7 @@ // 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 1a478460efc6..55b743ab7c7e 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 9fa759f9eb48..2284953fbbe9 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-wasm32-bare compiled with panic=abort by default +// ignore-emscripten 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 f86499e2e3f8..5d1e00d2d353 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,6 +10,7 @@ // 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 df56448dd225..030948850658 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -141,7 +141,10 @@ pub fn from_file(config: &Config, testfile: &Path) -> Self { 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 a2264f6af59f47497ccea65f29198edd2eb5ce58 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Wed, 9 Oct 2019 14:17:48 -0700 Subject: [PATCH 470/545] Temporarily enable asmjs and wasm32 on PR CI --- src/ci/azure-pipelines/pr.yml | 4 ++++ src/ci/docker/{disabled => }/wasm32/Dockerfile | 0 2 files changed, 4 insertions(+) rename src/ci/docker/{disabled => }/wasm32/Dockerfile (100%) diff --git a/src/ci/azure-pipelines/pr.yml b/src/ci/azure-pipelines/pr.yml index 62e23efe1ef1..07c79d8cc963 100644 --- a/src/ci/azure-pipelines/pr.yml +++ b/src/ci/azure-pipelines/pr.yml @@ -22,6 +22,10 @@ jobs: IMAGE: x86_64-gnu-llvm-6.0 mingw-check: IMAGE: mingw-check + asmjs: + IMAGE: asmjs + wasm32: + IMAGE: wasm32 - job: LinuxTools timeoutInMinutes: 600 diff --git a/src/ci/docker/disabled/wasm32/Dockerfile b/src/ci/docker/wasm32/Dockerfile similarity index 100% rename from src/ci/docker/disabled/wasm32/Dockerfile rename to src/ci/docker/wasm32/Dockerfile From b0b6e368c0d1fe35d7813c319a535a0ad09a1d47 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 11 Oct 2019 17:14:48 -0700 Subject: [PATCH 471/545] Update test and add -O1 to wasm32 Dockerfile --- src/ci/docker/asmjs/Dockerfile | 2 -- src/ci/docker/wasm32/Dockerfile | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile index 75db374907d7..24e9311d6806 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -29,8 +29,6 @@ ENV EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=asmjs-unknown-emscripten # Use -O1 optimizations in the link step to reduce time spent optimizing JS. -# FIXME: Switch to testing wasm32-unknown-emscripten and -O1 to save more time -# once the CI picks up https://github.com/rust-lang/cargo/pull/7476. ENV EMCC_CFLAGS=-O1 ENV SCRIPT python2.7 ../x.py test --target $TARGETS diff --git a/src/ci/docker/wasm32/Dockerfile b/src/ci/docker/wasm32/Dockerfile index aeccbb9bdc03..7a3055915111 100644 --- a/src/ci/docker/wasm32/Dockerfile +++ b/src/ci/docker/wasm32/Dockerfile @@ -28,6 +28,9 @@ ENV EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=wasm32-unknown-emscripten +# Use -O1 optimizations in the link step to reduce time spent optimizing. +ENV EMCC_CFLAGS=-O1 + # FIXME: Re-enable these tests once https://github.com/rust-lang/cargo/pull/7476 # is picked up by CI ENV SCRIPT python2.7 ../x.py test --target $TARGETS \ From 36808c251c47f4eafe4cc074867ac5fe8b194041 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Mon, 14 Oct 2019 14:19:53 -0700 Subject: [PATCH 472/545] Update test expectations --- src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr index 10cc49421350..97365c34d014 100644 --- a/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr +++ b/src/test/ui/feature-gates/feature-gate-unwind-attributes.stderr @@ -1,5 +1,5 @@ error[E0658]: the `#[unwind]` attribute is an experimental feature - --> $DIR/feature-gate-unwind-attributes.rs:11:5 + --> $DIR/feature-gate-unwind-attributes.rs:12:5 | LL | #[unwind(allowed)] | ^^^^^^^^^^^^^^^^^^ From 4b26d9c142efcbd175dad36f7cb4ebf9e682154e Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Wed, 16 Oct 2019 17:06:34 -0700 Subject: [PATCH 473/545] User should not change between emcc install and use --- src/ci/docker/asmjs/Dockerfile | 4 +++- src/ci/docker/scripts/emscripten.sh | 10 ---------- src/ci/docker/wasm32/Dockerfile | 4 +++- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/asmjs/Dockerfile index 24e9311d6806..e27a2a529a8c 100644 --- a/src/ci/docker/asmjs/Dockerfile +++ b/src/ci/docker/asmjs/Dockerfile @@ -24,13 +24,15 @@ 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 EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=asmjs-unknown-emscripten # Use -O1 optimizations in the link step to reduce time spent optimizing JS. ENV EMCC_CFLAGS=-O1 +# Emscripten installation is user-specific +ENV NO_CHANGE_USER=1 + ENV SCRIPT python2.7 ../x.py test --target $TARGETS # This is almost identical to the wasm32-unknown-emscripten target, so diff --git a/src/ci/docker/scripts/emscripten.sh b/src/ci/docker/scripts/emscripten.sh index 9c7a09e227a4..1be80741594c 100644 --- a/src/ci/docker/scripts/emscripten.sh +++ b/src/ci/docker/scripts/emscripten.sh @@ -21,13 +21,3 @@ git clone https://github.com/emscripten-core/emsdk.git /emsdk-portable cd /emsdk-portable hide_output ./emsdk install 1.38.46-upstream ./emsdk activate 1.38.46-upstream - -# Compile and cache libc -source ./emsdk_env.sh -echo "main(){}" > a.c -HOME=/emsdk-portable/ emcc a.c -rm -f a.* - -# Make emsdk usable by any user -cp /root/.emscripten /emsdk-portable -chmod a+rxw -R /emsdk-portable diff --git a/src/ci/docker/wasm32/Dockerfile b/src/ci/docker/wasm32/Dockerfile index 7a3055915111..a0f35afd995b 100644 --- a/src/ci/docker/wasm32/Dockerfile +++ b/src/ci/docker/wasm32/Dockerfile @@ -24,13 +24,15 @@ 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 EM_CONFIG=/emsdk-portable/.emscripten ENV TARGETS=wasm32-unknown-emscripten # Use -O1 optimizations in the link step to reduce time spent optimizing. ENV EMCC_CFLAGS=-O1 +# Emscripten installation is user-specific +ENV NO_CHANGE_USER=1 + # FIXME: Re-enable these tests once https://github.com/rust-lang/cargo/pull/7476 # is picked up by CI ENV SCRIPT python2.7 ../x.py test --target $TARGETS \ From 75f4dac5f38cfe46cf9ccd3b2c602a5e1336453c Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 16 Oct 2019 18:00:44 -0700 Subject: [PATCH 474/545] Add regression test for #65394 --- src/test/ui/consts/const-eval/issue-65394.rs | 13 +++++++++++++ src/test/ui/consts/const-eval/issue-65394.stderr | 11 +++++++++++ 2 files changed, 24 insertions(+) create mode 100644 src/test/ui/consts/const-eval/issue-65394.rs create mode 100644 src/test/ui/consts/const-eval/issue-65394.stderr diff --git a/src/test/ui/consts/const-eval/issue-65394.rs b/src/test/ui/consts/const-eval/issue-65394.rs new file mode 100644 index 000000000000..978e227bcc81 --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-65394.rs @@ -0,0 +1,13 @@ +// Test for absence of validation mismatch ICE in #65394 + +#![feature(rustc_attrs)] + +#[rustc_mir(borrowck_graphviz_postflow="hello.dot")] +const _: Vec = { + let mut x = Vec::::new(); + let r = &mut x; //~ ERROR references in constants may only refer to immutable values + let y = x; + y +}; + +fn main() {} diff --git a/src/test/ui/consts/const-eval/issue-65394.stderr b/src/test/ui/consts/const-eval/issue-65394.stderr new file mode 100644 index 000000000000..f48c551cb50f --- /dev/null +++ b/src/test/ui/consts/const-eval/issue-65394.stderr @@ -0,0 +1,11 @@ +error[E0017]: references in constants may only refer to immutable values + --> $DIR/issue-65394.rs:8:13 + | +LL | let r = &mut x; + | ^^^^^^ constants require immutable values + +[ERROR rustc_mir::transform::qualify_consts] old validator: [($DIR/issue-65394.rs:8:13: 8:19, "MutBorrow(Mut { allow_two_phase_borrow: false })")] +[ERROR rustc_mir::transform::qualify_consts] new validator: [($DIR/issue-65394.rs:8:13: 8:19, "MutBorrow(Mut { allow_two_phase_borrow: false })"), ($DIR/issue-65394.rs:7:9: 7:14, "LiveDrop")] +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0017`. From 22a0856641dec573ab3b83b09c57aa597ca87b19 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 16 Oct 2019 18:01:01 -0700 Subject: [PATCH 475/545] Enable `drain_filter` --- src/librustc_mir/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index a837c34e8d47..98d5487870a4 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -14,6 +14,7 @@ #![feature(core_intrinsics)] #![feature(const_fn)] #![feature(decl_macro)] +#![feature(drain_filter)] #![feature(exhaustive_patterns)] #![feature(never_type)] #![feature(specialization)] From af691de9c1d9923e8a6b7965d1eebf21e1d87ad2 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 16 Oct 2019 18:01:26 -0700 Subject: [PATCH 476/545] Suppress validation mismatch ICE in the presence of mut borrows --- src/librustc_mir/transform/qualify_consts.rs | 75 +++++++++++++++----- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index fbcf9c8cb5eb..da1abb9747c1 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1024,23 +1024,12 @@ fn check_const(&mut self) -> (u8, &'tcx BitSet) { new_errors.dedup(); if self.errors != new_errors { - error!("old validator: {:?}", self.errors); - error!("new validator: {:?}", new_errors); - - // ICE on nightly if the validators do not emit exactly the same errors. - // Users can supress this panic with an unstable compiler flag (hopefully after - // filing an issue). - let opts = &self.tcx.sess.opts; - let trigger_ice = opts.unstable_features.is_nightly_build() - && !opts.debugging_opts.suppress_const_validation_back_compat_ice; - - if trigger_ice { - span_bug!( - body.span, - "{}", - VALIDATOR_MISMATCH_ERR, - ); - } + validator_mismatch( + self.tcx, + body, + std::mem::replace(&mut self.errors, vec![]), + new_errors, + ); } } @@ -1870,6 +1859,58 @@ fn args_required_const(tcx: TyCtxt<'_>, def_id: DefId) -> Option, + body: &Body<'tcx>, + mut old_errors: Vec<(Span, String)>, + mut new_errors: Vec<(Span, String)>, +) { + error!("old validator: {:?}", old_errors); + error!("new validator: {:?}", new_errors); + + // ICE on nightly if the validators do not emit exactly the same errors. + // Users can supress this panic with an unstable compiler flag (hopefully after + // filing an issue). + let opts = &tcx.sess.opts; + let strict_validation_enabled = opts.unstable_features.is_nightly_build() + && !opts.debugging_opts.suppress_const_validation_back_compat_ice; + + if !strict_validation_enabled { + return; + } + + // If this difference would cause a regression from the old to the new or vice versa, trigger + // the ICE. + if old_errors.is_empty() || new_errors.is_empty() { + span_bug!(body.span, "{}", VALIDATOR_MISMATCH_ERR); + } + + // HACK: Borrows that would allow mutation are forbidden in const contexts, but they cause the + // new validator to be more conservative about when a dropped local has been moved out of. + // + // Supress the mismatch ICE in cases where the validators disagree only on the number of + // `LiveDrop` errors and both observe the same sequence of `MutBorrow`s. + + let is_live_drop = |(_, s): &mut (_, String)| s.starts_with("LiveDrop"); + let is_mut_borrow = |(_, s): &&(_, String)| s.starts_with("MutBorrow"); + + let old_live_drops: Vec<_> = old_errors.drain_filter(is_live_drop).collect(); + let new_live_drops: Vec<_> = new_errors.drain_filter(is_live_drop).collect(); + + let only_live_drops_differ = old_live_drops != new_live_drops && old_errors == new_errors; + + let old_mut_borrows = old_errors.iter().filter(is_mut_borrow); + let new_mut_borrows = new_errors.iter().filter(is_mut_borrow); + + let at_least_one_mut_borrow = old_mut_borrows.clone().next().is_some(); + + if only_live_drops_differ && at_least_one_mut_borrow && old_mut_borrows.eq(new_mut_borrows) { + return; + } + + span_bug!(body.span, "{}", VALIDATOR_MISMATCH_ERR); +} + const VALIDATOR_MISMATCH_ERR: &str = r"Disagreement between legacy and dataflow-based const validators. After filing an issue, use `-Zsuppress-const-validation-back-compat-ice` to compile your code."; From fb6d5e6b1f6550b74ca78b6c2c022ff553f6d421 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Wed, 16 Oct 2019 22:22:19 -0400 Subject: [PATCH 477/545] doc: fix typo in OsStrExt and OsStringExt --- src/libstd/sys_common/os_str_bytes.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libstd/sys_common/os_str_bytes.rs b/src/libstd/sys_common/os_str_bytes.rs index d734f412bf88..3753269adfe4 100644 --- a/src/libstd/sys_common/os_str_bytes.rs +++ b/src/libstd/sys_common/os_str_bytes.rs @@ -193,7 +193,7 @@ pub fn into_rc(&self) -> Rc { pub trait OsStringExt { /// Creates an [`OsString`] from a byte vector. /// - /// See the module docmentation for an example. + /// See the module documentation for an example. /// /// [`OsString`]: ../../../ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] @@ -201,7 +201,7 @@ pub trait OsStringExt { /// Yields the underlying byte vector of this [`OsString`]. /// - /// See the module docmentation for an example. + /// See the module documentation for an example. /// /// [`OsString`]: ../../../ffi/struct.OsString.html #[stable(feature = "rust1", since = "1.0.0")] @@ -226,14 +226,14 @@ pub trait OsStrExt { #[stable(feature = "rust1", since = "1.0.0")] /// Creates an [`OsStr`] from a byte slice. /// - /// See the module docmentation for an example. + /// See the module documentation for an example. /// /// [`OsStr`]: ../../../ffi/struct.OsStr.html fn from_bytes(slice: &[u8]) -> &Self; /// Gets the underlying byte view of the [`OsStr`] slice. /// - /// See the module docmentation for an example. + /// See the module documentation for an example. /// /// [`OsStr`]: ../../../ffi/struct.OsStr.html #[stable(feature = "rust1", since = "1.0.0")] From 42c0236ed0071ed9f8734c346341f0bf54732b8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 13 Jun 2019 23:14:44 +0200 Subject: [PATCH 478/545] Use a sharded dep node to dep node index map --- src/librustc/dep_graph/graph.rs | 29 +++++++++++++++++------- src/librustc_data_structures/sharded.rs | 30 +++++++++++++++++++------ 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 5d2d30f8debb..337cdddc432c 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -4,6 +4,7 @@ use rustc_index::vec::{Idx, IndexVec}; use smallvec::SmallVec; use rustc_data_structures::sync::{Lrc, Lock, AtomicU32, AtomicU64, Ordering}; +use rustc_data_structures::sharded::{self, Sharded}; use std::sync::atomic::Ordering::SeqCst; use std::env; use std::hash::Hash; @@ -381,7 +382,7 @@ pub fn with_eval_always_task<'a, C, A, R>( #[inline] pub fn read(&self, v: DepNode) { if let Some(ref data) = self.data { - let map = data.current.node_to_node_index.lock(); + let map = data.current.node_to_node_index.get_shard_by_value(&v).lock(); if let Some(dep_node_index) = map.get(&v).copied() { std::mem::drop(map); data.read_index(dep_node_index); @@ -405,6 +406,7 @@ pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex { .unwrap() .current .node_to_node_index + .get_shard_by_value(dep_node) .lock() .get(dep_node) .cloned() @@ -414,7 +416,11 @@ pub fn dep_node_index_of(&self, dep_node: &DepNode) -> DepNodeIndex { #[inline] pub fn dep_node_exists(&self, dep_node: &DepNode) -> bool { if let Some(ref data) = self.data { - data.current.node_to_node_index.lock().contains_key(dep_node) + data.current + .node_to_node_index + .get_shard_by_value(&dep_node) + .lock() + .contains_key(dep_node) } else { false } @@ -595,7 +601,11 @@ fn try_mark_previous_green<'tcx>( #[cfg(not(parallel_compiler))] { - debug_assert!(!data.current.node_to_node_index.lock().contains_key(dep_node)); + debug_assert!(!data.current + .node_to_node_index + .get_shard_by_value(dep_node) + .lock() + .contains_key(dep_node)); debug_assert!(data.colors.get(prev_dep_node_index).is_none()); } @@ -927,7 +937,7 @@ struct DepNodeData { /// acquire the lock on `data.` pub(super) struct CurrentDepGraph { data: Lock>, - node_to_node_index: Lock>, + node_to_node_index: Sharded>, /// 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`. @@ -985,8 +995,8 @@ fn new(prev_graph_node_count: usize) -> CurrentDepGraph { CurrentDepGraph { 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, + node_to_node_index: Sharded::new(|| FxHashMap::with_capacity_and_hasher( + new_node_count_estimate / sharded::SHARDS, Default::default(), )), anon_id_seed: stable_hasher.finish(), @@ -1035,7 +1045,10 @@ fn alloc_node( edges: SmallVec<[DepNodeIndex; 8]>, fingerprint: Fingerprint ) -> DepNodeIndex { - debug_assert!(!self.node_to_node_index.lock().contains_key(&dep_node)); + debug_assert!(!self.node_to_node_index + .get_shard_by_value(&dep_node) + .lock() + .contains_key(&dep_node)); self.intern_node(dep_node, edges, fingerprint) } @@ -1045,7 +1058,7 @@ fn intern_node( edges: SmallVec<[DepNodeIndex; 8]>, fingerprint: Fingerprint ) -> DepNodeIndex { - match self.node_to_node_index.lock().entry(dep_node) { + match self.node_to_node_index.get_shard_by_value(&dep_node).lock().entry(dep_node) { Entry::Occupied(entry) => *entry.get(), Entry::Vacant(entry) => { let mut data = self.data.lock(); diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs index 31cb22098b8e..d0ff6108d6ea 100644 --- a/src/librustc_data_structures/sharded.rs +++ b/src/librustc_data_structures/sharded.rs @@ -2,6 +2,7 @@ use std::mem; use std::borrow::Borrow; use std::collections::hash_map::RawEntryMut; +use smallvec::SmallVec; use crate::fx::{FxHasher, FxHashMap}; use crate::sync::{Lock, LockGuard}; @@ -18,7 +19,7 @@ #[cfg(not(parallel_compiler))] const SHARD_BITS: usize = 0; -const SHARDS: usize = 1 << SHARD_BITS; +pub const SHARDS: usize = 1 << SHARD_BITS; /// An array of cache-line aligned inner locked structures with convenience methods. #[derive(Clone)] @@ -29,21 +30,36 @@ pub struct Sharded { impl Default for Sharded { #[inline] fn default() -> Self { + Self::new(|| T::default()) + } +} + +impl Sharded { + #[inline] + pub fn new(mut value: impl FnMut() -> T) -> Self { + // Create a vector of the values we want + let mut values: SmallVec<[_; SHARDS]> = (0..SHARDS).map(|_| { + CacheAligned(Lock::new(value())) + }).collect(); + + // Create an unintialized array let mut shards: mem::MaybeUninit<[CacheAligned>; SHARDS]> = mem::MaybeUninit::uninit(); - let first = shards.as_mut_ptr() as *mut CacheAligned>; + unsafe { - for i in 0..SHARDS { - first.add(i).write(CacheAligned(Lock::new(T::default()))); - } + // Copy the values into our array + let first = shards.as_mut_ptr() as *mut CacheAligned>; + values.as_ptr().copy_to_nonoverlapping(first, SHARDS); + + // Ignore the content of the vector + values.set_len(0); + Sharded { shards: shards.assume_init(), } } } -} -impl Sharded { #[inline] pub fn get_shard_by_value(&self, val: &K) -> &Lock { if SHARDS == 1 { From c0aa7cb2b553f5c58102c6b95210c5adbb3518f3 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Wed, 16 Oct 2019 21:18:34 -0700 Subject: [PATCH 479/545] Remove PR runs, enable wasm32 CI, and move asmjs to disabled --- src/ci/azure-pipelines/auto.yml | 4 ++-- src/ci/azure-pipelines/pr.yml | 4 ---- src/ci/docker/{ => disabled}/asmjs/Dockerfile | 0 3 files changed, 2 insertions(+), 6 deletions(-) rename src/ci/docker/{ => disabled}/asmjs/Dockerfile (100%) diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index 5f7761297095..4442afc98e40 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -124,14 +124,14 @@ jobs: IMAGE: dist-x86_64-netbsd DEPLOY: 1 - asmjs: - IMAGE: asmjs i686-gnu: IMAGE: i686-gnu i686-gnu-nopt: IMAGE: i686-gnu-nopt test-various: IMAGE: test-various + wasm32: + IMAGE: wasm32 x86_64-gnu: IMAGE: x86_64-gnu x86_64-gnu-full-bootstrap: diff --git a/src/ci/azure-pipelines/pr.yml b/src/ci/azure-pipelines/pr.yml index 07c79d8cc963..62e23efe1ef1 100644 --- a/src/ci/azure-pipelines/pr.yml +++ b/src/ci/azure-pipelines/pr.yml @@ -22,10 +22,6 @@ jobs: IMAGE: x86_64-gnu-llvm-6.0 mingw-check: IMAGE: mingw-check - asmjs: - IMAGE: asmjs - wasm32: - IMAGE: wasm32 - job: LinuxTools timeoutInMinutes: 600 diff --git a/src/ci/docker/asmjs/Dockerfile b/src/ci/docker/disabled/asmjs/Dockerfile similarity index 100% rename from src/ci/docker/asmjs/Dockerfile rename to src/ci/docker/disabled/asmjs/Dockerfile From c716be6874f0c55c835d9b0aba5b41ff52329aab Mon Sep 17 00:00:00 2001 From: Guanqun Lu Date: Thu, 17 Oct 2019 16:57:46 +0800 Subject: [PATCH 480/545] show up some extra info when t!() fails --- src/bootstrap/lib.rs | 2 +- src/build_helper/lib.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 9203a558f646..6fc72fa0b2a3 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1126,7 +1126,7 @@ fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, bool)> { } let mut paths = Vec::new(); - let contents = t!(fs::read(stamp)); + let contents = t!(fs::read(stamp), &stamp); // This is the method we use for extracting paths from the stamp file passed to us. See // run_cargo for more information (in compile.rs). for part in contents.split(|b| *b == 0) { diff --git a/src/build_helper/lib.rs b/src/build_helper/lib.rs index f035a7119188..bb94fb2b755f 100644 --- a/src/build_helper/lib.rs +++ b/src/build_helper/lib.rs @@ -21,6 +21,13 @@ macro_rules! t { Err(e) => panic!("{} failed with {}", stringify!($e), e), } }; + // it can show extra info in the second parameter + ($e:expr, $extra:expr) => { + match $e { + Ok(e) => e, + Err(e) => panic!("{} failed with {} ({:?})", stringify!($e), e, $extra), + } + }; } // Because Cargo adds the compiler's dylib path to our library search path, llvm-config may From d1db077e067b00c4733512dd23f8b144a760f367 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 12 Oct 2019 14:48:20 +0200 Subject: [PATCH 481/545] Add long error explanation for E0575 --- src/librustc_resolve/error_codes.rs | 54 ++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index ab3d95dd8edf..8ccb27078d56 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1735,6 +1735,59 @@ enum Jak { ``` "##, +E0575: r##" +Something other than a type or an associated type was given. + +Erroneous code example: + +```compile_fail,E0575 +enum Rick { Morty } + +let _: ::Morty; // error! + +trait Age { + type Empire; + fn Mythology() {} +} + +impl Age for u8 { + type Empire = u16; +} + +let _: ::Mythology; // error! +``` + +In both cases, we're declaring a variable (called `_`) and we're giving it a +type. However, `::Morty` and `::Mythology` aren't types, +therefore the compiler throws an error. + +`::Morty` is an enum variant, you cannot use a variant as a type, +you have to use the enum directly: + +``` +enum Rick { Morty } + +let _: Rick; // ok! +``` + +`::Mythology` is a trait method, which is definitely not a type. +However, the `Age` trait provides an associated type `Empire` which can be +used as a type: + +``` +trait Age { + type Empire; + fn Mythology() {} +} + +impl Age for u8 { + type Empire = u16; +} + +let _: ::Empire; // ok! +``` +"##, + E0603: r##" A private item was used outside its scope. @@ -1862,7 +1915,6 @@ struct Foo> { // E0427, merged into 530 // E0467, removed // E0470, removed - E0575, E0576, E0577, E0578, From 21d9258909d131898bdd9d69bc9da8be3b31db9a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 12 Oct 2019 14:48:28 +0200 Subject: [PATCH 482/545] Update ui tests --- src/test/ui/ufcs/ufcs-partially-resolved.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr index 5ee8adaaf270..39752f66b9d6 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr +++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr @@ -200,5 +200,5 @@ LL | ::X::N; error: aborting due to 32 previous errors -Some errors have detailed explanations: E0223, E0433, E0599. +Some errors have detailed explanations: E0223, E0433, E0575, E0599. For more information about an error, try `rustc --explain E0223`. From 83e97c6ac1b722c1b55fdf9d6378f87d9e0cdbdd Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Thu, 17 Oct 2019 13:53:57 +0200 Subject: [PATCH 483/545] properly document panics in div_euclid and rem_euclid --- src/libcore/num/mod.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 998c8f816520..8f4ade377e31 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1864,7 +1864,7 @@ pub fn pow(self, mut exp: u32) -> Self { # Panics -This function will panic if `rhs` is 0. +This function will panic if `rhs` is 0 or the division results in overflow. # Examples @@ -1903,7 +1903,7 @@ pub fn div_euclid(self, rhs: Self) -> Self { # Panics -This function will panic if `rhs` is 0. +This function will panic if `rhs` is 0 or the division results in overflow. # Examples @@ -3694,6 +3694,10 @@ pub fn pow(self, mut exp: u32) -> Self { definitions of division are equal, this is exactly equal to `self / rhs`. +# Panics + +This function will panic if `rhs` is 0. + # Examples Basic usage: @@ -3719,6 +3723,10 @@ pub fn div_euclid(self, rhs: Self) -> Self { definitions of division are equal, this is exactly equal to `self % rhs`. +# Panics + +This function will panic if `rhs` is 0. + # Examples Basic usage: From 4cd92768ee9cbaf0df98f0d31f0c44e62f63d79a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 17 Oct 2019 11:06:06 +0200 Subject: [PATCH 484/545] Add long error explanation for E0584 --- src/libsyntax/error_codes.rs | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/libsyntax/error_codes.rs b/src/libsyntax/error_codes.rs index fc3f095856a8..17ea47675206 100644 --- a/src/libsyntax/error_codes.rs +++ b/src/libsyntax/error_codes.rs @@ -295,6 +295,33 @@ fn main() {} same directory. "##, +E0584: r##" +A doc comment that is not attached to anything has been encountered. + +Erroneous code example: + +```compile_fail,E0584 +trait Island { + fn lost(); + + /// I'm lost! +} +``` + +A little reminder: a doc comment has to be placed before the item it's supposed +to document. So if you want to document the `Island` trait, you need to put a +doc comment before it, not inside it. Same goes for the `lost` method: the doc +comment needs to be before it: + +``` +/// I'm THE island! +trait Island { + /// I'm lost! + fn lost(); +} +``` +"##, + E0585: r##" A documentation comment that doesn't document anything was found. @@ -494,7 +521,6 @@ pub(in crate::foo) struct Bar { E0549, E0553, // multiple rustc_const_unstable attributes // E0555, // replaced with a generic attribute input check - E0584, // file for module `..` found at both .. and .. E0629, // missing 'feature' (rustc_const_unstable) // rustc_const_unstable attribute must be paired with stable/unstable // attribute From f647c06120150bb26c843a5eaa65caf5c336b51a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 17 Oct 2019 11:06:14 +0200 Subject: [PATCH 485/545] Update ui tests --- src/test/ui/mod/mod_file_disambig.stderr | 1 + src/test/ui/parser/doc-inside-trait-item.stderr | 1 + 2 files changed, 2 insertions(+) diff --git a/src/test/ui/mod/mod_file_disambig.stderr b/src/test/ui/mod/mod_file_disambig.stderr index 27df0241aa21..2b77d866fb30 100644 --- a/src/test/ui/mod/mod_file_disambig.stderr +++ b/src/test/ui/mod/mod_file_disambig.stderr @@ -8,3 +8,4 @@ LL | mod mod_file_disambig_aux; error: aborting due to previous error +For more information about this error, try `rustc --explain E0584`. diff --git a/src/test/ui/parser/doc-inside-trait-item.stderr b/src/test/ui/parser/doc-inside-trait-item.stderr index 3287ece9ae64..261e27b6e0d1 100644 --- a/src/test/ui/parser/doc-inside-trait-item.stderr +++ b/src/test/ui/parser/doc-inside-trait-item.stderr @@ -8,3 +8,4 @@ LL | /// empty doc error: aborting due to previous error +For more information about this error, try `rustc --explain E0584`. From 71b0049ad66eb3f1d8339979422b89e44306bc05 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 17 Oct 2019 13:51:46 +0200 Subject: [PATCH 486/545] =?UTF-8?q?Plugins=20deprecation:=20don=E2=80=99t?= =?UTF-8?q?=20suggest=20simply=20removing=20the=20attribute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building Servo with a recent Nightly produces: ```rust warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 --> components/script/lib.rs:14:1 | 14 | #![plugin(script_plugins)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | = note: `#[warn(deprecated)]` on by default ``` First, linking to https://github.com/rust-lang/rust/issues/29597 is not ideal since there is pretty much no discussion there of the deprecation and what can be used instead. This PR changes the link to the deprecation PR which does have more discussion. Second, the “remove this attribute” suggestion is rather unhelpful. Just because a feature is deprecated doesn’t mean that simply removing its use without a replacement is acceptable. In the case of custom lint, there is no replacement available. Prefixing a message with “help:” when telling users that they’re screwed honestly feels disrespectful. This PR also changes the message to be more factual. --- src/libsyntax/feature_gate/builtin_attrs.rs | 10 ++++++-- src/test/ui-fulldeps/gated-plugin.stderr | 4 ++-- src/test/ui-fulldeps/issue-15778-fail.stderr | 4 ++-- src/test/ui-fulldeps/issue-15778-pass.stderr | 4 ++-- src/test/ui-fulldeps/issue-40001.stderr | 4 ++-- .../lint-group-plugin-deny-cmdline.stderr | 4 ++-- src/test/ui-fulldeps/lint-group-plugin.stderr | 4 ++-- .../lint-plugin-cmdline-allow.stderr | 4 ++-- .../ui-fulldeps/lint-plugin-deny-attr.stderr | 4 ++-- .../lint-plugin-deny-cmdline.stderr | 4 ++-- .../lint-plugin-forbid-attrs.stderr | 4 ++-- .../lint-plugin-forbid-cmdline.stderr | 4 ++-- src/test/ui-fulldeps/lint-plugin.stderr | 4 ++-- .../lint-tool-cmdline-allow.stderr | 4 ++-- src/test/ui-fulldeps/lint-tool-test.stderr | 4 ++-- src/test/ui-fulldeps/llvm-pass-plugin.stderr | 4 ++-- .../ui-fulldeps/lto-syntax-extension.stderr | 4 ++-- src/test/ui-fulldeps/macro-crate-rlib.stderr | 4 ++-- .../outlive-expansion-phase.stderr | 4 ++-- src/test/ui-fulldeps/plugin-args-1.stderr | 4 ++-- src/test/ui-fulldeps/plugin-args-2.stderr | 4 ++-- src/test/ui-fulldeps/plugin-args-3.stderr | 4 ++-- .../plugin-attr-register-deny.stderr | 4 ++-- src/test/ui-fulldeps/plugin-reexport.stderr | 4 ++-- .../ui-fulldeps/roman-numerals-macro.stderr | 4 ++-- ...issue-43106-gating-of-builtin-attrs.stderr | 24 +++++++++---------- .../feature-gates/feature-gate-plugin.stderr | 4 ++-- .../feature-gate-plugin_registrar.stderr | 4 ++-- .../ui/invalid/invalid-plugin-attr.stderr | 4 ++-- .../ui/malformed/malformed-plugin-1.stderr | 4 ++-- .../ui/malformed/malformed-plugin-2.stderr | 4 ++-- .../ui/malformed/malformed-plugin-3.stderr | 4 ++-- src/test/ui/multiple-plugin-registrars.stderr | 8 +++---- 33 files changed, 84 insertions(+), 78 deletions(-) diff --git a/src/libsyntax/feature_gate/builtin_attrs.rs b/src/libsyntax/feature_gate/builtin_attrs.rs index 043a2ffb5a48..7dd6ae90d9a4 100644 --- a/src/libsyntax/feature_gate/builtin_attrs.rs +++ b/src/libsyntax/feature_gate/builtin_attrs.rs @@ -286,7 +286,10 @@ macro_rules! experimental { ( sym::plugin_registrar, Normal, template!(Word), Gated( - Stability::Deprecated("https://github.com/rust-lang/rust/issues/29597", None), + Stability::Deprecated( + "https://github.com/rust-lang/rust/pull/64675", + Some("may be removed in a future compiler version"), + ), sym::plugin_registrar, "compiler plugins are deprecated", cfg_fn!(plugin_registrar) @@ -295,7 +298,10 @@ macro_rules! experimental { ( sym::plugin, CrateLevel, template!(List: "name|name(args)"), Gated( - Stability::Deprecated("https://github.com/rust-lang/rust/issues/29597", None), + Stability::Deprecated( + "https://github.com/rust-lang/rust/pull/64675", + Some("may be removed in a future compiler version"), + ), sym::plugin, "compiler plugins are deprecated", cfg_fn!(plugin) diff --git a/src/test/ui-fulldeps/gated-plugin.stderr b/src/test/ui-fulldeps/gated-plugin.stderr index aa031fb7a63d..aec1325844f2 100644 --- a/src/test/ui-fulldeps/gated-plugin.stderr +++ b/src/test/ui-fulldeps/gated-plugin.stderr @@ -7,11 +7,11 @@ LL | #![plugin(attr_plugin_test)] = note: for more information, see https://github.com/rust-lang/rust/issues/29597 = help: add `#![feature(plugin)]` to the crate attributes to enable -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/gated-plugin.rs:3:1 | LL | #![plugin(attr_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/issue-15778-fail.stderr b/src/test/ui-fulldeps/issue-15778-fail.stderr index 3afdb1fbf807..e76044c56ef9 100644 --- a/src/test/ui-fulldeps/issue-15778-fail.stderr +++ b/src/test/ui-fulldeps/issue-15778-fail.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/issue-15778-fail.rs:6:1 | LL | #![plugin(lint_for_crate)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/issue-15778-pass.stderr b/src/test/ui-fulldeps/issue-15778-pass.stderr index f81c314c23a2..0c30d2cdcbf1 100644 --- a/src/test/ui-fulldeps/issue-15778-pass.stderr +++ b/src/test/ui-fulldeps/issue-15778-pass.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/issue-15778-pass.rs:8:1 | LL | #![plugin(lint_for_crate_rpass)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/issue-40001.stderr b/src/test/ui-fulldeps/issue-40001.stderr index 186721e2bb9e..d0ad0275ed15 100644 --- a/src/test/ui-fulldeps/issue-40001.stderr +++ b/src/test/ui-fulldeps/issue-40001.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/issue-40001.rs:6:1 | LL | #![plugin(issue_40001_plugin)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-group-plugin-deny-cmdline.stderr b/src/test/ui-fulldeps/lint-group-plugin-deny-cmdline.stderr index 28065bf3946c..f8a4f271da5a 100644 --- a/src/test/ui-fulldeps/lint-group-plugin-deny-cmdline.stderr +++ b/src/test/ui-fulldeps/lint-group-plugin-deny-cmdline.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-group-plugin-deny-cmdline.rs:7:1 | LL | #![plugin(lint_group_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-group-plugin.stderr b/src/test/ui-fulldeps/lint-group-plugin.stderr index a93cae1a2b1e..58dc78b06d3f 100644 --- a/src/test/ui-fulldeps/lint-group-plugin.stderr +++ b/src/test/ui-fulldeps/lint-group-plugin.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-group-plugin.rs:6:1 | LL | #![plugin(lint_group_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr index 2185929e893b..c6d198dc458a 100644 --- a/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr +++ b/src/test/ui-fulldeps/lint-plugin-cmdline-allow.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-plugin-cmdline-allow.rs:8:1 | LL | #![plugin(lint_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-plugin-deny-attr.stderr b/src/test/ui-fulldeps/lint-plugin-deny-attr.stderr index a0cd9687f5bc..c611023e5490 100644 --- a/src/test/ui-fulldeps/lint-plugin-deny-attr.stderr +++ b/src/test/ui-fulldeps/lint-plugin-deny-attr.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-plugin-deny-attr.rs:5:1 | LL | #![plugin(lint_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-plugin-deny-cmdline.stderr b/src/test/ui-fulldeps/lint-plugin-deny-cmdline.stderr index 3c64025e5eb2..03668fbfe664 100644 --- a/src/test/ui-fulldeps/lint-plugin-deny-cmdline.stderr +++ b/src/test/ui-fulldeps/lint-plugin-deny-cmdline.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-plugin-deny-cmdline.rs:6:1 | LL | #![plugin(lint_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr index c0c43855c92a..c0de1feee7d4 100644 --- a/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr +++ b/src/test/ui-fulldeps/lint-plugin-forbid-attrs.stderr @@ -7,11 +7,11 @@ LL | #![forbid(test_lint)] LL | #[allow(test_lint)] | ^^^^^^^^^ overruled by previous forbid -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-plugin-forbid-attrs.rs:5:1 | LL | #![plugin(lint_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr index 99d013921911..f189efbf61d8 100644 --- a/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr +++ b/src/test/ui-fulldeps/lint-plugin-forbid-cmdline.stderr @@ -6,11 +6,11 @@ LL | #[allow(test_lint)] | = note: `forbid` lint level was set on command line -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-plugin-forbid-cmdline.rs:6:1 | LL | #![plugin(lint_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-plugin.stderr b/src/test/ui-fulldeps/lint-plugin.stderr index 2ca5eefe4376..e95650090dde 100644 --- a/src/test/ui-fulldeps/lint-plugin.stderr +++ b/src/test/ui-fulldeps/lint-plugin.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-plugin.rs:5:1 | LL | #![plugin(lint_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr index 71c3dc929b2e..239732521d59 100644 --- a/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr +++ b/src/test/ui-fulldeps/lint-tool-cmdline-allow.stderr @@ -2,11 +2,11 @@ warning: lint name `test_lint` is deprecated and does not have an effect anymore | = note: requested on the command line with `-A test_lint` -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-tool-cmdline-allow.rs:8:1 | LL | #![plugin(lint_tool_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lint-tool-test.stderr b/src/test/ui-fulldeps/lint-tool-test.stderr index c727cfc70154..d4031a780c3d 100644 --- a/src/test/ui-fulldeps/lint-tool-test.stderr +++ b/src/test/ui-fulldeps/lint-tool-test.stderr @@ -32,11 +32,11 @@ warning: lint name `test_lint` is deprecated and may not have an effect in the f LL | #![cfg_attr(foo, warn(test_lint))] | ^^^^^^^^^ help: change it to: `clippy::test_lint` -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lint-tool-test.rs:6:1 | LL | #![plugin(lint_tool_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/llvm-pass-plugin.stderr b/src/test/ui-fulldeps/llvm-pass-plugin.stderr index ebc092671a77..61b53bb2b7cd 100644 --- a/src/test/ui-fulldeps/llvm-pass-plugin.stderr +++ b/src/test/ui-fulldeps/llvm-pass-plugin.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/llvm-pass-plugin.rs:6:1 | LL | #![plugin(llvm_pass_plugin)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/lto-syntax-extension.stderr b/src/test/ui-fulldeps/lto-syntax-extension.stderr index 509331ceb218..529da32e10ee 100644 --- a/src/test/ui-fulldeps/lto-syntax-extension.stderr +++ b/src/test/ui-fulldeps/lto-syntax-extension.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/lto-syntax-extension.rs:9:1 | LL | #![plugin(lto_syntax_extension_plugin)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/macro-crate-rlib.stderr b/src/test/ui-fulldeps/macro-crate-rlib.stderr index 47d5ecb3742a..b5bd761f1b58 100644 --- a/src/test/ui-fulldeps/macro-crate-rlib.stderr +++ b/src/test/ui-fulldeps/macro-crate-rlib.stderr @@ -4,11 +4,11 @@ error[E0457]: plugin `rlib_crate_test` only found in rlib format, but must be av LL | #![plugin(rlib_crate_test)] | ^^^^^^^^^^^^^^^ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/macro-crate-rlib.rs:6:1 | LL | #![plugin(rlib_crate_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/outlive-expansion-phase.stderr b/src/test/ui-fulldeps/outlive-expansion-phase.stderr index 68e143d86eeb..d06fc480fb52 100644 --- a/src/test/ui-fulldeps/outlive-expansion-phase.stderr +++ b/src/test/ui-fulldeps/outlive-expansion-phase.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/outlive-expansion-phase.rs:6:1 | LL | #![plugin(outlive_expansion_phase)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/plugin-args-1.stderr b/src/test/ui-fulldeps/plugin-args-1.stderr index 0d01a859df8e..ca3e27069ed2 100644 --- a/src/test/ui-fulldeps/plugin-args-1.stderr +++ b/src/test/ui-fulldeps/plugin-args-1.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/plugin-args-1.rs:6:1 | LL | #![plugin(plugin_args)] - | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/plugin-args-2.stderr b/src/test/ui-fulldeps/plugin-args-2.stderr index 2bbabd201381..57c06513d5c0 100644 --- a/src/test/ui-fulldeps/plugin-args-2.stderr +++ b/src/test/ui-fulldeps/plugin-args-2.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/plugin-args-2.rs:6:1 | LL | #![plugin(plugin_args())] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/plugin-args-3.stderr b/src/test/ui-fulldeps/plugin-args-3.stderr index bf4108bd7f8d..179f1abc8c49 100644 --- a/src/test/ui-fulldeps/plugin-args-3.stderr +++ b/src/test/ui-fulldeps/plugin-args-3.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/plugin-args-3.rs:6:1 | LL | #![plugin(plugin_args(hello(there), how(are="you")))] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/plugin-attr-register-deny.stderr b/src/test/ui-fulldeps/plugin-attr-register-deny.stderr index a045782a95f7..8d95d6ff2d89 100644 --- a/src/test/ui-fulldeps/plugin-attr-register-deny.stderr +++ b/src/test/ui-fulldeps/plugin-attr-register-deny.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/plugin-attr-register-deny.rs:5:1 | LL | #![plugin(attr_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/plugin-reexport.stderr b/src/test/ui-fulldeps/plugin-reexport.stderr index 52d27c32897a..365b26d131e7 100644 --- a/src/test/ui-fulldeps/plugin-reexport.stderr +++ b/src/test/ui-fulldeps/plugin-reexport.stderr @@ -10,11 +10,11 @@ note: consider marking `mac` as `pub` in the imported module LL | pub use mac as reexport; | ^^^^^^^^^^^^^^^ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/plugin-reexport.rs:6:1 | LL | #![plugin(attr_plugin_test)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui-fulldeps/roman-numerals-macro.stderr b/src/test/ui-fulldeps/roman-numerals-macro.stderr index 7ac619185a1e..8f3f558e91df 100644 --- a/src/test/ui-fulldeps/roman-numerals-macro.stderr +++ b/src/test/ui-fulldeps/roman-numerals-macro.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/roman-numerals-macro.rs:6:1 | LL | #![plugin(roman_numerals)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr index 62a6d97dfe83..e78d9840abf7 100644 --- a/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr +++ b/src/test/ui/feature-gate/issue-43106-gating-of-builtin-attrs.stderr @@ -186,43 +186,43 @@ LL | mod inner { #![macro_escape] } | = help: consider an outer attribute, `#[macro_use]` mod ... -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:219:17 | LL | mod inner { #![plugin_registrar] } - | ^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:224:5 | LL | #[plugin_registrar] struct S; - | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:227:5 | LL | #[plugin_registrar] type T = S; - | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:230:5 | LL | #[plugin_registrar] impl S { } - | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:216:1 | LL | #[plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/issue-43106-gating-of-builtin-attrs.rs:40:1 | LL | #![plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version warning: use of deprecated attribute `crate_id`: no longer used. --> $DIR/issue-43106-gating-of-builtin-attrs.rs:90:1 diff --git a/src/test/ui/feature-gates/feature-gate-plugin.stderr b/src/test/ui/feature-gates/feature-gate-plugin.stderr index d1eee8cc5889..f89ddf995c49 100644 --- a/src/test/ui/feature-gates/feature-gate-plugin.stderr +++ b/src/test/ui/feature-gates/feature-gate-plugin.stderr @@ -7,11 +7,11 @@ LL | #![plugin(foo)] = note: for more information, see https://github.com/rust-lang/rust/issues/29597 = help: add `#![feature(plugin)]` to the crate attributes to enable -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/feature-gate-plugin.rs:3:1 | LL | #![plugin(foo)] - | ^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr b/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr index 1c4ccac1dcff..4856cf7c3f7d 100644 --- a/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr +++ b/src/test/ui/feature-gates/feature-gate-plugin_registrar.stderr @@ -16,11 +16,11 @@ LL | #[plugin_registrar] = note: for more information, see https://github.com/rust-lang/rust/issues/29597 = help: add `#![feature(plugin_registrar)]` to the crate attributes to enable -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/feature-gate-plugin_registrar.rs:5:1 | LL | #[plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui/invalid/invalid-plugin-attr.stderr b/src/test/ui/invalid/invalid-plugin-attr.stderr index d14a7524bf2d..0d7315dd887c 100644 --- a/src/test/ui/invalid/invalid-plugin-attr.stderr +++ b/src/test/ui/invalid/invalid-plugin-attr.stderr @@ -1,8 +1,8 @@ -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/invalid-plugin-attr.rs:4:1 | LL | #[plugin(bla)] - | ^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui/malformed/malformed-plugin-1.stderr b/src/test/ui/malformed/malformed-plugin-1.stderr index d8416c409542..3860864bd133 100644 --- a/src/test/ui/malformed/malformed-plugin-1.stderr +++ b/src/test/ui/malformed/malformed-plugin-1.stderr @@ -4,11 +4,11 @@ error: malformed `plugin` attribute input LL | #![plugin] | ^^^^^^^^^^ help: must be of the form: `#[plugin(name|name(args))]` -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/malformed-plugin-1.rs:2:1 | LL | #![plugin] - | ^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui/malformed/malformed-plugin-2.stderr b/src/test/ui/malformed/malformed-plugin-2.stderr index 34383ba08281..e4bca93f13b3 100644 --- a/src/test/ui/malformed/malformed-plugin-2.stderr +++ b/src/test/ui/malformed/malformed-plugin-2.stderr @@ -4,11 +4,11 @@ error: malformed `plugin` attribute input LL | #![plugin="bleh"] | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[plugin(name|name(args))]` -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/malformed-plugin-2.rs:2:1 | LL | #![plugin="bleh"] - | ^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui/malformed/malformed-plugin-3.stderr b/src/test/ui/malformed/malformed-plugin-3.stderr index 71f607d68a4a..7393072cb1ca 100644 --- a/src/test/ui/malformed/malformed-plugin-3.stderr +++ b/src/test/ui/malformed/malformed-plugin-3.stderr @@ -4,11 +4,11 @@ error[E0498]: malformed `plugin` attribute LL | #![plugin(foo="bleh")] | ^^^^^^^^^^^^^^^^^^^^^^ malformed attribute -warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/malformed-plugin-3.rs:2:1 | LL | #![plugin(foo="bleh")] - | ^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default diff --git a/src/test/ui/multiple-plugin-registrars.stderr b/src/test/ui/multiple-plugin-registrars.stderr index 3a7895a08c6e..dad8172e0c59 100644 --- a/src/test/ui/multiple-plugin-registrars.stderr +++ b/src/test/ui/multiple-plugin-registrars.stderr @@ -1,16 +1,16 @@ -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/multiple-plugin-registrars.rs:6:1 | LL | #[plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version | = note: `#[warn(deprecated)]` on by default -warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/issues/29597 +warning: use of deprecated attribute `plugin_registrar`: compiler plugins are deprecated. See https://github.com/rust-lang/rust/pull/64675 --> $DIR/multiple-plugin-registrars.rs:9:1 | LL | #[plugin_registrar] - | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | ^^^^^^^^^^^^^^^^^^^ help: may be removed in a future compiler version error: multiple plugin registration functions found | From 470e9d2789cf589b701594ce69b76bb530c67483 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 17 Oct 2019 19:37:05 +0200 Subject: [PATCH 487/545] Rc: value -> allocation --- src/liballoc/rc.rs | 95 +++++++++++++++++++++++++--------------------- 1 file changed, 51 insertions(+), 44 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index b0651f16484d..3178f5774eb6 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -3,8 +3,8 @@ //! //! The type [`Rc`][`Rc`] provides shared ownership of a value of type `T`, //! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new -//! pointer to the same value in the heap. When the last [`Rc`] pointer to a -//! given value is destroyed, the pointed-to value is also destroyed. +//! pointer to the same allocation in the heap. When the last [`Rc`] pointer to a +//! given allocation is destroyed, the pointed-to value is also destroyed. //! //! Shared references in Rust disallow mutation by default, and [`Rc`] //! is no exception: you cannot generally obtain a mutable reference to @@ -21,7 +21,7 @@ //! //! The [`downgrade`][downgrade] method can be used to create a non-owning //! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d -//! to an [`Rc`], but this will return [`None`] if the value has +//! to an [`Rc`], but this will return [`None`] if the allocation has //! already been dropped. //! //! A cycle between [`Rc`] pointers will never be deallocated. For this reason, @@ -41,7 +41,7 @@ //! Rc::downgrade(&my_rc); //! ``` //! -//! [`Weak`][`Weak`] does not auto-dereference to `T`, because the value may have +//! [`Weak`][`Weak`] does not auto-dereference to `T`, because the allocation may have //! already been destroyed. //! //! # Cloning references @@ -93,7 +93,7 @@ //! ); //! //! // Create `Gadget`s belonging to `gadget_owner`. Cloning the `Rc` -//! // value gives us a new pointer to the same `Owner` value, incrementing +//! // gives us a new pointer to the same `Owner` allocation, incrementing //! // the reference count in the process. //! let gadget1 = Gadget { //! id: 1, @@ -110,7 +110,7 @@ //! // Despite dropping `gadget_owner`, we're still able to print out the name //! // of the `Owner` of the `Gadget`s. This is because we've only dropped a //! // single `Rc`, not the `Owner` it points to. As long as there are -//! // other `Rc` values pointing at the same `Owner`, it will remain +//! // other `Rc` pointing at the same `Owner`, it will remain //! // allocated. The field projection `gadget1.owner.name` works because //! // `Rc` automatically dereferences to `Owner`. //! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); @@ -124,9 +124,9 @@ //! //! If our requirements change, and we also need to be able to traverse from //! `Owner` to `Gadget`, we will run into problems. An [`Rc`] pointer from `Owner` -//! to `Gadget` introduces a cycle between the values. This means that their -//! reference counts can never reach 0, and the values will remain allocated -//! forever: a memory leak. In order to get around this, we can use [`Weak`] +//! to `Gadget` introduces a cycle. This means that their +//! reference counts can never reach 0, and the allocation will never be destroyed: +//! a memory leak. In order to get around this, we can use [`Weak`] //! pointers. //! //! Rust actually makes it somewhat difficult to produce this loop in the first @@ -193,10 +193,10 @@ //! for gadget_weak in gadget_owner.gadgets.borrow().iter() { //! //! // `gadget_weak` is a `Weak`. Since `Weak` pointers can't -//! // guarantee the value is still allocated, we need to call +//! // guarantee the allocation still exists, we need to call //! // `upgrade`, which returns an `Option>`. //! // -//! // In this case we know the value still exists, so we simply +//! // In this case we know the allocation still exists, so we simply //! // `unwrap` the `Option`. In a more complicated program, you might //! // need graceful error handling for a `None` result. //! @@ -604,7 +604,7 @@ pub fn into_raw_non_null(this: Self) -> NonNull { unsafe { NonNull::new_unchecked(Rc::into_raw(this) as *mut _) } } - /// Creates a new [`Weak`][weak] pointer to this value. + /// Creates a new [`Weak`][weak] pointer to this allocation. /// /// [weak]: struct.Weak.html /// @@ -625,7 +625,7 @@ pub fn downgrade(this: &Self) -> Weak { Weak { ptr: this.ptr } } - /// Gets the number of [`Weak`][weak] pointers to this value. + /// Gets the number of [`Weak`][weak] pointers to this allocation. /// /// [weak]: struct.Weak.html /// @@ -645,7 +645,7 @@ pub fn weak_count(this: &Self) -> usize { this.weak() - 1 } - /// Gets the number of strong (`Rc`) pointers to this value. + /// Gets the number of strong (`Rc`) pointers to this allocation. /// /// # Examples /// @@ -664,7 +664,7 @@ pub fn strong_count(this: &Self) -> usize { } /// Returns `true` if there are no other `Rc` or [`Weak`][weak] pointers to - /// this inner value. + /// this allocation. /// /// [weak]: struct.Weak.html #[inline] @@ -672,8 +672,8 @@ fn is_unique(this: &Self) -> bool { Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1 } - /// Returns a mutable reference to the inner value, if there are - /// no other `Rc` or [`Weak`][weak] pointers to the same value. + /// Returns a mutable reference into the given `Rc`, if there are + /// no other `Rc` or [`Weak`][weak] pointers to the same allocation. /// /// Returns [`None`] otherwise, because it is not safe to /// mutate a shared value. @@ -710,7 +710,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> { } } - /// Returns a mutable reference to the inner value, + /// Returns a mutable reference into the given `Rc`, /// without any check. /// /// See also [`get_mut`], which is safe and does appropriate checks. @@ -719,7 +719,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> { /// /// # Safety /// - /// Any other `Rc` or [`Weak`] pointers to the same value must not be dereferenced + /// Any other `Rc` or [`Weak`] pointers to the same allocation must not be dereferenced /// for the duration of the returned borrow. /// This is trivially the case if no such pointers exist, /// for example immediately after `Rc::new`. @@ -745,8 +745,8 @@ pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] - /// Returns `true` if the two `Rc`s point to the same value (not - /// just values that compare as equal). + /// Returns `true` if the two `Rc`s point to the same allocation + /// (in a vein similar to [`ptr::eq`]). /// /// # Examples /// @@ -760,6 +760,8 @@ pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { /// assert!(Rc::ptr_eq(&five, &same_five)); /// assert!(!Rc::ptr_eq(&five, &other_five)); /// ``` + /// + /// [`ptr::eq`]: ../../std/ptr/fn.eq.html pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.ptr.as_ptr() == other.ptr.as_ptr() } @@ -768,12 +770,12 @@ pub fn ptr_eq(this: &Self, other: &Self) -> bool { impl Rc { /// Makes a mutable reference into the given `Rc`. /// - /// If there are other `Rc` pointers to the same value, then `make_mut` will - /// [`clone`] the inner value to ensure unique ownership. This is also + /// If there are other `Rc` pointers to the same allocation, then `make_mut` will + /// [`clone`] the inner value to a new allocation to ensure unique ownership. This is also /// referred to as clone-on-write. /// - /// If there are no other `Rc` pointers to this value, then [`Weak`] - /// pointers to this value will be disassociated. + /// If there are no other `Rc` pointers to this allocation, then [`Weak`] + /// pointers to this allocation will be disassociated. /// /// See also [`get_mut`], which will fail rather than cloning. /// @@ -794,7 +796,7 @@ impl Rc { /// *Rc::make_mut(&mut data) += 1; // Won't clone anything /// *Rc::make_mut(&mut other_data) *= 2; // Won't clone anything /// - /// // Now `data` and `other_data` point to different values. + /// // Now `data` and `other_data` point to different allocations. /// assert_eq!(*data, 8); /// assert_eq!(*other_data, 12); /// ``` @@ -837,7 +839,7 @@ pub fn make_mut(this: &mut Self) -> &mut T { // returned is the *only* pointer that will ever be returned to T. Our // reference count is guaranteed to be 1 at this point, and we required // the `Rc` itself to be `mut`, so we're returning the only possible - // reference to the inner value. + // reference to the allocation. unsafe { &mut this.ptr.as_mut().value } @@ -1111,7 +1113,7 @@ fn drop(&mut self) { impl Clone for Rc { /// Makes a clone of the `Rc` pointer. /// - /// This creates another pointer to the same inner value, increasing the + /// This creates another pointer to the same allocation, increasing the /// strong reference count. /// /// # Examples @@ -1189,9 +1191,11 @@ fn ne(&self, other: &Rc) -> bool { impl PartialEq for Rc { /// Equality for two `Rc`s. /// - /// Two `Rc`s are equal if their inner values are equal. + /// Two `Rc`s are equal if their inner values are equal, even if they are + /// stored in different allocation. /// - /// If `T` also implements `Eq`, two `Rc`s that point to the same value are + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Rc`s that point to the same allocation are /// always equal. /// /// # Examples @@ -1212,7 +1216,8 @@ fn eq(&self, other: &Rc) -> bool { /// /// Two `Rc`s are unequal if their inner values are unequal. /// - /// If `T` also implements `Eq`, two `Rc`s that point to the same value are + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Rc`s that point to the same allocation are /// never unequal. /// /// # Examples @@ -1541,16 +1546,16 @@ fn from_iter(iter: slice::Iter<'a, T>) -> Self { } /// `Weak` is a version of [`Rc`] that holds a non-owning reference to the -/// managed value. The value is accessed by calling [`upgrade`] on the `Weak` +/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [`Option`]`<`[`Rc`]`>`. /// /// Since a `Weak` reference does not count towards ownership, it will not -/// prevent the inner value from being dropped, and `Weak` itself makes no +/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no /// guarantees about the value still being present and may return [`None`] /// when [`upgrade`]d. /// -/// A `Weak` pointer is useful for keeping a temporary reference to the value -/// within [`Rc`] without extending its lifetime. It is also used to prevent +/// A `Weak` pointer is useful for keeping a temporary reference to the allocation +/// managed by [`Rc`] without extending its lifetime. It is also used to prevent /// circular references between [`Rc`] pointers, since mutual owning references /// would never allow either [`Rc`] to be dropped. For example, a tree could /// have strong [`Rc`] pointers from parent nodes to children, and `Weak` @@ -1751,9 +1756,9 @@ pub(crate) fn is_dangling(ptr: NonNull) -> bool { impl Weak { /// Attempts to upgrade the `Weak` pointer to an [`Rc`], extending - /// the lifetime of the value if successful. + /// the lifetime of the allocation if successful. /// - /// Returns [`None`] if the value has since been dropped. + /// Returns [`None`] if the value stored in the allocation has since been dropped. /// /// [`Rc`]: struct.Rc.html /// [`None`]: ../../std/option/enum.Option.html @@ -1787,7 +1792,7 @@ pub fn upgrade(&self) -> Option> { } } - /// Gets the number of strong (`Rc`) pointers pointing to this value. + /// Gets the number of strong (`Rc`) pointers pointing to this allocation. /// /// If `self` was created using [`Weak::new`], this will return 0. /// @@ -1801,11 +1806,11 @@ pub fn strong_count(&self) -> usize { } } - /// Gets the number of `Weak` pointers pointing to this value. + /// Gets the number of `Weak` pointers pointing to this allocation. /// /// If `self` was created using [`Weak::new`], this will return `None`. If /// not, the returned value is at least 1, since `self` still points to the - /// value. + /// allocation. /// /// [`Weak::new`]: #method.new #[unstable(feature = "weak_counts", issue = "57977")] @@ -1830,14 +1835,14 @@ fn inner(&self) -> Option<&RcBox> { } } - /// Returns `true` if the two `Weak`s point to the same value (not just - /// values that compare as equal), or if both don't point to any value + /// Returns `true` if the two `Weak`s point to the same allocation (similar to + /// [`ptr::eq`]), or if both don't point to any allocation /// (because they were created with `Weak::new()`). /// /// # Notes /// /// Since this compares pointers it means that `Weak::new()` will equal each - /// other, even though they don't point to any value. + /// other, even though they don't point to any allocation. /// /// # Examples /// @@ -1869,6 +1874,8 @@ fn inner(&self) -> Option<&RcBox> { /// let third = Rc::downgrade(&third_rc); /// assert!(!first.ptr_eq(&third)); /// ``` + /// + /// [`ptr::eq`]: ../../std/ptr/fn.eq.html #[inline] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { @@ -1918,7 +1925,7 @@ fn drop(&mut self) { #[stable(feature = "rc_weak", since = "1.4.0")] impl Clone for Weak { - /// Makes a clone of the `Weak` pointer that points to the same value. + /// Makes a clone of the `Weak` pointer that points to the same allocation. /// /// # Examples /// From 868a77263a6e140401946b4a0fca72b41315c3df Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 17 Oct 2019 19:51:42 +0200 Subject: [PATCH 488/545] more consistency and clarification --- src/liballoc/rc.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 3178f5774eb6..1cab8026514e 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -4,7 +4,8 @@ //! The type [`Rc`][`Rc`] provides shared ownership of a value of type `T`, //! allocated in the heap. Invoking [`clone`][clone] on [`Rc`] produces a new //! pointer to the same allocation in the heap. When the last [`Rc`] pointer to a -//! given allocation is destroyed, the pointed-to value is also destroyed. +//! given allocation is destroyed, the value stored in that allocation (often +//! referred to as "inner value") is also dropped. //! //! Shared references in Rust disallow mutation by default, and [`Rc`] //! is no exception: you cannot generally obtain a mutable reference to @@ -21,8 +22,10 @@ //! //! The [`downgrade`][downgrade] method can be used to create a non-owning //! [`Weak`] pointer. A [`Weak`] pointer can be [`upgrade`][upgrade]d -//! to an [`Rc`], but this will return [`None`] if the allocation has -//! already been dropped. +//! to an [`Rc`], but this will return [`None`] if the value stored in the allocation has +//! already been dropped. In other words, `Weak` pointers do not keep the value +//! inside the allocation alive; however, they *do* keep the allocation +//! (the backing store for the value) alive. //! //! A cycle between [`Rc`] pointers will never be deallocated. For this reason, //! [`Weak`] is used to break cycles. For example, a tree could have strong @@ -46,8 +49,8 @@ //! //! # Cloning references //! -//! Creating a new reference from an existing reference counted pointer is done using the -//! `Clone` trait implemented for [`Rc`][`Rc`] and [`Weak`][`Weak`]. +//! Creating a new reference to the same allocation as an existing reference counted pointer +//! is done using the `Clone` trait implemented for [`Rc`][`Rc`] and [`Weak`][`Weak`]. //! //! ``` //! use std::rc::Rc; @@ -109,8 +112,8 @@ //! //! // Despite dropping `gadget_owner`, we're still able to print out the name //! // of the `Owner` of the `Gadget`s. This is because we've only dropped a -//! // single `Rc`, not the `Owner` it points to. As long as there are -//! // other `Rc` pointing at the same `Owner`, it will remain +//! // single `Rc`, not the `Owner` allocation it points to. As long as there are +//! // other `Rc` pointing at the same `Owner` allocation, it will remain //! // allocated. The field projection `gadget1.owner.name` works because //! // `Rc` automatically dereferences to `Owner`. //! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); @@ -365,7 +368,7 @@ pub fn pin(value: T) -> Pin> { unsafe { Pin::new_unchecked(Rc::new(value)) } } - /// Returns the contained value, if the `Rc` has exactly one strong reference. + /// Returns the inner value, if the `Rc` has exactly one strong reference. /// /// Otherwise, an [`Err`][result] is returned with the same `Rc` that was /// passed in. @@ -679,7 +682,7 @@ fn is_unique(this: &Self) -> bool { /// mutate a shared value. /// /// See also [`make_mut`][make_mut], which will [`clone`][clone] - /// the inner value when it's shared. + /// the inner value when there are other pointers. /// /// [weak]: struct.Weak.html /// [`None`]: ../../std/option/enum.Option.html#variant.None @@ -1551,12 +1554,13 @@ fn from_iter(iter: slice::Iter<'a, T>) -> Self { /// /// Since a `Weak` reference does not count towards ownership, it will not /// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no -/// guarantees about the value still being present and may return [`None`] -/// when [`upgrade`]d. +/// guarantees about the value still being present. Thus it may return [`None`] +/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation +/// itself (the backing store) from being deallocated. /// /// A `Weak` pointer is useful for keeping a temporary reference to the allocation -/// managed by [`Rc`] without extending its lifetime. It is also used to prevent -/// circular references between [`Rc`] pointers, since mutual owning references +/// managed by [`Rc`] without preventing its inner value from being dropped. It is also used to +/// prevent circular references between [`Rc`] pointers, since mutual owning references /// would never allow either [`Rc`] to be dropped. For example, a tree could /// have strong [`Rc`] pointers from parent nodes to children, and `Weak` /// pointers from children back to their parents. From a4d94925c737b1fee1dc8e90225a71b47ed77042 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 17 Oct 2019 14:15:59 -0400 Subject: [PATCH 489/545] add option to ping llvm ice-breakers to triagebot --- triagebot.toml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index d87c5b64c21c..b39c95f68361 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -8,3 +8,14 @@ allow-unauthenticated = [ ] [assign] + +[ping.icebreaker-llvm] +message = """\ +Hey LLVM ICE-breakers! This bug has been identified as a good +"LLVM ICE-breaking candidate". In case it's useful, here are some +[instructions] for tackling these sorts of bugs. Maybe take a look? +Thanks! <3 + +[instructions]: https://rust-lang.github.io/rustc-guide/ice-breaker/llvm.html +""" +label = "ICEBreaker-LLVM" From 5fe88abed06b3efc8627d726c18dbc48d9d653b3 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 17 Oct 2019 20:48:00 +0200 Subject: [PATCH 490/545] save-analysis: Nest tables when processing impl items --- src/librustc_save_analysis/dump_visitor.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 502ae337b527..e282936b5d9e 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -669,15 +669,18 @@ fn process_impl( } } } - self.visit_ty(&typ); - if let &Some(ref trait_ref) = trait_ref { - self.process_path(trait_ref.ref_id, &trait_ref.path); - } - self.process_generic_params(generics, "", item.id); - for impl_item in impl_items { - let map = &self.tcx.hir(); - self.process_impl_item(impl_item, map.local_def_id_from_node_id(item.id)); - } + + let map = &self.tcx.hir(); + self.nest_tables(item.id, |v| { + v.visit_ty(&typ); + if let &Some(ref trait_ref) = trait_ref { + v.process_path(trait_ref.ref_id, &trait_ref.path); + } + v.process_generic_params(generics, "", item.id); + for impl_item in impl_items { + v.process_impl_item(impl_item, map.local_def_id_from_node_id(item.id)); + } + }); } fn process_trait( From ad6ce4698641f57133ea75c379a928c6017b08cf Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Thu, 17 Oct 2019 20:49:06 +0200 Subject: [PATCH 491/545] save-analysis: Add a relevant test case --- src/test/ui/save-analysis/issue-65411.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/ui/save-analysis/issue-65411.rs diff --git a/src/test/ui/save-analysis/issue-65411.rs b/src/test/ui/save-analysis/issue-65411.rs new file mode 100644 index 000000000000..9e58b8da5d27 --- /dev/null +++ b/src/test/ui/save-analysis/issue-65411.rs @@ -0,0 +1,15 @@ +// check-pass +// compile-flags: -Zsave-analysis + +trait Trait { type Assoc; } +trait GenericTrait {} +struct Wrapper { b: B } + +fn func() { + // Processing associated path in impl block definition inside a function + // body does not ICE + impl GenericTrait for Wrapper {} +} + + +fn main() {} From 4e6efe48110a5e09ee87b0aa8cea31d511bb5708 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 17 Oct 2019 21:22:46 +0200 Subject: [PATCH 492/545] reorder fmt docs for more clarity --- src/liballoc/fmt.rs | 103 ++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 42 deletions(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 1e39b7f822e9..4d3523da7fc0 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -86,18 +86,53 @@ //! parameters (corresponding to `format_spec` in the syntax above). These //! parameters affect the string representation of what's being formatted. //! +//! ## Width +//! +//! ``` +//! // All of these print "Hello x !" +//! println!("Hello {:5}!", "x"); +//! println!("Hello {:1$}!", "x", 5); +//! println!("Hello {1:0$}!", 5, "x"); +//! println!("Hello {:width$}!", "x", width = 5); +//! ``` +//! +//! This is a parameter for the "minimum width" that the format should take up. +//! If the value's string does not fill up this many characters, then the +//! padding specified by fill/alignment will be used to take up the required +//! space (see below). +//! +//! The value for the width can also be provided as a [`usize`] in the list of +//! parameters by adding a postfix `$`, indicating that the second argument is +//! a [`usize`] specifying the width. +//! +//! Referring to an argument with the dollar syntax does not affect the "next +//! argument" counter, so it's usually a good idea to refer to arguments by +//! position, or use named arguments. +//! //! ## Fill/Alignment //! -//! The fill character is provided normally in conjunction with the -//! [`width`](#width) -//! parameter. This indicates that if the value being formatted is smaller than -//! `width` some extra characters will be printed around it. The extra -//! characters are specified by `fill`, and the alignment can be one of the -//! following options: +//! ``` +//! assert_eq!(format!("Hello {:<5}!", "x"), "Hello x !"); +//! assert_eq!(format!("Hello {:-<5}!", "x"), "Hello x----!"); +//! assert_eq!(format!("Hello {:^5}!", "x"), "Hello x !"); +//! assert_eq!(format!("Hello {:>5}!", "x"), "Hello x!"); +//! ``` //! -//! * `<` - the argument is left-aligned in `width` columns -//! * `^` - the argument is center-aligned in `width` columns -//! * `>` - the argument is right-aligned in `width` columns +//! The optional fill character and alignment is provided normally in conjunction with the +//! [`width`](#width) parameter. It must be defined before `width`, right after the `:`. +//! This indicates that if the value being formatted is smaller than +//! `width` some extra characters will be printed around it. +//! Filling comes in the following variants for different alignments: +//! +//! * `[fill]<` - the argument is left-aligned in `width` columns +//! * `[fill]^` - the argument is center-aligned in `width` columns +//! * `[fill]>` - the argument is right-aligned in `width` columns +//! +//! The default [fill/alignment](#fillalignment) for non-numerics is a space and +//! left-aligned. The +//! defaults for numeric formatters is also a space but with right-alignment. If +//! the `0` flag (see below) is specified for numerics, then the implicit fill character is +//! `0`. //! //! Note that alignment may not be implemented by some types. In particular, it //! is not generally implemented for the `Debug` trait. A good way to ensure @@ -106,7 +141,15 @@ //! //! ## Sign/`#`/`0` //! -//! These can all be interpreted as flags for a particular formatter. +//! ``` +//! assert_eq!(format!("Hello {:+}!", 5), "Hello +5!"); +//! assert_eq!(format!("{:#x}!", 27), "0x1b!"); +//! assert_eq!(format!("Hello {:05}!", 5), "Hello 00005!"); +//! assert_eq!(format!("Hello {:05}!", -5), "Hello -0005!"); +//! assert_eq!(format!("{:#010x}!", 27), "0x0000001b!"); +//! ``` +//! +//! These are all flags altering the behavior of the formatter. //! //! * `+` - This is intended for numeric types and indicates that the sign //! should always be printed. Positive signs are never printed by @@ -121,7 +164,7 @@ //! * `#X` - precedes the argument with a `0x` //! * `#b` - precedes the argument with a `0b` //! * `#o` - precedes the argument with a `0o` -//! * `0` - This is used to indicate for integer formats that the padding should +//! * `0` - This is used to indicate for integer formats that the padding to `width` should //! both be done with a `0` character as well as be sign-aware. A format //! like `{:08}` would yield `00000001` for the integer `1`, while the //! same format would yield `-0000001` for the integer `-1`. Notice that @@ -129,36 +172,7 @@ //! Note that padding zeroes are always placed after the sign (if any) //! and before the digits. When used together with the `#` flag, a similar //! rule applies: padding zeroes are inserted after the prefix but before -//! the digits. -//! -//! ## Width -//! -//! This is a parameter for the "minimum width" that the format should take up. -//! If the value's string does not fill up this many characters, then the -//! padding specified by fill/alignment will be used to take up the required -//! space. -//! -//! The default [fill/alignment](#fillalignment) for non-numerics is a space and -//! left-aligned. The -//! defaults for numeric formatters is also a space but with right-alignment. If -//! the `0` flag is specified for numerics, then the implicit fill character is -//! `0`. -//! -//! The value for the width can also be provided as a [`usize`] in the list of -//! parameters by using the dollar syntax indicating that the second argument is -//! a [`usize`] specifying the width, for example: -//! -//! ``` -//! // All of these print "Hello x !" -//! println!("Hello {:5}!", "x"); -//! println!("Hello {:1$}!", "x", 5); -//! println!("Hello {1:0$}!", 5, "x"); -//! println!("Hello {:width$}!", "x", width = 5); -//! ``` -//! -//! Referring to an argument with the dollar syntax does not affect the "next -//! argument" counter, so it's usually a good idea to refer to arguments by -//! position, or use named arguments. +//! the digits. The prefix is included in the total width. //! //! ## Precision //! @@ -235,9 +249,14 @@ //! them with the same character. For example, the `{` character is escaped with //! `{{` and the `}` character is escaped with `}}`. //! +//! ``` +//! assert_eq!(format!("Hello {{}}"), "Hello {}"); +//! assert_eq!(format!("{{ Hello"), "{ Hello"); +//! ``` +//! //! # Syntax //! -//! To summarize, you can find the full grammar of format strings. +//! To summarize, here 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 From 54879949f18ed44dc4db4b9c450d6c09551a2e0d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 17 Oct 2019 16:53:47 -0400 Subject: [PATCH 493/545] Update triagebot.toml Co-Authored-By: Mark Rousskov --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index b39c95f68361..f0e3a99037b0 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -9,7 +9,7 @@ allow-unauthenticated = [ [assign] -[ping.icebreaker-llvm] +[ping.icebreakers-llvm] message = """\ Hey LLVM ICE-breakers! This bug has been identified as a good "LLVM ICE-breaking candidate". In case it's useful, here are some From c0b7e769a0f76a76fc5d239d886e5b8a69648b10 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 17 Oct 2019 23:00:46 +0200 Subject: [PATCH 494/545] example for padding any format --- src/liballoc/fmt.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index 4d3523da7fc0..cbfc55233a1e 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -136,8 +136,12 @@ //! //! Note that alignment may not be implemented by some types. In particular, it //! is not generally implemented for the `Debug` trait. A good way to ensure -//! padding is applied is to format your input, then use this resulting string -//! to pad your output. +//! padding is applied is to format your input, then pad this resulting string +//! to obtain your output: +//! +//! ``` +//! println!("Hello {:^15}!", format!("{:?}", Some("hi"))); // => "Hello Some("hi") !" +//! ``` //! //! ## Sign/`#`/`0` //! From 56974329d1eab8dd990d53b6cd6978bbf6a615b7 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Wed, 9 Oct 2019 01:07:57 +0200 Subject: [PATCH 495/545] BTreeSet symmetric_difference & union optimized, cleaned --- src/liballoc/collections/btree/set.rs | 239 +++++++++++++------------- src/liballoc/tests/btree/set.rs | 26 ++- 2 files changed, 144 insertions(+), 121 deletions(-) diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs index 8250fc38ccd1..f0796354e00c 100644 --- a/src/liballoc/collections/btree/set.rs +++ b/src/liballoc/collections/btree/set.rs @@ -2,7 +2,7 @@ // to TreeMap use core::borrow::Borrow; -use core::cmp::Ordering::{self, Less, Greater, Equal}; +use core::cmp::Ordering::{Less, Greater, Equal}; use core::cmp::{max, min}; use core::fmt::{self, Debug}; use core::iter::{Peekable, FromIterator, FusedIterator}; @@ -109,6 +109,77 @@ pub struct Range<'a, T: 'a> { iter: btree_map::Range<'a, T, ()>, } +/// Core of SymmetricDifference and Union. +/// More efficient than btree.map.MergeIter, +/// and crucially for SymmetricDifference, nexts() reports on both sides. +#[derive(Clone)] +struct MergeIterInner + where I: Iterator, + I::Item: Copy, +{ + a: I, + b: I, + peeked: Option>, +} + +#[derive(Copy, Clone, Debug)] +enum MergeIterPeeked { + A(I::Item), + B(I::Item), +} + +impl MergeIterInner + where I: ExactSizeIterator + FusedIterator, + I::Item: Copy + Ord, +{ + fn new(a: I, b: I) -> Self { + MergeIterInner { a, b, peeked: None } + } + + fn nexts(&mut self) -> (Option, Option) { + let mut a_next = match self.peeked { + Some(MergeIterPeeked::A(next)) => Some(next), + _ => self.a.next(), + }; + let mut b_next = match self.peeked { + Some(MergeIterPeeked::B(next)) => Some(next), + _ => self.b.next(), + }; + let ord = match (a_next, b_next) { + (None, None) => Equal, + (_, None) => Less, + (None, _) => Greater, + (Some(a1), Some(b1)) => a1.cmp(&b1), + }; + self.peeked = match ord { + Less => b_next.take().map(MergeIterPeeked::B), + Equal => None, + Greater => a_next.take().map(MergeIterPeeked::A), + }; + (a_next, b_next) + } + + fn lens(&self) -> (usize, usize) { + match self.peeked { + Some(MergeIterPeeked::A(_)) => (1 + self.a.len(), self.b.len()), + Some(MergeIterPeeked::B(_)) => (self.a.len(), 1 + self.b.len()), + _ => (self.a.len(), self.b.len()), + } + } +} + +impl Debug for MergeIterInner + where I: Iterator + Debug, + I::Item: Copy + Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("MergeIterInner") + .field(&self.a) + .field(&self.b) + .finish() + } +} + /// A lazy iterator producing elements in the difference of `BTreeSet`s. /// /// This `struct` is created by the [`difference`] method on [`BTreeSet`]. @@ -120,6 +191,7 @@ pub struct Range<'a, T: 'a> { pub struct Difference<'a, T: 'a> { inner: DifferenceInner<'a, T>, } +#[derive(Debug)] enum DifferenceInner<'a, T: 'a> { Stitch { // iterate all of self and some of other, spotting matches along the way @@ -137,21 +209,7 @@ enum DifferenceInner<'a, T: 'a> { #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Difference<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.inner { - DifferenceInner::Stitch { - self_iter, - other_iter, - } => f - .debug_tuple("Difference") - .field(&self_iter) - .field(&other_iter) - .finish(), - DifferenceInner::Search { - self_iter, - other_set: _, - } => f.debug_tuple("Difference").field(&self_iter).finish(), - DifferenceInner::Iterate(iter) => f.debug_tuple("Difference").field(&iter).finish(), - } + f.debug_tuple("Difference").field(&self.inner).finish() } } @@ -163,18 +221,12 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// [`BTreeSet`]: struct.BTreeSet.html /// [`symmetric_difference`]: struct.BTreeSet.html#method.symmetric_difference #[stable(feature = "rust1", since = "1.0.0")] -pub struct SymmetricDifference<'a, T: 'a> { - a: Peekable>, - b: Peekable>, -} +pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner>); #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for SymmetricDifference<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("SymmetricDifference") - .field(&self.a) - .field(&self.b) - .finish() + f.debug_tuple("SymmetricDifference").field(&self.0).finish() } } @@ -189,6 +241,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { pub struct Intersection<'a, T: 'a> { inner: IntersectionInner<'a, T>, } +#[derive(Debug)] enum IntersectionInner<'a, T: 'a> { Stitch { // iterate similarly sized sets jointly, spotting matches along the way @@ -206,23 +259,7 @@ enum IntersectionInner<'a, T: 'a> { #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Intersection<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match &self.inner { - IntersectionInner::Stitch { - a, - b, - } => f - .debug_tuple("Intersection") - .field(&a) - .field(&b) - .finish(), - IntersectionInner::Search { - small_iter, - large_set: _, - } => f.debug_tuple("Intersection").field(&small_iter).finish(), - IntersectionInner::Answer(answer) => { - f.debug_tuple("Intersection").field(&answer).finish() - } - } + f.debug_tuple("Intersection").field(&self.inner).finish() } } @@ -234,18 +271,12 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// [`BTreeSet`]: struct.BTreeSet.html /// [`union`]: struct.BTreeSet.html#method.union #[stable(feature = "rust1", since = "1.0.0")] -pub struct Union<'a, T: 'a> { - a: Peekable>, - b: Peekable>, -} +pub struct Union<'a, T: 'a>(MergeIterInner>); #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Union<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Union") - .field(&self.a) - .field(&self.b) - .finish() + f.debug_tuple("Union").field(&self.0).finish() } } @@ -355,19 +386,16 @@ pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> { self_iter.next_back(); DifferenceInner::Iterate(self_iter) } - _ => { - if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { - DifferenceInner::Search { - self_iter: self.iter(), - other_set: other, - } - } else { - DifferenceInner::Stitch { - self_iter: self.iter(), - other_iter: other.iter().peekable(), - } + _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + DifferenceInner::Search { + self_iter: self.iter(), + other_set: other, } } + _ => DifferenceInner::Stitch { + self_iter: self.iter(), + other_iter: other.iter().peekable(), + }, }, } } @@ -396,10 +424,7 @@ pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T> { pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet) -> SymmetricDifference<'a, T> { - SymmetricDifference { - a: self.iter().peekable(), - b: other.iter().peekable(), - } + SymmetricDifference(MergeIterInner::new(self.iter(), other.iter())) } /// Visits the values representing the intersection, @@ -447,24 +472,22 @@ pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T> (Greater, _) | (_, Less) => IntersectionInner::Answer(None), (Equal, _) => IntersectionInner::Answer(Some(self_min)), (_, Equal) => IntersectionInner::Answer(Some(self_max)), - _ => { - if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { - IntersectionInner::Search { - small_iter: self.iter(), - large_set: other, - } - } else if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { - IntersectionInner::Search { - small_iter: other.iter(), - large_set: self, - } - } else { - IntersectionInner::Stitch { - a: self.iter(), - b: other.iter(), - } + _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + IntersectionInner::Search { + small_iter: self.iter(), + large_set: other, } } + _ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + IntersectionInner::Search { + small_iter: other.iter(), + large_set: self, + } + } + _ => IntersectionInner::Stitch { + a: self.iter(), + b: other.iter(), + }, }, } } @@ -489,10 +512,7 @@ pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T> /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T> { - Union { - a: self.iter().peekable(), - b: other.iter().peekable(), - } + Union(MergeIterInner::new(self.iter(), other.iter())) } /// Clears the set, removing all values. @@ -1166,15 +1186,6 @@ fn next_back(&mut self) -> Option<&'a T> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Range<'_, T> {} -/// Compares `x` and `y`, but return `short` if x is None and `long` if y is None -fn cmp_opt(x: Option<&T>, y: Option<&T>, short: Ordering, long: Ordering) -> Ordering { - match (x, y) { - (None, _) => short, - (_, None) => long, - (Some(x1), Some(y1)) => x1.cmp(y1), - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Difference<'_, T> { fn clone(&self) -> Self { @@ -1261,10 +1272,7 @@ impl FusedIterator for Difference<'_, T> {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for SymmetricDifference<'_, T> { fn clone(&self) -> Self { - SymmetricDifference { - a: self.a.clone(), - b: self.b.clone(), - } + SymmetricDifference(self.0.clone()) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1273,19 +1281,19 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { fn next(&mut self) -> Option<&'a T> { loop { - match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { - Less => return self.a.next(), - Equal => { - self.a.next(); - self.b.next(); - } - Greater => return self.b.next(), + let (a_next, b_next) = self.0.nexts(); + if a_next.and(b_next).is_none() { + return a_next.or(b_next); } } } fn size_hint(&self) -> (usize, Option) { - (0, Some(self.a.len() + self.b.len())) + let (a_len, b_len) = self.0.lens(); + // No checked_add, because even if a and b refer to the same set, + // and T is an empty type, the storage overhead of sets limits + // the number of elements to less than half the range of usize. + (0, Some(a_len + b_len)) } } @@ -1311,7 +1319,7 @@ fn clone(&self) -> Self { small_iter: small_iter.clone(), large_set, }, - IntersectionInner::Answer(answer) => IntersectionInner::Answer(answer.clone()), + IntersectionInner::Answer(answer) => IntersectionInner::Answer(*answer), }, } } @@ -1365,10 +1373,7 @@ impl FusedIterator for Intersection<'_, T> {} #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Union<'_, T> { fn clone(&self) -> Self { - Union { - a: self.a.clone(), - b: self.b.clone(), - } + Union(self.0.clone()) } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1376,19 +1381,13 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { type Item = &'a T; fn next(&mut self) -> Option<&'a T> { - match cmp_opt(self.a.peek(), self.b.peek(), Greater, Less) { - Less => self.a.next(), - Equal => { - self.b.next(); - self.a.next() - } - Greater => self.b.next(), - } + let (a_next, b_next) = self.0.nexts(); + a_next.or(b_next) } fn size_hint(&self) -> (usize, Option) { - let a_len = self.a.len(); - let b_len = self.b.len(); + let (a_len, b_len) = self.0.lens(); + // No checked_add - see SymmetricDifference::size_hint. (max(a_len, b_len), Some(a_len + b_len)) } } diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index 5c611fd21d21..e4883abc8b56 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -221,6 +221,18 @@ fn check_symmetric_difference(a: &[i32], b: &[i32], expected: &[i32]) { &[-2, 1, 5, 11, 14, 22]); } +#[test] +fn test_symmetric_difference_size_hint() { + let x: BTreeSet = [2, 4].iter().copied().collect(); + let y: BTreeSet = [1, 2, 3].iter().copied().collect(); + let mut iter = x.symmetric_difference(&y); + assert_eq!(iter.size_hint(), (0, Some(5))); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.size_hint(), (0, Some(4))); + assert_eq!(iter.next(), Some(&3)); + assert_eq!(iter.size_hint(), (0, Some(1))); +} + #[test] fn test_union() { fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { @@ -235,6 +247,18 @@ fn check_union(a: &[i32], b: &[i32], expected: &[i32]) { &[-2, 1, 3, 5, 9, 11, 13, 16, 19, 24]); } +#[test] +fn test_union_size_hint() { + let x: BTreeSet = [2, 4].iter().copied().collect(); + let y: BTreeSet = [1, 2, 3].iter().copied().collect(); + let mut iter = x.union(&y); + assert_eq!(iter.size_hint(), (3, Some(5))); + assert_eq!(iter.next(), Some(&1)); + assert_eq!(iter.size_hint(), (2, Some(4))); + assert_eq!(iter.next(), Some(&2)); + assert_eq!(iter.size_hint(), (1, Some(2))); +} + #[test] // Only tests the simple function definition with respect to intersection fn test_is_disjoint() { @@ -244,7 +268,7 @@ fn test_is_disjoint() { } #[test] -// Also tests the trivial function definition of is_superset +// Also implicitly tests the trivial function definition of is_superset fn test_is_subset() { fn is_subset(a: &[i32], b: &[i32]) -> bool { let set_a = a.iter().collect::>(); From c9b27d1236d68f9f5c86ca4db015ddeca6a1e39a Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Fri, 18 Oct 2019 01:16:30 +0200 Subject: [PATCH 496/545] doc: make BitSet intro more short Also, add a link to the growable type --- src/librustc_index/bit_set.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc_index/bit_set.rs b/src/librustc_index/bit_set.rs index d8c6e4c33e2f..9ed5ef5a539a 100644 --- a/src/librustc_index/bit_set.rs +++ b/src/librustc_index/bit_set.rs @@ -13,8 +13,9 @@ pub const WORD_BYTES: usize = mem::size_of::(); pub const WORD_BITS: usize = WORD_BYTES * 8; -/// A fixed-size bitset type with a dense representation. It does not support -/// resizing after creation; use `GrowableBitSet` for that. +/// A fixed-size bitset type with a dense representation. +/// +/// NOTE: Use [`GrowableBitSet`] if you need support for resizing after creation. /// /// `T` is an index type, typically a newtyped `usize` wrapper, but it can also /// just be `usize`. @@ -22,6 +23,8 @@ /// All operations that involve an element will panic if the element is equal /// to or greater than the domain size. All operations that involve two bitsets /// will panic if the bitsets have differing domain sizes. +/// +/// [`GrowableBitSet`]: struct.GrowableBitSet.html #[derive(Clone, Eq, PartialEq, RustcDecodable, RustcEncodable)] pub struct BitSet { domain_size: usize, From b25e3238c76a4df767b4a929011ed47c479ed115 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 17 Oct 2019 16:09:32 -0700 Subject: [PATCH 497/545] Don't add `argc` and `argv` arguments to `main` on WASI. Add a target setting to allow targets to specify whether the generated `main` function should be passed `argc` and `argv` arguments. Set it to false on wasm32-wasi, since WASI's `args::args()` calls into the WASI APIs itself. This will allow the WASI toolchain to avoid linking and running command-line argument initialization code when the arguments aren't actually needed. --- src/librustc_codegen_ssa/base.rs | 25 ++++++++++++++++++------- src/librustc_target/spec/mod.rs | 6 ++++++ src/librustc_target/spec/wasm32_wasi.rs | 4 ++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index 1c441ca7cbf2..546972903e9b 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -414,8 +414,11 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( rust_main_def_id: DefId, use_start_lang_item: bool, ) { - let llfty = - cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()); + let llfty = if cx.sess().target.target.options.main_needs_argc_argv { + cx.type_func(&[cx.type_int(), cx.type_ptr_to(cx.type_i8p())], cx.type_int()) + } else { + cx.type_func(&[], cx.type_int()) + }; let main_ret_ty = cx.tcx().fn_sig(rust_main_def_id).output(); // Given that `main()` has no arguments, @@ -445,11 +448,19 @@ fn create_entry_fn<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx.insert_reference_to_gdb_debug_scripts_section_global(); - // Params from native main() used as args for rust start function - let param_argc = bx.get_param(0); - let param_argv = bx.get_param(1); - let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); - let arg_argv = param_argv; + let (arg_argc, arg_argv) = if cx.sess().target.target.options.main_needs_argc_argv { + // Params from native main() used as args for rust start function + let param_argc = bx.get_param(0); + let param_argv = bx.get_param(1); + let arg_argc = bx.intcast(param_argc, cx.type_isize(), true); + let arg_argv = param_argv; + (arg_argc, arg_argv) + } else { + // The Rust start function doesn't need argc and argv, so just pass zeros. + let arg_argc = bx.const_int(cx.type_int(), 0); + let arg_argv = bx.const_null(cx.type_ptr_to(cx.type_i8p())); + (arg_argc, arg_argv) + }; let (start_fn, args) = if use_start_lang_item { let start_def_id = cx.tcx().require_lang_item(StartFnLangItem, None); diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index cf1a84dec97b..c5277c4f90e7 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -691,6 +691,9 @@ pub struct TargetOptions { /// defined in libgcc. If this option is enabled, the target must provide /// `eh_unwind_resume` lang item. pub custom_unwind_resume: bool, + /// Whether the runtime startup code requires the `main` function be passed + /// `argc` and `argv` values. + pub main_needs_argc_argv: bool, /// Flag indicating whether ELF TLS (e.g., #[thread_local]) is available for /// this target. @@ -849,6 +852,7 @@ fn default() -> TargetOptions { link_env_remove: Vec::new(), archive_format: "gnu".to_string(), custom_unwind_resume: false, + main_needs_argc_argv: true, allow_asm: true, has_elf_tls: false, obj_is_bitcode: false, @@ -1159,6 +1163,7 @@ macro_rules! key { key!(archive_format); key!(allow_asm, bool); key!(custom_unwind_resume, bool); + key!(main_needs_argc_argv, bool); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); key!(no_integrated_as, bool); @@ -1376,6 +1381,7 @@ macro_rules! target_option_val { target_option_val!(archive_format); target_option_val!(allow_asm); target_option_val!(custom_unwind_resume); + target_option_val!(main_needs_argc_argv); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); target_option_val!(no_integrated_as); diff --git a/src/librustc_target/spec/wasm32_wasi.rs b/src/librustc_target/spec/wasm32_wasi.rs index 86978c05b15d..d5ef230dcf7d 100644 --- a/src/librustc_target/spec/wasm32_wasi.rs +++ b/src/librustc_target/spec/wasm32_wasi.rs @@ -101,6 +101,10 @@ pub fn target() -> Result { // without a main function. options.crt_static_allows_dylibs = true; + // WASI's `sys::args::init` function ignores its arguments; instead, + // `args::args()` makes the WASI API calls itself. + options.main_needs_argc_argv = false; + Ok(Target { llvm_target: "wasm32-wasi".to_string(), target_endian: "little".to_string(), From ebf731c638c544211427391c138d34c2c7e1f65f Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Thu, 17 Oct 2019 16:59:10 -0700 Subject: [PATCH 498/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 52cebb1f8f87..e979eb4cc55f 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 52cebb1f8f8789b97d243c07bf4c961ca0017f7b +Subproject commit e979eb4cc55ffd357158c7d30133cbf894e93fe9 From cd9e4441eb55135b452689abe54ce9fb0c72f90b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Oct 2019 03:14:57 +0300 Subject: [PATCH 499/545] rustc: arena-allocate the slice in `ty::GenericsPredicate`, not the whole struct. --- src/librustc/arena.rs | 1 - src/librustc/query/mod.rs | 13 ++-- src/librustc/traits/specialize/mod.rs | 2 +- src/librustc/ty/codec.rs | 35 ++++++---- src/librustc/ty/context.rs | 14 ---- src/librustc/ty/mod.rs | 11 ++- src/librustc/ty/query/on_disk_cache.rs | 7 +- src/librustc/ty/structural_impls.rs | 6 -- src/librustc_lint/builtin.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/librustc_metadata/cstore_impl.rs | 8 +-- src/librustc_metadata/encoder.rs | 14 ++-- .../transform/qualify_min_const_fn.rs | 2 +- src/librustc_privacy/lib.rs | 4 +- src/librustc_traits/lowering/mod.rs | 4 +- src/librustc_typeck/astconv.rs | 3 +- src/librustc_typeck/check/dropck.rs | 6 +- src/librustc_typeck/check/mod.rs | 16 ++--- src/librustc_typeck/check/wfcheck.rs | 4 +- src/librustc_typeck/collect.rs | 69 +++++++++++-------- .../constrained_generic_params.rs | 4 +- src/librustc_typeck/impl_wf_check.rs | 2 +- src/librustc_typeck/outlives/explicit.rs | 2 +- src/librustdoc/clean/auto_trait.rs | 4 +- src/librustdoc/clean/blanket_impl.rs | 2 +- src/librustdoc/clean/inline.rs | 14 ++-- src/librustdoc/clean/mod.rs | 7 +- 27 files changed, 120 insertions(+), 138 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 5a5919d78663..3daf0fc9df7a 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -98,7 +98,6 @@ macro_rules! arena_types { rustc::hir::def_id::DefId, >, [few] resolve_lifetimes: rustc::middle::resolve_lifetime::ResolveLifetimes, - [decode] generic_predicates: rustc::ty::GenericPredicates<'tcx>, [few] lint_levels: rustc::lint::LintLevelMap, [few] stability_index: rustc::middle::stability::Index<'tcx>, [few] features: syntax::feature_gate::Features, diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 2a012c527419..2c407a24493f 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -61,7 +61,7 @@ /// predicate gets in the way of some checks, which are intended /// to operate over only the actual where-clauses written by the /// user.) - query predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> { + query predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { cache_on_disk_if { key.is_local() } } @@ -184,12 +184,10 @@ /// predicates (where-clauses) directly defined on it. This is /// equal to the `explicit_predicates_of` predicates plus the /// `inferred_outlives_of` predicates. - query predicates_defined_on(_: DefId) - -> &'tcx ty::GenericPredicates<'tcx> {} + query predicates_defined_on(_: DefId) -> ty::GenericPredicates<'tcx> {} /// Returns the predicates written explicitly by the user. - query explicit_predicates_of(_: DefId) - -> &'tcx ty::GenericPredicates<'tcx> {} + query explicit_predicates_of(_: DefId) -> ty::GenericPredicates<'tcx> {} /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). @@ -201,14 +199,13 @@ /// evaluate them even during type conversion, often before the /// full predicates are available (note that supertraits have /// additional acyclicity requirements). - query super_predicates_of(key: DefId) -> &'tcx ty::GenericPredicates<'tcx> { + query super_predicates_of(key: DefId) -> ty::GenericPredicates<'tcx> { desc { |tcx| "computing the supertraits of `{}`", tcx.def_path_str(key) } } /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. - query type_param_predicates(key: (DefId, DefId)) - -> &'tcx ty::GenericPredicates<'tcx> { + query type_param_predicates(key: (DefId, DefId)) -> ty::GenericPredicates<'tcx> { no_force desc { |tcx| "computing the bounds for type parameter `{}`", { let id = tcx.hir().as_local_hir_id(key.1).unwrap(); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 9c80ef7d4a23..c1c6eb850f59 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -419,7 +419,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option // The predicates will contain default bounds like `T: Sized`. We need to // remove these bounds, and add `T: ?Sized` to any untouched type parameters. - let predicates = &tcx.predicates_of(impl_def_id).predicates; + let predicates = tcx.predicates_of(impl_def_id).predicates; let mut pretty_predicates = Vec::with_capacity( predicates.len() + types_without_default_bounds.len()); diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index bd4913c88fd1..03cb4775bd83 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -16,6 +16,7 @@ use crate::ty::{self, Ty, TyCtxt}; use crate::ty::subst::SubstsRef; use crate::mir::interpret::Allocation; +use syntax_pos::Span; /// The shorthand encoding uses an enum's variant index `usize` /// and is offset by this value so it never matches a real variant. @@ -92,16 +93,16 @@ pub fn encode_with_shorthand(encoder: &mut E, Ok(()) } -pub fn encode_predicates<'tcx, E, C>(encoder: &mut E, - predicates: &ty::GenericPredicates<'tcx>, - cache: C) - -> Result<(), E::Error> +pub fn encode_spanned_predicates<'tcx, E, C>( + encoder: &mut E, + predicates: &'tcx [(ty::Predicate<'tcx>, Span)], + cache: C, +) -> Result<(), E::Error> where E: TyEncoder, C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap, usize>, { - predicates.parent.encode(encoder)?; - predicates.predicates.len().encode(encoder)?; - for (predicate, span) in &predicates.predicates { + predicates.len().encode(encoder)?; + for (predicate, span) in predicates { encode_with_shorthand(encoder, predicate, &cache)?; span.encode(encoder)?; } @@ -182,13 +183,15 @@ pub fn decode_ty(decoder: &mut D) -> Result, D::Error> } #[inline] -pub fn decode_predicates(decoder: &mut D) -> Result, D::Error> +pub fn decode_spanned_predicates( + decoder: &mut D, +) -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], D::Error> where D: TyDecoder<'tcx>, { - Ok(ty::GenericPredicates { - parent: Decodable::decode(decoder)?, - predicates: (0..decoder.read_usize()?).map(|_| { + let tcx = decoder.tcx(); + Ok(tcx.arena.alloc_from_iter( + (0..decoder.read_usize()?).map(|_| { // Handle shorthands first, if we have an usize > 0x80. let predicate = if decoder.positioned_at_shorthand() { let pos = decoder.read_usize()?; @@ -202,7 +205,7 @@ pub fn decode_predicates(decoder: &mut D) -> Result, _>>()?, - }) + )) } #[inline] @@ -339,6 +342,8 @@ mod __ty_decoder_impl { use $crate::ty::subst::SubstsRef; use $crate::hir::def_id::{CrateNum}; + use syntax_pos::Span; + use super::$DecoderName; impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> { @@ -393,11 +398,11 @@ fn specialized_decode(&mut self) -> Result, Self::Error> { } } - impl<$($typaram),*> SpecializedDecoder> + impl<$($typaram),*> SpecializedDecoder<&'tcx [(ty::Predicate<'tcx>, Span)]> for $DecoderName<$($typaram),*> { fn specialized_decode(&mut self) - -> Result, Self::Error> { - decode_predicates(self) + -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], Self::Error> { + decode_spanned_predicates(self) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 256194cfb00e..665d4c2d0696 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -148,10 +148,6 @@ fn intern_ty(&self, } } -pub struct Common<'tcx> { - pub empty_predicates: ty::GenericPredicates<'tcx>, -} - pub struct CommonTypes<'tcx> { pub unit: Ty<'tcx>, pub bool: Ty<'tcx>, @@ -1039,9 +1035,6 @@ pub struct GlobalCtxt<'tcx> { pub prof: SelfProfilerRef, - /// Common objects. - pub common: Common<'tcx>, - /// Common types, pre-interned for your convenience. pub types: CommonTypes<'tcx>, @@ -1213,12 +1206,6 @@ pub fn create_global_ctxt( s.fatal(&err); }); let interners = CtxtInterners::new(&arenas.interner); - let common = Common { - empty_predicates: ty::GenericPredicates { - parent: None, - predicates: vec![], - }, - }; let common_types = CommonTypes::new(&interners); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); @@ -1273,7 +1260,6 @@ pub fn create_global_ctxt( interners, dep_graph, prof: s.prof.clone(), - common, types: common_types, lifetimes: common_lifetimes, consts: common_consts, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d5911a24de21..14f0c3284fcb 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1018,15 +1018,12 @@ pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &Generi } /// Bounds on generics. -#[derive(Clone, Default, Debug, HashStable)] +#[derive(Copy, Clone, Default, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct GenericPredicates<'tcx> { pub parent: Option, - pub predicates: Vec<(Predicate<'tcx>, Span)>, + pub predicates: &'tcx [(Predicate<'tcx>, Span)], } -impl<'tcx> rustc_serialize::UseSpecializedEncodable for GenericPredicates<'tcx> {} -impl<'tcx> rustc_serialize::UseSpecializedDecodable for GenericPredicates<'tcx> {} - impl<'tcx> GenericPredicates<'tcx> { pub fn instantiate( &self, @@ -2321,7 +2318,7 @@ pub fn non_enum_variant(&self) -> &VariantDef { } #[inline] - pub fn predicates(&self, tcx: TyCtxt<'tcx>) -> &'tcx GenericPredicates<'tcx> { + pub fn predicates(&self, tcx: TyCtxt<'tcx>) -> GenericPredicates<'tcx> { tcx.predicates_of(self.did) } @@ -2561,7 +2558,7 @@ fn sized_constraint_for_ty(&self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Vec) -> Result<(), Self::Error> { } } -impl<'a, 'tcx, E> SpecializedEncoder> for CacheEncoder<'a, 'tcx, E> +impl<'a, 'tcx, E> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> + for CacheEncoder<'a, 'tcx, E> where E: 'a + TyEncoder, { #[inline] fn specialized_encode(&mut self, - predicates: &ty::GenericPredicates<'tcx>) + predicates: &&'tcx [(ty::Predicate<'tcx>, Span)]) -> Result<(), Self::Error> { - ty_codec::encode_predicates(self, predicates, + ty_codec::encode_spanned_predicates(self, predicates, |encoder| &mut encoder.predicate_shorthands) } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 8945e1a1debd..83ec98f9ddd2 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -1218,12 +1218,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> { } } -BraceStructTypeFoldableImpl! { - impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { - parent, predicates - } -} - impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List> { fn super_fold_with>(&self, folder: &mut F) -> Self { // This code is hot enough that it's worth specializing for a list of diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 9a16d0a0715f..08f6f43ab0cf 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1241,7 +1241,7 @@ fn check_item( if cx.tcx.features().trivial_bounds { let def_id = cx.tcx.hir().local_def_id(item.hir_id); let predicates = cx.tcx.predicates_of(def_id); - for &(predicate, span) in &predicates.predicates { + for &(predicate, span) in predicates.predicates { let predicate_kind_name = match predicate { Trait(..) => "Trait", TypeOutlives(..) | diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 3b3995832cb4..a93946df68f9 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -156,7 +156,7 @@ fn check_must_use_ty<'tcx>( } ty::Opaque(def, _) => { let mut has_emitted = false; - for (predicate, _) in &cx.tcx.predicates_of(def).predicates { + for (predicate, _) in cx.tcx.predicates_of(def).predicates { if let ty::Predicate::Trait(ref poly_trait_predicate) = predicate { let trait_ref = poly_trait_predicate.skip_binder().trait_ref; let def_id = trait_ref.def_id; diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index fd011265da7c..4cd1ff7b4a4f 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -97,11 +97,9 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) } generics_of => { tcx.arena.alloc(cdata.get_generics(def_id.index, tcx.sess)) } - predicates_of => { tcx.arena.alloc(cdata.get_predicates(def_id.index, tcx)) } - predicates_defined_on => { - tcx.arena.alloc(cdata.get_predicates_defined_on(def_id.index, tcx)) - } - super_predicates_of => { tcx.arena.alloc(cdata.get_super_predicates(def_id.index, tcx)) } + predicates_of => { cdata.get_predicates(def_id.index, tcx) } + predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) } + super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } trait_def => { tcx.arena.alloc(cdata.get_trait_def(def_id.index, tcx.sess)) } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f1436e4c09df..ce4969146135 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -243,11 +243,11 @@ fn specialized_encode(&mut self, alloc_id: &interpret::AllocId) -> Result<(), Se } } -impl<'tcx> SpecializedEncoder> for EncodeContext<'tcx> { +impl<'tcx> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> for EncodeContext<'tcx> { fn specialized_encode(&mut self, - predicates: &ty::GenericPredicates<'tcx>) + predicates: &&'tcx [(ty::Predicate<'tcx>, Span)]) -> Result<(), Self::Error> { - ty_codec::encode_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands) + ty_codec::encode_spanned_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands) } } @@ -826,13 +826,13 @@ fn encode_generics(&mut self, def_id: DefId) { fn encode_predicates(&mut self, def_id: DefId) { debug!("EncodeContext::encode_predicates({:?})", def_id); - record!(self.per_def.predicates[def_id] <- &*self.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) { debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); record!(self.per_def.predicates_defined_on[def_id] <- - &*self.tcx.predicates_defined_on(def_id)) + self.tcx.predicates_defined_on(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) { @@ -1166,14 +1166,14 @@ fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { paren_sugar: trait_def.paren_sugar, has_auto_impl: self.tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, - super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), + super_predicates: self.lazy(tcx.super_predicates_of(def_id)), }; EntryKind::Trait(self.lazy(data)) } hir::ItemKind::TraitAlias(..) => { let data = TraitAliasData { - super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), + super_predicates: self.lazy(tcx.super_predicates_of(def_id)), }; EntryKind::TraitAlias(self.lazy(data)) diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index cf0ee1bf0922..7b6255defd14 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -14,7 +14,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) - let mut current = def_id; loop { let predicates = tcx.predicates_of(current); - for (predicate, _) in &predicates.predicates { + for (predicate, _) in predicates.predicates { match predicate { | Predicate::RegionOutlives(_) | Predicate::TypeOutlives(_) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index f44692b7aea7..eb79ce69a3e1 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -64,7 +64,7 @@ fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> bool { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { self.skeleton().visit_trait(trait_ref) } - fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool { + fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> bool { self.skeleton().visit_predicates(predicates) } } @@ -88,7 +88,7 @@ fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { (!self.def_id_visitor.shallow() && substs.visit_with(self)) } - fn visit_predicates(&mut self, predicates: &ty::GenericPredicates<'tcx>) -> bool { + fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> bool { let ty::GenericPredicates { parent: _, predicates } = predicates; for (predicate, _span) in predicates { match predicate { diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 4c30227150fb..0df367fcca83 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -218,7 +218,7 @@ fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> { let implemented_from_env = Clause::ForAll(ty::Binder::bind(implemented_from_env)); - let predicates = &tcx.predicates_defined_on(def_id).predicates; + let predicates = tcx.predicates_defined_on(def_id).predicates; // Warning: these where clauses are not substituted for bound vars yet, // so that we don't need to adjust binders in the `FromEnv` rules below @@ -319,7 +319,7 @@ fn program_clauses_for_impl(tcx: TyCtxt<'tcx>, def_id: DefId) -> Clauses<'tcx> { let trait_pred = ty::TraitPredicate { trait_ref }.lower(); // `WC` - let predicates = &tcx.predicates_of(def_id).predicates; + let predicates = tcx.predicates_of(def_id).predicates; let where_clauses = predicates .iter() .map(|(wc, _)| wc.lower()) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index b8e2700803a5..7e0a9bc4011c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -54,8 +54,7 @@ pub trait AstConv<'tcx> { /// but this can lead to cycle errors. The problem is that we have /// to do this resolution *in order to create the predicates in /// the first place*. Hence, we have this "special pass". - fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> &'tcx ty::GenericPredicates<'tcx>; + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx>; /// Returns the lifetime to use when a lifetime is omitted (and not elided). fn re_infer( diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index d46ac4a39a33..0c8df9bad448 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -44,7 +44,7 @@ pub fn check_drop_impl(tcx: TyCtxt<'_>, drop_impl_did: DefId) -> Result<(), Erro ensure_drop_predicates_are_implied_by_item_defn( tcx, drop_impl_did, - &dtor_predicates, + dtor_predicates, adt_def.did, self_to_impl_substs, ) @@ -140,7 +140,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( tcx: TyCtxt<'tcx>, drop_impl_did: DefId, - dtor_predicates: &ty::GenericPredicates<'tcx>, + dtor_predicates: ty::GenericPredicates<'tcx>, self_type_did: DefId, self_to_impl_substs: SubstsRef<'tcx>, ) -> Result<(), ErrorReported> { @@ -199,7 +199,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( // just to look for all the predicates directly. assert_eq!(dtor_predicates.parent, None); - for (predicate, _) in &dtor_predicates.predicates { + for (predicate, _) in dtor_predicates.predicates { // (We do not need to worry about deep analysis of type // expressions etc because the Drop impls are already forced // to take on a structure that is roughly an alpha-renaming of diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7475b9cc3b32..152edf8dd0e5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2245,19 +2245,17 @@ fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { self.tcx } - fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) - -> &'tcx ty::GenericPredicates<'tcx> - { + fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { let tcx = self.tcx; let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); let item_id = tcx.hir().ty_param_owner(hir_id); let item_def_id = tcx.hir().local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - tcx.arena.alloc(ty::GenericPredicates { + ty::GenericPredicates { parent: None, - predicates: self.param_env.caller_bounds.iter().filter_map(|&predicate| { - match predicate { + predicates: tcx.arena.alloc_from_iter( + self.param_env.caller_bounds.iter().filter_map(|&predicate| match predicate { ty::Predicate::Trait(ref data) if data.skip_binder().self_ty().is_param(index) => { // HACK(eddyb) should get the original `Span`. @@ -2265,9 +2263,9 @@ fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) Some((predicate, span)) } _ => None - } - }).collect() - }) + }), + ), + } } fn re_infer( diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index fa283904fe47..18b103960c74 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -791,7 +791,7 @@ fn check_opaque_types<'fcx, 'tcx>( "check_opaque_types: may define, predicates={:#?}", predicates, ); - for &(pred, _) in predicates.predicates.iter() { + for &(pred, _) in predicates.predicates { let substituted_pred = pred.subst(fcx.tcx, substs); // Avoid duplication of predicates that contain no parameters, for example. if !predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) { @@ -1011,7 +1011,7 @@ fn check_variances_for_type_defn<'tcx>( identify_constrained_generic_params( tcx, - &ty_predicates, + ty_predicates, None, &mut constrained_parameters, ); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5b2081bef78d..1749fd1075e0 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -182,8 +182,7 @@ fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } - fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> &'tcx ty::GenericPredicates<'tcx> { + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { self.tcx .at(span) .type_param_predicates((self.item_def_id, def_id)) @@ -254,7 +253,7 @@ fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) { fn type_param_predicates( tcx: TyCtxt<'_>, (item_def_id, def_id): (DefId, DefId), -) -> &ty::GenericPredicates<'_> { +) -> ty::GenericPredicates<'_> { use rustc::hir::*; // In the AST, bounds can derive from two places. Either @@ -275,10 +274,10 @@ fn type_param_predicates( tcx.generics_of(item_def_id).parent }; - let result = parent.map_or(&tcx.common.empty_predicates, |parent| { + let mut result = parent.map(|parent| { let icx = ItemCtxt::new(tcx, parent); icx.get_type_parameter_bounds(DUMMY_SP, def_id) - }); + }).unwrap_or_default(); let mut extend = None; let item_hir_id = tcx.hir().as_local_hir_id(item_def_id).unwrap(); @@ -321,9 +320,7 @@ fn type_param_predicates( }; let icx = ItemCtxt::new(tcx, item_def_id); - let mut result = (*result).clone(); - result.predicates.extend(extend.into_iter()); - result.predicates.extend( + let extra_predicates = extend.into_iter().chain( icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true)) .into_iter() .filter(|(predicate, _)| { @@ -331,9 +328,12 @@ fn type_param_predicates( ty::Predicate::Trait(ref data) => data.skip_binder().self_ty().is_param(index), _ => false, } - }) + }), ); - tcx.arena.alloc(result) + result.predicates = tcx.arena.alloc_from_iter( + result.predicates.iter().copied().chain(extra_predicates), + ); + result } impl ItemCtxt<'tcx> { @@ -698,7 +698,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::AdtDef { fn super_predicates_of( tcx: TyCtxt<'_>, trait_def_id: DefId, -) -> &ty::GenericPredicates<'_> { +) -> ty::GenericPredicates<'_> { debug!("super_predicates(trait_def_id={:?})", trait_def_id); let trait_hir_id = tcx.hir().as_local_hir_id(trait_def_id).unwrap(); @@ -732,21 +732,23 @@ fn super_predicates_of( generics, item.hir_id, self_param_ty, OnlySelfBounds(!is_trait_alias)); // Combine the two lists to form the complete set of superbounds: - let superbounds: Vec<_> = superbounds1.into_iter().chain(superbounds2).collect(); + let superbounds = &*tcx.arena.alloc_from_iter( + superbounds1.into_iter().chain(superbounds2) + ); // Now require that immediate supertraits are converted, // which will, in turn, reach indirect supertraits. - for &(pred, span) in &superbounds { + for &(pred, span) in superbounds { debug!("superbound: {:?}", pred); if let ty::Predicate::Trait(bound) = pred { tcx.at(span).super_predicates_of(bound.def_id()); } } - tcx.arena.alloc(ty::GenericPredicates { + ty::GenericPredicates { parent: None, predicates: superbounds, - }) + } } fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef { @@ -1958,7 +1960,7 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx: 'a>( fn predicates_defined_on( tcx: TyCtxt<'_>, def_id: DefId, -) -> &ty::GenericPredicates<'_> { +) -> ty::GenericPredicates<'_> { debug!("predicates_defined_on({:?})", def_id); let mut result = tcx.explicit_predicates_of(def_id); debug!( @@ -1974,9 +1976,13 @@ fn predicates_defined_on( def_id, inferred_outlives, ); - let mut predicates = (*result).clone(); - predicates.predicates.extend(inferred_outlives.iter().map(|&p| (p, span))); - result = tcx.arena.alloc(predicates); + result.predicates = tcx.arena.alloc_from_iter( + result.predicates.iter().copied().chain( + // FIXME(eddyb) use better spans - maybe add `Span`s + // to `inferred_outlives_of` predicates as well? + inferred_outlives.iter().map(|&p| (p, span)), + ), + ); } debug!("predicates_defined_on({:?}) = {:?}", def_id, result); result @@ -1985,7 +1991,7 @@ fn predicates_defined_on( /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus /// `Self: Trait` predicates for traits. -fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::GenericPredicates<'_> { +fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { let mut result = tcx.predicates_defined_on(def_id); if tcx.is_trait(def_id) { @@ -2002,9 +2008,11 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::GenericPredicates<'_> { // used, and adding the predicate into this list ensures // that this is done. let span = tcx.def_span(def_id); - let mut predicates = (*result).clone(); - predicates.predicates.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); - result = tcx.arena.alloc(predicates); + result.predicates = tcx.arena.alloc_from_iter( + result.predicates.iter().copied().chain( + std::iter::once((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)) + ), + ); } debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); result @@ -2015,7 +2023,7 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::GenericPredicates<'_> { fn explicit_predicates_of( tcx: TyCtxt<'_>, def_id: DefId, -) -> &ty::GenericPredicates<'_> { +) -> ty::GenericPredicates<'_> { use rustc::hir::*; use rustc_data_structures::fx::FxHashSet; @@ -2024,6 +2032,7 @@ fn explicit_predicates_of( /// A data structure with unique elements, which preserves order of insertion. /// Preserving the order of insertion is important here so as not to break /// compile-fail UI tests. + // FIXME(eddyb) just use `IndexSet` from `indexmap`. struct UniquePredicates<'tcx> { predicates: Vec<(ty::Predicate<'tcx>, Span)>, uniques: FxHashSet<(ty::Predicate<'tcx>, Span)>, @@ -2133,10 +2142,10 @@ fn extend, Span)>>(&mut self, iter: let bounds_predicates = bounds.predicates(tcx, opaque_ty); if impl_trait_fn.is_some() { // opaque types - return tcx.arena.alloc(ty::GenericPredicates { + return ty::GenericPredicates { parent: None, - predicates: bounds_predicates, - }); + predicates: tcx.arena.alloc_from_iter(bounds_predicates), + }; } else { // named opaque types predicates.extend(bounds_predicates); @@ -2339,10 +2348,10 @@ fn extend, Span)>>(&mut self, iter: ); } - let result = tcx.arena.alloc(ty::GenericPredicates { + let result = ty::GenericPredicates { parent: generics.parent, - predicates, - }); + predicates: tcx.arena.alloc_from_iter(predicates), + }; debug!("explicit_predicates_of(def_id={:?}) = {:?}", def_id, result); result } diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index 31476eb73179..1fdf49fde55b 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -86,11 +86,11 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { pub fn identify_constrained_generic_params<'tcx>( tcx: TyCtxt<'tcx>, - predicates: &ty::GenericPredicates<'tcx>, + predicates: ty::GenericPredicates<'tcx>, impl_trait_ref: Option>, input_parameters: &mut FxHashSet, ) { - let mut predicates = predicates.predicates.clone(); + let mut predicates = predicates.predicates.to_vec(); setup_constraining_predicates(tcx, &mut predicates, impl_trait_ref, input_parameters); } diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index ab660caa222a..2d188007712a 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -114,7 +114,7 @@ fn enforce_impl_params_are_constrained( let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref); cgp::identify_constrained_generic_params( - tcx, &impl_predicates, impl_trait_ref, &mut input_parameters); + tcx, impl_predicates, impl_trait_ref, &mut input_parameters); // Disallow unconstrained lifetimes, but only if they appear in assoc types. let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs.iter() diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs index 40a57788c071..83194144216e 100644 --- a/src/librustc_typeck/outlives/explicit.rs +++ b/src/librustc_typeck/outlives/explicit.rs @@ -30,7 +30,7 @@ pub fn explicit_predicates_of( let mut required_predicates = RequiredPredicates::default(); // process predicates and convert to `RequiredPredicates` entry, see below - for (pred, _) in predicates.predicates.iter() { + for (pred, _) in predicates.predicates { match pred { ty::Predicate::TypeOutlives(predicate) => { let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder(); diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 18a84cd0eeb7..b7f5ed9d004d 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -104,7 +104,7 @@ pub fn get_auto_trait_impls( // regardless of the choice of `T`. let params = ( self.cx.tcx.generics_of(param_env_def_id), - &&self.cx.tcx.common.empty_predicates, + ty::GenericPredicates::default(), ).clean(self.cx).params; Generics { @@ -489,7 +489,7 @@ fn param_env_to_generics( let mut generic_params = ( tcx.generics_of(param_env_def_id), - &tcx.explicit_predicates_of(param_env_def_id), + tcx.explicit_predicates_of(param_env_def_id), ).clean(self.cx).params; let mut has_sized = FxHashSet::default(); diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index afed11e7fab2..ff59dcab672f 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -107,7 +107,7 @@ pub fn get_blanket_impls( unsafety: hir::Unsafety::Normal, generics: ( self.cx.tcx.generics_of(impl_def_id), - &self.cx.tcx.explicit_predicates_of(impl_def_id), + self.cx.tcx.explicit_predicates_of(impl_def_id), ).clean(self.cx), provided_trait_methods, // FIXME(eddyb) compute both `trait_` and `for_` from diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 532c5f67bf3b..b3227c9f6002 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -193,7 +193,7 @@ pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait { let auto_trait = cx.tcx.trait_def(did).has_auto_impl; let trait_items = cx.tcx.associated_items(did).map(|item| item.clean(cx)).collect(); let predicates = cx.tcx.predicates_of(did); - let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); + let generics = (cx.tcx.generics_of(did), predicates).clean(cx); let generics = filter_non_trait_generics(did, generics); let (generics, supertrait_bounds) = separate_supertrait_bounds(generics); let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight); @@ -220,7 +220,7 @@ fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function { let asyncness = cx.tcx.asyncness(did); let predicates = cx.tcx.predicates_of(did); let (generics, decl) = clean::enter_impl_trait(cx, || { - ((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx)) + ((cx.tcx.generics_of(did), predicates).clean(cx), (did, sig).clean(cx)) }); let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx); clean::Function { @@ -241,7 +241,7 @@ fn build_enum(cx: &DocContext<'_>, did: DefId) -> clean::Enum { let predicates = cx.tcx.explicit_predicates_of(did); clean::Enum { - generics: (cx.tcx.generics_of(did), &predicates).clean(cx), + generics: (cx.tcx.generics_of(did), predicates).clean(cx), variants_stripped: false, variants: cx.tcx.adt_def(did).variants.clean(cx), } @@ -257,7 +257,7 @@ fn build_struct(cx: &DocContext<'_>, did: DefId) -> clean::Struct { CtorKind::Fn => doctree::Tuple, CtorKind::Const => doctree::Unit, }, - generics: (cx.tcx.generics_of(did), &predicates).clean(cx), + generics: (cx.tcx.generics_of(did), predicates).clean(cx), fields: variant.fields.clean(cx), fields_stripped: false, } @@ -269,7 +269,7 @@ fn build_union(cx: &DocContext<'_>, did: DefId) -> clean::Union { clean::Union { struct_type: doctree::Plain, - generics: (cx.tcx.generics_of(did), &predicates).clean(cx), + generics: (cx.tcx.generics_of(did), predicates).clean(cx), fields: variant.fields.clean(cx), fields_stripped: false, } @@ -280,7 +280,7 @@ fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef { clean::Typedef { type_: cx.tcx.type_of(did).clean(cx), - generics: (cx.tcx.generics_of(did), &predicates).clean(cx), + generics: (cx.tcx.generics_of(did), predicates).clean(cx), } } @@ -376,7 +376,7 @@ pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option>, } }).collect::>(), clean::enter_impl_trait(cx, || { - (tcx.generics_of(did), &predicates).clean(cx) + (tcx.generics_of(did), predicates).clean(cx) }), ) }; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 212a09ee6e63..d9c853aa7aa3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1664,8 +1664,7 @@ fn is_impl_trait(param: &hir::GenericParam) -> bool { } } -impl<'a, 'tcx> Clean for (&'a ty::Generics, - &'a &'tcx ty::GenericPredicates<'tcx>) { +impl<'a, 'tcx> Clean for (&'a ty::Generics, ty::GenericPredicates<'tcx>) { fn clean(&self, cx: &DocContext<'_>) -> Generics { use self::WherePredicate as WP; use std::collections::BTreeMap; @@ -2369,7 +2368,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item { } ty::AssocKind::Method => { let generics = (cx.tcx.generics_of(self.def_id), - &cx.tcx.explicit_predicates_of(self.def_id)).clean(cx); + cx.tcx.explicit_predicates_of(self.def_id)).clean(cx); let sig = cx.tcx.fn_sig(self.def_id); let mut decl = (self.def_id, sig).clean(cx); @@ -2448,7 +2447,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Item { // all of the generics from there and then look for bounds that are // applied to this associated type in question. let predicates = cx.tcx.explicit_predicates_of(did); - let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); + let generics = (cx.tcx.generics_of(did), predicates).clean(cx); let mut bounds = generics.where_predicates.iter().filter_map(|pred| { let (name, self_type, trait_, bounds) = match *pred { WherePredicate::BoundPredicate { From 11011013f2b609b6cf58c96555b9e31dfd19d7ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 17 Oct 2019 19:00:19 -0700 Subject: [PATCH 500/545] Refer to "associated functions" instead of "static methods" --- src/librustc_resolve/error_codes.rs | 22 ++++++++++++++-------- src/librustc_resolve/late/diagnostics.rs | 22 ++++++++++------------ src/libsyntax_ext/deriving/clone.rs | 22 +++++++++------------- src/libsyntax_ext/deriving/default.rs | 2 +- src/libsyntax_ext/deriving/generic/mod.rs | 4 +--- src/test/ui/error-codes/E0424.stderr | 2 +- src/test/ui/resolve/issue-2356.stderr | 4 ++-- 7 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index ab3d95dd8edf..29ca797fc065 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1013,7 +1013,12 @@ fn h1() -> i32 { "##, E0424: r##" -The `self` keyword was used in a static method. +The `self` keyword was used inside of an associated function instead of inside +of a method. Associated functions have no "`self` receiver" argument, and are +equivalent to regular functions which exist in the namespace of a trait. +Methods, on the other hand, have a `self` reciver argument, like `self`, +`&self`, `&mut self` or `self: &mut Pin` (this last one is an example of +an ["abitrary `self` type"](https://github.com/rust-lang/rust/issues/44874)). Erroneous code example: @@ -1021,25 +1026,26 @@ fn h1() -> i32 { struct Foo; impl Foo { - fn bar(self) {} + // `bar` is a method, because it has a receiver argument. + fn bar(&self) {} + // `foo` is an associated function, because it has no receiver argument. fn foo() { - self.bar(); // error: `self` is not available in a static method. + self.bar(); // error: `self` is not available in an associated function } } ``` -Please check if the method's argument list should have contained `self`, -`&self`, or `&mut self` (in case you didn't want to create a static -method), and add it if so. Example: +Check if the associated function's argument list should have contained a `self` +receiver for it to be a method, and add it if so. Example: ``` struct Foo; impl Foo { - fn bar(self) {} + fn bar(&self) {} - fn foo(self) { + fn foo(self) { // `foo` is now a method. self.bar(); // ok! } } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 412734eabe05..dba4226e9836 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -115,8 +115,10 @@ pub(crate) fn smart_resolve_report_errors( if is_self_type(path, ns) { syntax::diagnostic_used!(E0411); err.code(DiagnosticId::Error("E0411".into())); - err.span_label(span, format!("`Self` is only available in impls, traits, \ - and type definitions")); + err.span_label( + span, + format!("`Self` is only available in impls, traits, and type definitions"), + ); return (err, Vec::new()); } if is_self_value(path, ns) { @@ -125,16 +127,12 @@ pub(crate) fn smart_resolve_report_errors( syntax::diagnostic_used!(E0424); err.code(DiagnosticId::Error("E0424".into())); err.span_label(span, match source { - PathSource::Pat => { - format!("`self` value is a keyword \ - and may not be bound to \ - variables or shadowed") - } - _ => { - format!("`self` value is a keyword \ - only available in methods \ - with `self` parameter") - } + PathSource::Pat => format!( + "`self` value is a keyword and may not be bound to variables or shadowed", + ), + _ => format!( + "`self` value is a keyword only available in methods with a `self` parameter", + ), }); return (err, Vec::new()); } diff --git a/src/libsyntax_ext/deriving/clone.rs b/src/libsyntax_ext/deriving/clone.rs index eb7d480aa983..67ef69babdc0 100644 --- a/src/libsyntax_ext/deriving/clone.rs +++ b/src/libsyntax_ext/deriving/clone.rs @@ -174,14 +174,12 @@ fn cs_clone(name: &str, all_fields = af; vdata = &variant.data; } - EnumNonMatchingCollapsed(..) => { - cx.span_bug(trait_span, - &format!("non-matching enum variants in \ - `derive({})`", - name)) - } + EnumNonMatchingCollapsed(..) => cx.span_bug(trait_span, &format!( + "non-matching enum variants in `derive({})`", + name, + )), StaticEnum(..) | StaticStruct(..) => { - cx.span_bug(trait_span, &format!("static method in `derive({})`", name)) + cx.span_bug(trait_span, &format!("associated function in `derive({})`", name)) } } @@ -191,12 +189,10 @@ fn cs_clone(name: &str, .map(|field| { let ident = match field.name { Some(i) => i, - None => { - cx.span_bug(trait_span, - &format!("unnamed field in normal struct in \ - `derive({})`", - name)) - } + None => cx.span_bug(trait_span, &format!( + "unnamed field in normal struct in `derive({})`", + name, + )), }; let call = subcall(cx, field); cx.field_imm(field.span, ident, call) diff --git a/src/libsyntax_ext/deriving/default.rs b/src/libsyntax_ext/deriving/default.rs index 6176791c31b1..cfc0f3cd6cbf 100644 --- a/src/libsyntax_ext/deriving/default.rs +++ b/src/libsyntax_ext/deriving/default.rs @@ -75,6 +75,6 @@ fn default_substructure(cx: &mut ExtCtxt<'_>, // let compilation continue DummyResult::raw_expr(trait_span, true) } - _ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"), + _ => cx.span_bug(trait_span, "method in `derive(Default)`"), }; } diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index 1886a5154b7b..fd2c1552d32a 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1055,9 +1055,7 @@ fn expand_struct_method_body<'b>(&self, }) .collect() } else { - cx.span_bug(trait_.span, - "no self arguments to non-static method in generic \ - `derive`") + cx.span_bug(trait_.span, "no self arguments for method in generic `derive`") }; // body of the inner most destructuring match diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr index d67a2660dac3..99b5e01abb19 100644 --- a/src/test/ui/error-codes/E0424.stderr +++ b/src/test/ui/error-codes/E0424.stderr @@ -2,7 +2,7 @@ error[E0424]: expected value, found module `self` --> $DIR/E0424.rs:7:9 | LL | self.bar(); - | ^^^^ `self` value is a keyword only available in methods with `self` parameter + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error[E0424]: expected unit struct/variant or constant, found module `self` --> $DIR/E0424.rs:12:9 diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index 7790383843e1..e0a2088ab8b9 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -62,7 +62,7 @@ error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:65:8 | LL | if self.whiskers > 3 { - | ^^^^ `self` value is a keyword only available in methods with `self` parameter + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error[E0425]: cannot find function `grow_older` in this scope --> $DIR/issue-2356.rs:72:5 @@ -98,7 +98,7 @@ error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:92:5 | LL | self += 1; - | ^^^^ `self` value is a keyword only available in methods with `self` parameter + | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error: aborting due to 17 previous errors From 5de9cb0703555ee6e2e0af8305be138f09545485 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 19:36:48 -0300 Subject: [PATCH 501/545] super_ty on MutVisitor is empty so avoid the call --- src/librustc_mir/transform/erase_regions.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 38a04ce8f381..e9ce84a25838 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -25,7 +25,6 @@ pub fn new(tcx: TyCtxt<'tcx>) -> Self { impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) { *ty = self.tcx.erase_regions(ty); - self.super_ty(ty); } fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) { From e069e9ccacbe92de1c893be5ad77fd5d6173f937 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 16:39:20 -0300 Subject: [PATCH 502/545] Prepare promote_consts MutVisitor to have projections interned --- src/librustc_mir/transform/promote_consts.rs | 26 +++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 5d241ffe1c06..d1c79c5ae2ad 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -191,6 +191,10 @@ fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) { }); } + fn is_temp_kind(&self, local: Local) -> bool { + self.source.local_kind(local) == LocalKind::Temp + } + /// Copies the initialization of this temp to the /// promoted MIR, recursing through temps. fn promote_temp(&mut self, temp: Local) -> Local { @@ -396,10 +400,30 @@ fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { - if self.source.local_kind(*local) == LocalKind::Temp { + if self.is_temp_kind(*local) { *local = self.promote_temp(*local); } } + + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + match elem { + PlaceElem::Index(local) if self.is_temp_kind(*local) => { + PlaceElem::Index(self.promote_temp(*local)) + } + _ => elem.clone(), + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } pub fn promote_candidates<'tcx>( From 591cc9aede4aec9b8816b8489eb98c2f2a3bfe90 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 17:58:28 -0300 Subject: [PATCH 503/545] Prepare simplify MutVisitor to have projections interned --- src/librustc_mir/transform/simplify.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 9ffff9a92fa5..57bc1c8fab96 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -366,7 +366,27 @@ fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockDat }); self.super_basic_block_data(block, data); } + fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) { *l = self.map[*l].unwrap(); } + + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + if let PlaceElem::Index(local) = elem { + PlaceElem::Index(self.map[*local].unwrap()) + } else { + elem.clone() + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } From bb7d6d1c70964d1d3efd5fb448538b7de50bbe3c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 18:15:19 -0300 Subject: [PATCH 504/545] Prepare renumber MutVisitor to have projections interned --- src/librustc_mir/borrow_check/nll/renumber.rs | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 88ad1fb12950..6eb5735cb16b 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,7 +1,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::mir::{Location, Body, Promoted}; -use rustc::mir::visit::{MutVisitor, TyContext}; +use rustc::mir::{Body, Location, Place, PlaceElem, Promoted}; +use rustc::mir::visit::{MutVisitor, PlaceContext, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_index::vec::IndexVec; @@ -62,6 +62,25 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { debug!("visit_ty: ty={:?}", ty); } + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + if let PlaceElem::Field(field, ty) = elem { + PlaceElem::Field(*field, self.renumber_regions(ty)) + } else { + elem.clone() + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } + fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { debug!("visit_substs(substs={:?}, location={:?})", substs, location); From e3e99516730f72fa05cb964ae341156e1ca85c39 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 18:23:39 -0300 Subject: [PATCH 505/545] Prepare inline MutVisitor to have projections interned --- src/librustc_mir/transform/inline.rs | 53 +++++++++++++++++++--------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 9830ed35ffc3..3a71d22da787 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -647,38 +647,45 @@ fn update_target(&self, tgt: BasicBlock) -> BasicBlock { debug!("updating target `{:?}`, new: `{:?}`", tgt, new); new } -} -impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { - fn visit_local(&mut self, - local: &mut Local, - _ctxt: PlaceContext, - _location: Location) { + fn make_integrate_local(&self, local: &Local) -> Local { if *local == RETURN_PLACE { match self.destination { Place { base: PlaceBase::Local(l), projection: box [], } => { - *local = l; - return; + return l; }, ref place => bug!("Return place is {:?}, not local", place) } } + let idx = local.index() - 1; if idx < self.args.len() { - *local = self.args[idx]; - return; + return self.args[idx]; } - *local = self.local_map[Local::new(idx - self.args.len())]; + + self.local_map[Local::new(idx - self.args.len())] + } +} + +impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { + fn visit_local( + &mut self, + local: &mut Local, + _ctxt: PlaceContext, + _location: Location, + ) { + *local = self.make_integrate_local(local); } - fn visit_place(&mut self, - place: &mut Place<'tcx>, - _ctxt: PlaceContext, - _location: Location) { - + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { match place { Place { base: PlaceBase::Local(RETURN_PLACE), @@ -687,7 +694,19 @@ fn visit_place(&mut self, // Return pointer; update the place itself *place = self.destination.clone(); }, - _ => self.super_place(place, _ctxt, _location) + _ => { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + if let PlaceElem::Index(local) = elem { + PlaceElem::Index(self.make_integrate_local(local)) + } else { + elem.clone() + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } } From 0fc063f15936761024183a3bb3790684d5de3bd3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 19:14:35 -0300 Subject: [PATCH 506/545] Prepare generator MutVisitor to have projections interned --- src/librustc_mir/transform/generator.rs | 52 +++++++++++++++++++++---- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 865fa012c299..a801548efab0 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -88,6 +88,24 @@ fn visit_local(&mut self, *local = self.to; } } + + fn visit_place(&mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + match elem { + PlaceElem::Index(local) if *local == self.from => { + PlaceElem::Index(self.to) + } + _ => elem.clone(), + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } struct DerefArgVisitor; @@ -110,7 +128,13 @@ fn visit_place(&mut self, projection: Box::new([ProjectionElem::Deref]), }); } else { - self.super_place(place, context, location); + self.visit_place_base(&mut place.base, context, location); + + for elem in place.projection.iter() { + if let PlaceElem::Index(local) = elem { + assert_ne!(*local, self_arg()); + } + } } } } @@ -137,7 +161,13 @@ fn visit_place(&mut self, projection: Box::new([ProjectionElem::Field(Field::new(0), self.ref_gen_ty)]), }); } else { - self.super_place(place, context, location); + self.visit_place_base(&mut place.base, context, location); + + for elem in place.projection.iter() { + if let PlaceElem::Index(local) = elem { + assert_ne!(*local, self_arg()); + } + } } } } @@ -247,17 +277,25 @@ fn visit_local(&mut self, assert_eq!(self.remap.get(local), None); } - fn visit_place(&mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location) { + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { if let PlaceBase::Local(l) = place.base { // Replace an Local in the remap with a generator struct access if let Some(&(ty, variant_index, idx)) = self.remap.get(&l) { replace_base(place, self.make_field(variant_index, idx, ty)); } } else { - self.super_place(place, context, location); + self.visit_place_base(&mut place.base, context, location); + + for elem in place.projection.iter() { + if let PlaceElem::Index(local) = elem { + assert_ne!(*local, self_arg()); + } + } } } From 39c9ed3ac19b3f6c79069d32a317daa763371369 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 7 Oct 2019 19:35:41 -0300 Subject: [PATCH 507/545] Prepare erase_regions MutVisitor to have projections interned --- src/librustc_mir/transform/erase_regions.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index e9ce84a25838..132149d5d433 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -7,7 +7,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::*; -use rustc::mir::visit::{MutVisitor, TyContext}; +use rustc::mir::visit::{MutVisitor, PlaceContext, TyContext}; use crate::transform::{MirPass, MirSource}; struct EraseRegionsVisitor<'tcx> { @@ -38,6 +38,25 @@ fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) { fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) { *substs = self.tcx.erase_regions(substs); } + + fn visit_place( + &mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, + ) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + if let PlaceElem::Field(field, ty) = elem { + PlaceElem::Field(*field, self.tcx.erase_regions(ty)) + } else { + elem.clone() + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } pub struct EraseRegions; From 2b2e35bfc34618cff7b62a7726ee3a97101d3fa2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 00:24:18 -0300 Subject: [PATCH 508/545] Prepare def_use MutVisitor to have projections interned --- src/librustc_mir/util/def_use.rs | 36 ++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 3aea25fa8769..d90be90bd9d4 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -1,6 +1,6 @@ //! Def-use analysis. -use rustc::mir::{Local, Location, Body}; +use rustc::mir::{Body, Local, Location, Place, PlaceElem}; use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; use rustc_index::vec::IndexVec; use std::mem; @@ -47,13 +47,13 @@ pub fn local_info(&self, local: Local) -> &Info { &self.info[local] } - fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, mut callback: F) - where F: for<'a> FnMut(&'a mut Local, + fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, callback: F) + where F: for<'a> Fn(&'a Local, PlaceContext, - Location) { + Location) -> Local { for place_use in &self.info[local].defs_and_uses { MutateUseVisitor::new(local, - &mut callback, + &callback, body).visit_location(body, place_use.location) } } @@ -63,7 +63,7 @@ pub fn replace_all_defs_and_uses_with(&self, local: Local, body: &mut Body<'_>, new_local: Local) { - self.mutate_defs_and_uses(local, body, |local, _, _| *local = new_local) + self.mutate_defs_and_uses(local, body, |_, _, _| new_local) } } @@ -125,7 +125,7 @@ struct MutateUseVisitor { impl MutateUseVisitor { fn new(query: Local, callback: F, _: &Body<'_>) -> MutateUseVisitor - where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) { + where F: for<'a> Fn(&'a Local, PlaceContext, Location) -> Local { MutateUseVisitor { query, callback, @@ -134,13 +134,31 @@ fn new(query: Local, callback: F, _: &Body<'_>) } impl MutVisitor<'_> for MutateUseVisitor - where F: for<'a> FnMut(&'a mut Local, PlaceContext, Location) { + where F: for<'a> Fn(&'a Local, PlaceContext, Location) -> Local { fn visit_local(&mut self, local: &mut Local, context: PlaceContext, location: Location) { if *local == self.query { - (self.callback)(local, context, location) + *local = (self.callback)(local, context, location) } } + + fn visit_place(&mut self, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location) { + self.visit_place_base(&mut place.base, context, location); + + let new_projection: Vec<_> = place.projection.iter().map(|elem| + match elem { + PlaceElem::Index(local) if *local == self.query => { + PlaceElem::Index((self.callback)(&local, context, location)) + } + _ => elem.clone(), + } + ).collect(); + + place.projection = new_projection.into_boxed_slice(); + } } From 4f2a11036d085227e261824a1aa76dd752c84267 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 00:33:47 -0300 Subject: [PATCH 509/545] Remove unneeded callback and just use the new_local value --- src/librustc_mir/util/def_use.rs | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index d90be90bd9d4..5b5f7d83f074 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -47,13 +47,10 @@ pub fn local_info(&self, local: Local) -> &Info { &self.info[local] } - fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, callback: F) - where F: for<'a> Fn(&'a Local, - PlaceContext, - Location) -> Local { + fn mutate_defs_and_uses(&self, local: Local, body: &mut Body<'_>, new_local: Local) { for place_use in &self.info[local].defs_and_uses { MutateUseVisitor::new(local, - &callback, + new_local, body).visit_location(body, place_use.location) } } @@ -63,7 +60,7 @@ pub fn replace_all_defs_and_uses_with(&self, local: Local, body: &mut Body<'_>, new_local: Local) { - self.mutate_defs_and_uses(local, body, |_, _, _| new_local) + self.mutate_defs_and_uses(local, body, new_local) } } @@ -117,30 +114,27 @@ pub fn use_count(&self) -> usize { } } -struct MutateUseVisitor { +struct MutateUseVisitor { query: Local, - callback: F, + new_local: Local, } -impl MutateUseVisitor { - fn new(query: Local, callback: F, _: &Body<'_>) - -> MutateUseVisitor - where F: for<'a> Fn(&'a Local, PlaceContext, Location) -> Local { +impl MutateUseVisitor { + fn new(query: Local, new_local: Local, _: &Body<'_>) -> MutateUseVisitor { MutateUseVisitor { query, - callback, + new_local, } } } -impl MutVisitor<'_> for MutateUseVisitor - where F: for<'a> Fn(&'a Local, PlaceContext, Location) -> Local { +impl MutVisitor<'_> for MutateUseVisitor { fn visit_local(&mut self, local: &mut Local, - context: PlaceContext, - location: Location) { + _context: PlaceContext, + _location: Location) { if *local == self.query { - *local = (self.callback)(local, context, location) + *local = self.new_local; } } @@ -153,7 +147,7 @@ fn visit_place(&mut self, let new_projection: Vec<_> = place.projection.iter().map(|elem| match elem { PlaceElem::Index(local) if *local == self.query => { - PlaceElem::Index((self.callback)(&local, context, location)) + PlaceElem::Index(self.new_local) } _ => elem.clone(), } From 7fa3425ef675b4bf4177dc2ea232078f4556b4c4 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 12:16:26 -0300 Subject: [PATCH 510/545] Setup a different visit place set of methods for mutable and immutable visitors In particular, use a blank visit_place for mutable visitor to be sure, non modified visitors are not trying to mutating place. --- src/librustc/mir/visit.rs | 180 ++++++++++++++++++++++---------------- 1 file changed, 103 insertions(+), 77 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index edc7922f46ee..0fb43c7f98d1 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -158,22 +158,7 @@ fn visit_place_base(&mut self, self.super_place_base(base, context, location); } - fn visit_projection(&mut self, - base: & $($mutability)? PlaceBase<'tcx>, - projection: & $($mutability)? [PlaceElem<'tcx>], - context: PlaceContext, - location: Location) { - self.super_projection(base, projection, context, location); - } - - fn visit_projection_elem(&mut self, - base: & $($mutability)? PlaceBase<'tcx>, - proj_base: & $($mutability)? [PlaceElem<'tcx>], - elem: & $($mutability)? PlaceElem<'tcx>, - context: PlaceContext, - location: Location) { - self.super_projection_elem(base, proj_base, elem, context, location); - } + visit_place_fns!($($mutability)?); fn visit_constant(&mut self, constant: & $($mutability)? Constant<'tcx>, @@ -681,28 +666,6 @@ fn super_retag(&mut self, ); } - fn super_place(&mut self, - place: & $($mutability)? Place<'tcx>, - context: PlaceContext, - location: Location) { - let mut context = context; - - if !place.projection.is_empty() { - context = if context.is_mutating_use() { - PlaceContext::MutatingUse(MutatingUseContext::Projection) - } else { - PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) - }; - } - - self.visit_place_base(& $($mutability)? place.base, context, location); - - self.visit_projection(& $($mutability)? place.base, - & $($mutability)? place.projection, - context, - location); - } - fn super_place_base(&mut self, place_base: & $($mutability)? PlaceBase<'tcx>, context: PlaceContext, @@ -717,45 +680,6 @@ fn super_place_base(&mut self, } } - fn super_projection(&mut self, - base: & $($mutability)? PlaceBase<'tcx>, - projection: & $($mutability)? [PlaceElem<'tcx>], - context: PlaceContext, - location: Location) { - let mut cursor = projection; - while let [proj_base @ .., elem] = cursor { - cursor = proj_base; - self.visit_projection_elem(base, cursor, elem, context, location); - } - } - - fn super_projection_elem(&mut self, - _base: & $($mutability)? PlaceBase<'tcx>, - _proj_base: & $($mutability)? [PlaceElem<'tcx>], - elem: & $($mutability)? PlaceElem<'tcx>, - _context: PlaceContext, - location: Location) { - match elem { - ProjectionElem::Field(_field, ty) => { - self.visit_ty(ty, TyContext::Location(location)); - } - ProjectionElem::Index(local) => { - self.visit_local( - local, - PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), - location - ); - } - ProjectionElem::Deref | - ProjectionElem::Subslice { from: _, to: _ } | - ProjectionElem::ConstantIndex { offset: _, - min_length: _, - from_end: _ } | - ProjectionElem::Downcast(_, _) => { - } - } - } - fn super_local_decl(&mut self, local: Local, local_decl: & $($mutability)? LocalDecl<'tcx>) { @@ -858,6 +782,108 @@ fn visit_location(&mut self, body: & $($mutability)? Body<'tcx>, location: Locat } } +macro_rules! visit_place_fns { + (mut) => ( + fn super_place( + &mut self, + _place: &mut Place<'tcx>, + _context: PlaceContext, + _location: Location, + ) { + } + ); + + () => ( + fn visit_projection( + &mut self, + base: &PlaceBase<'tcx>, + projection: &[PlaceElem<'tcx>], + context: PlaceContext, + location: Location, + ) { + self.super_projection(base, projection, context, location); + } + + fn visit_projection_elem( + &mut self, + base: &PlaceBase<'tcx>, + proj_base: &[PlaceElem<'tcx>], + elem: &PlaceElem<'tcx>, + context: PlaceContext, + location: Location, + ) { + self.super_projection_elem(base, proj_base, elem, context, location); + } + + fn super_place( + &mut self, + place: &Place<'tcx>, + context: PlaceContext, + location: Location, + ) { + let mut context = context; + + if !place.projection.is_empty() { + context = if context.is_mutating_use() { + PlaceContext::MutatingUse(MutatingUseContext::Projection) + } else { + PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) + }; + } + + self.visit_place_base(&place.base, context, location); + + self.visit_projection(&place.base, + &place.projection, + context, + location); + } + + fn super_projection( + &mut self, + base: &PlaceBase<'tcx>, + projection: &[PlaceElem<'tcx>], + context: PlaceContext, + location: Location, + ) { + let mut cursor = projection; + while let [proj_base @ .., elem] = cursor { + cursor = proj_base; + self.visit_projection_elem(base, cursor, elem, context, location); + } + } + + fn super_projection_elem( + &mut self, + _base: &PlaceBase<'tcx>, + _proj_base: &[PlaceElem<'tcx>], + elem: &PlaceElem<'tcx>, + _context: PlaceContext, + location: Location, + ) { + match elem { + ProjectionElem::Field(_field, ty) => { + self.visit_ty(ty, TyContext::Location(location)); + } + ProjectionElem::Index(local) => { + self.visit_local( + local, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy), + location + ); + } + ProjectionElem::Deref | + ProjectionElem::Subslice { from: _, to: _ } | + ProjectionElem::ConstantIndex { offset: _, + min_length: _, + from_end: _ } | + ProjectionElem::Downcast(_, _) => { + } + } + } + ); +} + make_mir_visitor!(Visitor,); make_mir_visitor!(MutVisitor,mut); From d53fc9cae5b17c138be09383dea8b8f10d3df3a1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 15:33:19 -0300 Subject: [PATCH 511/545] Add process_* place hooks to improve code reutilization --- src/librustc/mir/visit.rs | 28 +++++++++++++++++-- src/librustc_mir/borrow_check/nll/renumber.rs | 28 +++++++------------ src/librustc_mir/transform/erase_regions.rs | 26 ++++++----------- src/librustc_mir/transform/inline.rs | 23 +++++++-------- src/librustc_mir/transform/promote_consts.rs | 24 ++++++---------- src/librustc_mir/transform/simplify.rs | 24 ++++++---------- src/librustc_mir/util/def_use.rs | 26 +++++++---------- 7 files changed, 82 insertions(+), 97 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 0fb43c7f98d1..c8a6367899ba 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -786,10 +786,32 @@ macro_rules! visit_place_fns { (mut) => ( fn super_place( &mut self, - _place: &mut Place<'tcx>, - _context: PlaceContext, - _location: Location, + place: &mut Place<'tcx>, + context: PlaceContext, + location: Location, ) { + self.visit_place_base(&mut place.base, context, location); + + place.projection = self.process_projection(&place.projection); + } + + fn process_projection( + &mut self, + projection: &Box<[PlaceElem<'tcx>]>, + ) -> Box<[PlaceElem<'tcx>]> { + let new_projection: Vec<_> = projection.iter().map(|elem| + self.process_projection_elem(elem) + ).collect(); + + new_projection.into_boxed_slice() + } + + fn process_projection_elem( + &mut self, + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + // FIXME: avoid cloning here + elem.clone() } ); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 6eb5735cb16b..c4a19ce5128b 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,7 +1,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc::mir::{Body, Location, Place, PlaceElem, Promoted}; -use rustc::mir::visit::{MutVisitor, PlaceContext, TyContext}; +use rustc::mir::{Body, Location, PlaceElem, Promoted}; +use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc_index::vec::IndexVec; @@ -62,23 +62,15 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { debug!("visit_ty: ty={:?}", ty); } - fn visit_place( + fn process_projection_elem( &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.renumber_regions(ty)) - } else { - elem.clone() - } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + if let PlaceElem::Field(field, ty) = elem { + PlaceElem::Field(*field, self.renumber_regions(ty)) + } else { + elem.clone() + } } fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 132149d5d433..725a8de8fe7d 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -7,7 +7,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; use rustc::mir::*; -use rustc::mir::visit::{MutVisitor, PlaceContext, TyContext}; +use rustc::mir::visit::{MutVisitor, TyContext}; use crate::transform::{MirPass, MirSource}; struct EraseRegionsVisitor<'tcx> { @@ -39,23 +39,15 @@ fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) { *substs = self.tcx.erase_regions(substs); } - fn visit_place( + fn process_projection_elem( &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.tcx.erase_regions(ty)) - } else { - elem.clone() - } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + if let PlaceElem::Field(field, ty) = elem { + PlaceElem::Field(*field, self.tcx.erase_regions(ty)) + } else { + elem.clone() + } } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 3a71d22da787..dd13d0c96557 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -695,21 +695,22 @@ fn visit_place( *place = self.destination.clone(); }, _ => { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - if let PlaceElem::Index(local) = elem { - PlaceElem::Index(self.make_integrate_local(local)) - } else { - elem.clone() - } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + self.super_place(place, context, location); } } } + fn process_projection_elem( + &mut self, + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + if let PlaceElem::Index(local) = elem { + PlaceElem::Index(self.make_integrate_local(local)) + } else { + elem.clone() + } + } + fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { self.in_cleanup_block = data.is_cleanup; self.super_basic_block_data(block, data); diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index d1c79c5ae2ad..565f260546bc 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -405,24 +405,16 @@ fn visit_local(&mut self, } } - fn visit_place( + fn process_projection_elem( &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - match elem { - PlaceElem::Index(local) if self.is_temp_kind(*local) => { - PlaceElem::Index(self.promote_temp(*local)) - } - _ => elem.clone(), + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + match elem { + PlaceElem::Index(local) if self.is_temp_kind(*local) => { + PlaceElem::Index(self.promote_temp(*local)) } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + _ => elem.clone(), + } } } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 57bc1c8fab96..7dca3e357cc9 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -371,22 +371,14 @@ fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) { *l = self.map[*l].unwrap(); } - fn visit_place( + fn process_projection_elem( &mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location, - ) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - if let PlaceElem::Index(local) = elem { - PlaceElem::Index(self.map[*local].unwrap()) - } else { - elem.clone() - } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + if let PlaceElem::Index(local) = elem { + PlaceElem::Index(self.map[*local].unwrap()) + } else { + elem.clone() + } } } diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 5b5f7d83f074..25930df020aa 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -1,6 +1,6 @@ //! Def-use analysis. -use rustc::mir::{Body, Local, Location, Place, PlaceElem}; +use rustc::mir::{Body, Local, Location, PlaceElem}; use rustc::mir::visit::{PlaceContext, MutVisitor, Visitor}; use rustc_index::vec::IndexVec; use std::mem; @@ -138,21 +138,15 @@ fn visit_local(&mut self, } } - fn visit_place(&mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - match elem { - PlaceElem::Index(local) if *local == self.query => { - PlaceElem::Index(self.new_local) - } - _ => elem.clone(), + fn process_projection_elem( + &mut self, + elem: &PlaceElem<'tcx>, + ) -> PlaceElem<'tcx> { + match elem { + PlaceElem::Index(local) if *local == self.query => { + PlaceElem::Index(self.new_local) } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + _ => elem.clone(), + } } } From d0eaf60d5e4bd0d5be63a41ed9ff861dca95c932 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Oct 2019 09:30:28 +1100 Subject: [PATCH 512/545] Remove two no-op `into()` calls. --- 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 9cb410a8ae31..6bbd8be0cb98 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -285,10 +285,10 @@ fn next_desugared(&mut self) -> Token { token::NoDelim, &if doc_comment_style(&name.as_str()) == AttrStyle::Inner { [TokenTree::token(token::Pound, sp), TokenTree::token(token::Not, sp), body] - .iter().cloned().collect::().into() + .iter().cloned().collect::() } else { [TokenTree::token(token::Pound, sp), body] - .iter().cloned().collect::().into() + .iter().cloned().collect::() }, ))); From a6eef299d3b0ca24f8ffc0c3dc03283c09ec7945 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 14 Oct 2019 10:37:21 +1100 Subject: [PATCH 513/545] Make `TokenStream::from_iter` less general and more efficient. The current code has this impl: ``` impl> iter::FromIterator for TokenStream ``` If given an `IntoIterator`, it will convert each individual `TokenTree` to a `TokenStream` (at the cost of two allocations: a `Vec` and an `Lrc`). It will then merge those `TokenStream`s into a single `TokenStream`. This is inefficient. This commit changes the impl to this less general one: ``` impl iter::FromIterator for TokenStream ``` It collects the `TokenTree`s into a single `Vec` first and then converts that to a `TokenStream` by wrapping it in a single `Lrc`. The previous generality was unnecessary; no other code needs changing. This change speeds up several benchmarks by up to 4%. --- src/libsyntax/tokenstream.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index db6832d64232..3d89e73d729f 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -202,9 +202,9 @@ fn from(tree: TokenTree) -> TreeAndJoint { } } -impl> iter::FromIterator for TokenStream { - fn from_iter>(iter: I) -> Self { - TokenStream::from_streams(iter.into_iter().map(Into::into).collect::>()) +impl iter::FromIterator for TokenStream { + fn from_iter>(iter: I) -> Self { + TokenStream::new(iter.into_iter().map(Into::into).collect::>()) } } From 212ae58f36e4c9f2e0f46153f1c50a657e6c25db Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 14 Oct 2019 11:24:46 +1100 Subject: [PATCH 514/545] Change `Lit::tokens()` to `Lit::token_tree()`. Because most of the call sites have an easier time working with a `TokenTree` instead of a `TokenStream`. --- src/libsyntax/attr/mod.rs | 9 +++++---- src/libsyntax/parse/literal.rs | 8 ++++---- src/libsyntax/parse/parser/attr.rs | 9 ++++----- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 402c2cad72f9..8786c850bfdd 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -541,9 +541,10 @@ pub fn tokens(&self, span: Span) -> TokenStream { match *self { 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); - TokenStream::new(vec) + TokenStream::new(vec![ + TokenTree::token(token::Eq, span).into(), + lit.token_tree().into(), + ]) } MetaItemKind::List(ref list) => { let mut tokens = Vec::new(); @@ -606,7 +607,7 @@ pub fn span(&self) -> Span { fn tokens(&self) -> TokenStream { match *self { NestedMetaItem::MetaItem(ref item) => item.tokens(), - NestedMetaItem::Literal(ref lit) => lit.tokens(), + NestedMetaItem::Literal(ref lit) => lit.token_tree().into(), } } diff --git a/src/libsyntax/parse/literal.rs b/src/libsyntax/parse/literal.rs index 14e1696610a4..7952e293a532 100644 --- a/src/libsyntax/parse/literal.rs +++ b/src/libsyntax/parse/literal.rs @@ -3,7 +3,7 @@ use crate::ast::{self, Lit, LitKind}; use crate::parse::token::{self, Token}; use crate::symbol::{kw, sym, Symbol}; -use crate::tokenstream::{TokenStream, TokenTree}; +use crate::tokenstream::TokenTree; use log::debug; use rustc_data_structures::sync::Lrc; @@ -216,13 +216,13 @@ pub fn from_lit_kind(kind: LitKind, span: Span) -> Lit { Lit { token: kind.to_lit_token(), kind, span } } - /// Losslessly convert an AST literal into a token stream. - crate fn tokens(&self) -> TokenStream { + /// Losslessly convert an AST literal into a token tree. + crate fn token_tree(&self) -> TokenTree { let token = match self.token.kind { token::Bool => token::Ident(self.token.symbol, false), _ => token::Literal(self.token), }; - TokenTree::token(token, self.span).into() + TokenTree::token(token, self.span) } } diff --git a/src/libsyntax/parse/parser/attr.rs b/src/libsyntax/parse/parser/attr.rs index 6f7d1ead4c17..188a144cac9d 100644 --- a/src/libsyntax/parse/parser/attr.rs +++ b/src/libsyntax/parse/parser/attr.rs @@ -6,7 +6,6 @@ use crate::source_map::Span; use log::debug; -use smallvec::smallvec; #[derive(Debug)] enum InnerAttributeParsePolicy<'a> { @@ -193,15 +192,15 @@ pub fn parse_attr_item(&mut self) -> PResult<'a, ast::AttrItem> { is_interpolated_expr = true; } } - let tokens = if is_interpolated_expr { + let token_tree = if is_interpolated_expr { // We need to accept arbitrary interpolated expressions to continue // supporting things like `doc = $expr` that work on stable. // Non-literal interpolated expressions are rejected after expansion. - self.parse_token_tree().into() + self.parse_token_tree() } else { - self.parse_unsuffixed_lit()?.tokens() + self.parse_unsuffixed_lit()?.token_tree() }; - TokenStream::from_streams(smallvec![eq.into(), tokens]) + TokenStream::new(vec![eq.into(), token_tree.into()]) } else { TokenStream::default() }; From e4ec4a6da350ae2564971ae826a1bc3ec9a41988 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 14 Oct 2019 14:06:00 +1100 Subject: [PATCH 515/545] Change `MetaItem::tokens()` to `MetaItem::token_trees_and_joints()`. Likewise for `NestedMetaItem::tokens()`. Also, add `MetaItemKind::token_trees_and_joints()`, which `MetaItemKind::tokens()` now calls. This avoids some unnecessary `TokenTree` to `TokenStream` conversions, and removes the need for the clumsy `TokenStream::append_to_tree_and_joint_vec()`. --- src/libsyntax/attr/mod.rs | 43 ++++++++++++++++++++++-------------- src/libsyntax/tokenstream.rs | 4 ---- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 8786c850bfdd..4aec50408812 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -22,7 +22,7 @@ use crate::sess::ParseSess; use crate::symbol::{sym, Symbol}; use crate::ThinVec; -use crate::tokenstream::{TokenStream, TokenTree, DelimSpan}; +use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; use crate::GLOBALS; use log::debug; @@ -463,7 +463,7 @@ pub fn first_attr_value_str_by_name(attrs: &[Attribute], name: Symbol) -> Option } impl MetaItem { - fn tokens(&self) -> TokenStream { + fn token_trees_and_joints(&self) -> Vec { let mut idents = vec![]; let mut last_pos = BytePos(0 as u32); for (i, segment) in self.path.segments.iter().enumerate() { @@ -477,8 +477,8 @@ fn tokens(&self) -> TokenStream { idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into()); last_pos = segment.ident.span.hi(); } - self.kind.tokens(self.span).append_to_tree_and_joint_vec(&mut idents); - TokenStream::new(idents) + idents.extend(self.kind.token_trees_and_joints(self.span)); + idents } fn from_tokens(tokens: &mut iter::Peekable) -> Option @@ -537,14 +537,14 @@ fn from_tokens(tokens: &mut iter::Peekable) -> Option } impl MetaItemKind { - pub fn tokens(&self, span: Span) -> TokenStream { + pub fn token_trees_and_joints(&self, span: Span) -> Vec { match *self { - MetaItemKind::Word => TokenStream::default(), + MetaItemKind::Word => vec![], MetaItemKind::NameValue(ref lit) => { - TokenStream::new(vec![ + vec![ TokenTree::token(token::Eq, span).into(), lit.token_tree().into(), - ]) + ] } MetaItemKind::List(ref list) => { let mut tokens = Vec::new(); @@ -552,17 +552,26 @@ pub fn tokens(&self, span: Span) -> TokenStream { if i > 0 { tokens.push(TokenTree::token(token::Comma, span).into()); } - item.tokens().append_to_tree_and_joint_vec(&mut tokens); + tokens.extend(item.token_trees_and_joints()) } - TokenTree::Delimited( - DelimSpan::from_single(span), - token::Paren, - TokenStream::new(tokens).into(), - ).into() + vec![ + TokenTree::Delimited( + DelimSpan::from_single(span), + token::Paren, + TokenStream::new(tokens).into(), + ).into() + ] } } } + // Premature conversions of `TokenTree`s to `TokenStream`s can hurt + // performance. Do not use this function if `token_trees_and_joints()` can + // be used instead. + pub fn tokens(&self, span: Span) -> TokenStream { + TokenStream::new(self.token_trees_and_joints(span)) + } + fn from_tokens(tokens: &mut iter::Peekable) -> Option where I: Iterator, { @@ -604,10 +613,10 @@ pub fn span(&self) -> Span { } } - fn tokens(&self) -> TokenStream { + fn token_trees_and_joints(&self) -> Vec { match *self { - NestedMetaItem::MetaItem(ref item) => item.tokens(), - NestedMetaItem::Literal(ref lit) => lit.token_tree().into(), + NestedMetaItem::MetaItem(ref item) => item.token_trees_and_joints(), + NestedMetaItem::Literal(ref lit) => vec![lit.token_tree().into()], } } diff --git a/src/libsyntax/tokenstream.rs b/src/libsyntax/tokenstream.rs index 3d89e73d729f..ac155556cdae 100644 --- a/src/libsyntax/tokenstream.rs +++ b/src/libsyntax/tokenstream.rs @@ -271,10 +271,6 @@ pub fn len(&self) -> usize { } } - pub fn append_to_tree_and_joint_vec(self, vec: &mut Vec) { - vec.extend(self.0.iter().cloned()); - } - pub fn trees(&self) -> Cursor { self.clone().into_trees() } From d8fca9ee4ea9399dc8244f744f0198821d233ecf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Oct 2019 09:24:56 +1100 Subject: [PATCH 516/545] Use `with` in `Symbol` trait methods. Instead of `as_str()`, which unnecessarily involves `LocalInternedString`. --- src/libsyntax_pos/symbol.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index 8845b66a7cef..e4f309259e7c 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -934,19 +934,19 @@ pub fn as_u32(self) -> u32 { impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) + self.with(|str| fmt::Display::fmt(&str, f)) } } impl fmt::Display for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(&self.as_str(), f) + self.with(|str| fmt::Display::fmt(&str, f)) } } impl Encodable for Symbol { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self.as_str()) + self.with(|string| s.emit_str(string)) } } From 3532863a96499df049589aa5120db149498ab544 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Oct 2019 10:06:23 +1100 Subject: [PATCH 517/545] Change how `Symbol::Debug` works. Currently, `Symbol::Debug` and `Symbol::Display` produce the same output; neither wraps the symbol in double quotes. This commit changes `Symbol::Debug` so it wraps the symbol in quotes. This change brings `Symbol`'s behaviour in line with `String` and `InternedString`. The change requires a couple of trivial test output adjustments. --- src/libsyntax_pos/symbol.rs | 2 +- src/test/ui/hygiene/unpretty-debug.stdout | 2 +- .../lint/redundant-semicolon/redundant-semi-proc-macro.stderr | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index e4f309259e7c..efb01ff84dcd 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -934,7 +934,7 @@ pub fn as_u32(self) -> u32 { impl fmt::Debug for Symbol { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.with(|str| fmt::Display::fmt(&str, f)) + self.with(|str| fmt::Debug::fmt(&str, f)) } } diff --git a/src/test/ui/hygiene/unpretty-debug.stdout b/src/test/ui/hygiene/unpretty-debug.stdout index 6971873ba601..acd852103cae 100644 --- a/src/test/ui/hygiene/unpretty-debug.stdout +++ b/src/test/ui/hygiene/unpretty-debug.stdout @@ -17,7 +17,7 @@ fn y /* 0#0 */() { } /* Expansions: 0: parent: ExpnId(0), call_site_ctxt: #0, kind: Root -1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, foo) +1: parent: ExpnId(0), call_site_ctxt: #0, kind: Macro(Bang, "foo") SyntaxContexts: #0: parent: #0, outer_mark: (ExpnId(0), Opaque) diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr index 5f289c0914d6..2160df51a837 100644 --- a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -1,4 +1,4 @@ -TokenStream [Ident { ident: "fn", span: #0 bytes(197..199) }, Ident { ident: "span_preservation", span: #0 bytes(200..217) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(217..219) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(227..230) }, Ident { ident: "tst", span: #0 bytes(231..234) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(235..236) }, Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(237), hi: BytePos(240), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(240..241) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(241..242) }, Ident { ident: "match", span: #0 bytes(288..293) }, Ident { ident: "tst", span: #0 bytes(294..297) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: 123, suffix: None }, span: Span { lo: BytePos(482), hi: BytePos(485), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(486..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(486..488) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(489..491) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(491..492) }, Ident { ident: "_", span: #0 bytes(501..502) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(503..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(503..505) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(506..508) }], span: #0 bytes(298..514) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(514..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(516..517) }], span: #0 bytes(221..561) }] +TokenStream [Ident { ident: "fn", span: #0 bytes(197..199) }, Ident { ident: "span_preservation", span: #0 bytes(200..217) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(217..219) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(227..230) }, Ident { ident: "tst", span: #0 bytes(231..234) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(235..236) }, Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(237), hi: BytePos(240), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(240..241) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(241..242) }, Ident { ident: "match", span: #0 bytes(288..293) }, Ident { ident: "tst", span: #0 bytes(294..297) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(482), hi: BytePos(485), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(486..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(486..488) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(489..491) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(491..492) }, Ident { ident: "_", span: #0 bytes(501..502) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(503..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(503..505) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(506..508) }], span: #0 bytes(298..514) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(514..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(516..517) }], span: #0 bytes(221..561) }] error: unnecessary trailing semicolon --> $DIR/redundant-semi-proc-macro.rs:9:19 | From 43f398be6d0faaf119150c950133ba4aa0ff42b3 Mon Sep 17 00:00:00 2001 From: oxalica Date: Fri, 4 Oct 2019 16:17:23 +0800 Subject: [PATCH 518/545] Prefer statx on linux if available --- src/libstd/fs.rs | 22 ++++- src/libstd/sys/unix/fs.rs | 171 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 182 insertions(+), 11 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index fc26dcb32114..6595f54162f0 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1090,13 +1090,14 @@ pub fn accessed(&self) -> io::Result { /// Returns the creation time listed in this metadata. /// - /// The returned value corresponds to the `birthtime` field of `stat` on - /// Unix platforms and the `ftCreationTime` field on Windows platforms. + /// The returned value corresponds to the `btime` field of `statx` on + /// Linux kernel starting from to 4.11, the `birthtime` field of `stat` on other + /// Unix platforms, and the `ftCreationTime` field on Windows platforms. /// /// # Errors /// /// This field may not be available on all platforms, and will return an - /// `Err` on platforms where it is not available. + /// `Err` on platforms or filesystems where it is not available. /// /// # Examples /// @@ -1109,7 +1110,7 @@ pub fn accessed(&self) -> io::Result { /// if let Ok(time) = metadata.created() { /// println!("{:?}", time); /// } else { - /// println!("Not supported on this platform"); + /// println!("Not supported on this platform or filesystem"); /// } /// Ok(()) /// } @@ -3443,5 +3444,18 @@ fn metadata_access_times() { check!(a.created()); check!(b.created()); } + + if cfg!(target_os = "linux") { + // Not always available + match (a.created(), b.created()) { + (Ok(t1), Ok(t2)) => assert!(t1 <= t2), + (Err(e1), Err(e2)) if e1.kind() == ErrorKind::Other && + e2.kind() == ErrorKind::Other => {} + (a, b) => panic!( + "creation time must be always supported or not supported: {:?} {:?}", + a, b, + ), + } + } } } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 3b1eb86b84fe..8113fe38165b 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -44,6 +44,84 @@ #[derive(Clone)] pub struct FileAttr { stat: stat64, + #[cfg(target_os = "linux")] + statx_extra_fields: Option, +} + +#[cfg(target_os = "linux")] +#[derive(Clone)] +struct StatxExtraFields { + // This is needed to check if btime is supported by the filesystem. + stx_mask: u32, + stx_btime: libc::statx_timestamp, +} + +// We prefer `statx` on Linux if available, which contains file creation time. +// Default `stat64` contains no creation time. +#[cfg(target_os = "linux")] +unsafe fn try_statx( + fd: c_int, + path: *const libc::c_char, + flags: i32, + mask: u32, +) -> Option> { + use crate::sync::atomic::{AtomicBool, Ordering}; + + // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx` + // We store the availability in a global to avoid unnecessary syscalls + static HAS_STATX: AtomicBool = AtomicBool::new(true); + syscall! { + fn statx( + fd: c_int, + pathname: *const libc::c_char, + flags: c_int, + mask: libc::c_uint, + statxbuf: *mut libc::statx + ) -> c_int + } + + if !HAS_STATX.load(Ordering::Relaxed) { + return None; + } + + let mut buf: libc::statx = mem::zeroed(); + let ret = cvt(statx(fd, path, flags, mask, &mut buf)); + match ret { + Err(err) => match err.raw_os_error() { + Some(libc::ENOSYS) => { + HAS_STATX.store(false, Ordering::Relaxed); + return None; + } + _ => return Some(Err(err)), + } + Ok(_) => { + // We cannot fill `stat64` exhaustively because of private padding fields. + let mut stat: stat64 = mem::zeroed(); + stat.st_dev = libc::makedev(buf.stx_dev_major, buf.stx_dev_minor); + stat.st_ino = buf.stx_ino as libc::ino64_t; + stat.st_nlink = buf.stx_nlink as libc::nlink_t; + stat.st_mode = buf.stx_mode as libc::mode_t; + stat.st_uid = buf.stx_uid as libc::uid_t; + stat.st_gid = buf.stx_gid as libc::gid_t; + stat.st_rdev = libc::makedev(buf.stx_rdev_major, buf.stx_rdev_minor); + stat.st_size = buf.stx_size as off64_t; + stat.st_blksize = buf.stx_blksize as libc::blksize_t; + stat.st_blocks = buf.stx_blocks as libc::blkcnt64_t; + stat.st_atime = buf.stx_atime.tv_sec as libc::time_t; + stat.st_atime_nsec = buf.stx_atime.tv_nsec as libc::c_long; + stat.st_mtime = buf.stx_mtime.tv_sec as libc::time_t; + stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as libc::c_long; + stat.st_ctime = buf.stx_ctime.tv_sec as libc::time_t; + stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as libc::c_long; + + let extra = StatxExtraFields { + stx_mask: buf.stx_mask, + stx_btime: buf.stx_btime, + }; + + Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) })) + } + } } // all DirEntry's will have a reference to this struct @@ -98,6 +176,14 @@ pub struct FileType { mode: mode_t } pub struct DirBuilder { mode: mode_t } impl FileAttr { + fn from_stat64(stat: stat64) -> Self { + Self { + stat, + #[cfg(target_os = "linux")] + statx_extra_fields: None, + } + } + pub fn size(&self) -> u64 { self.stat.st_size as u64 } pub fn perm(&self) -> FilePermissions { FilePermissions { mode: (self.stat.st_mode as mode_t) } @@ -164,6 +250,23 @@ pub fn created(&self) -> io::Result { target_os = "macos", target_os = "ios")))] pub fn created(&self) -> io::Result { + #[cfg(target_os = "linux")] + { + if let Some(ext) = &self.statx_extra_fields { + return if (ext.stx_mask & libc::STATX_BTIME) != 0 { + Ok(SystemTime::from(libc::timespec { + tv_sec: ext.stx_btime.tv_sec as libc::time_t, + tv_nsec: ext.stx_btime.tv_nsec as libc::c_long, + })) + } else { + Err(io::Error::new( + io::ErrorKind::Other, + "creation time is not available for the filesystem", + )) + }; + } + } + Err(io::Error::new(io::ErrorKind::Other, "creation time is not available on this platform \ currently")) @@ -306,12 +409,26 @@ pub fn file_name(&self) -> OsString { #[cfg(any(target_os = "linux", target_os = "emscripten", target_os = "android"))] pub fn metadata(&self) -> io::Result { - let fd = cvt(unsafe {dirfd(self.dir.inner.dirp.0)})?; + let fd = cvt(unsafe { dirfd(self.dir.inner.dirp.0) })?; + let name = self.entry.d_name.as_ptr(); + + #[cfg(target_os = "linux")] + { + if let Some(ret) = unsafe { try_statx( + fd, + name, + libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_ALL, + ) } { + return ret; + } + } + let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { - fstatat64(fd, self.entry.d_name.as_ptr(), &mut stat, libc::AT_SYMLINK_NOFOLLOW) + fstatat64(fd, name, &mut stat, libc::AT_SYMLINK_NOFOLLOW) })?; - Ok(FileAttr { stat }) + Ok(FileAttr::from_stat64(stat)) } #[cfg(not(any(target_os = "linux", target_os = "emscripten", target_os = "android")))] @@ -517,11 +634,25 @@ fn ensure_cloexec(_: &FileDesc) -> io::Result<()> { } pub fn file_attr(&self) -> io::Result { + let fd = self.0.raw(); + + #[cfg(target_os = "linux")] + { + if let Some(ret) = unsafe { try_statx( + fd, + b"\0" as *const _ as *const libc::c_char, + libc::AT_EMPTY_PATH | libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_ALL, + ) } { + return ret; + } + } + let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { - fstat64(self.0.raw(), &mut stat) + fstat64(fd, &mut stat) })?; - Ok(FileAttr { stat }) + Ok(FileAttr::from_stat64(stat)) } pub fn fsync(&self) -> io::Result<()> { @@ -798,20 +929,46 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { pub fn stat(p: &Path) -> io::Result { let p = cstr(p)?; + + #[cfg(target_os = "linux")] + { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_ALL, + ) } { + return ret; + } + } + let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { stat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr { stat }) + Ok(FileAttr::from_stat64(stat)) } pub fn lstat(p: &Path) -> io::Result { let p = cstr(p)?; + + #[cfg(target_os = "linux")] + { + if let Some(ret) = unsafe { try_statx( + libc::AT_FDCWD, + p.as_ptr(), + libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_ALL, + ) } { + return ret; + } + } + let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { lstat64(p.as_ptr(), &mut stat) })?; - Ok(FileAttr { stat }) + Ok(FileAttr::from_stat64(stat)) } pub fn canonicalize(p: &Path) -> io::Result { From 15cb3e08e31660b94305abe5cc3abc8b79662c0f Mon Sep 17 00:00:00 2001 From: oxalica Date: Mon, 14 Oct 2019 07:17:15 +0800 Subject: [PATCH 519/545] Fix cfgs for current libc --- src/libstd/sys/unix/fs.rs | 234 +++++++++++++++++++++++--------------- 1 file changed, 142 insertions(+), 92 deletions(-) diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 8113fe38165b..fee6eecf864a 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -41,88 +41,137 @@ pub struct File(FileDesc); -#[derive(Clone)] -pub struct FileAttr { - stat: stat64, - #[cfg(target_os = "linux")] - statx_extra_fields: Option, -} - -#[cfg(target_os = "linux")] -#[derive(Clone)] -struct StatxExtraFields { - // This is needed to check if btime is supported by the filesystem. - stx_mask: u32, - stx_btime: libc::statx_timestamp, -} - -// We prefer `statx` on Linux if available, which contains file creation time. -// Default `stat64` contains no creation time. -#[cfg(target_os = "linux")] -unsafe fn try_statx( - fd: c_int, - path: *const libc::c_char, - flags: i32, - mask: u32, -) -> Option> { - use crate::sync::atomic::{AtomicBool, Ordering}; - - // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx` - // We store the availability in a global to avoid unnecessary syscalls - static HAS_STATX: AtomicBool = AtomicBool::new(true); - syscall! { - fn statx( - fd: c_int, - pathname: *const libc::c_char, - flags: c_int, - mask: libc::c_uint, - statxbuf: *mut libc::statx - ) -> c_int - } - - if !HAS_STATX.load(Ordering::Relaxed) { - return None; - } - - let mut buf: libc::statx = mem::zeroed(); - let ret = cvt(statx(fd, path, flags, mask, &mut buf)); - match ret { - Err(err) => match err.raw_os_error() { - Some(libc::ENOSYS) => { - HAS_STATX.store(false, Ordering::Relaxed); - return None; +// FIXME: This should be available on Linux with all `target_arch` and `target_env`. +// https://github.com/rust-lang/libc/issues/1545 +macro_rules! cfg_has_statx { + ({ $($then_tt:tt)* } else { $($else_tt:tt)* }) => { + cfg_if::cfg_if! { + if #[cfg(all(target_os = "linux", target_env = "gnu", any( + target_arch = "x86", + target_arch = "arm", + // target_arch = "mips", + target_arch = "powerpc", + target_arch = "x86_64", + // target_arch = "aarch64", + target_arch = "powerpc64", + // target_arch = "mips64", + // target_arch = "s390x", + target_arch = "sparc64", + )))] { + $($then_tt)* + } else { + $($else_tt)* } - _ => return Some(Err(err)), } - Ok(_) => { - // We cannot fill `stat64` exhaustively because of private padding fields. - let mut stat: stat64 = mem::zeroed(); - stat.st_dev = libc::makedev(buf.stx_dev_major, buf.stx_dev_minor); - stat.st_ino = buf.stx_ino as libc::ino64_t; - stat.st_nlink = buf.stx_nlink as libc::nlink_t; - stat.st_mode = buf.stx_mode as libc::mode_t; - stat.st_uid = buf.stx_uid as libc::uid_t; - stat.st_gid = buf.stx_gid as libc::gid_t; - stat.st_rdev = libc::makedev(buf.stx_rdev_major, buf.stx_rdev_minor); - stat.st_size = buf.stx_size as off64_t; - stat.st_blksize = buf.stx_blksize as libc::blksize_t; - stat.st_blocks = buf.stx_blocks as libc::blkcnt64_t; - stat.st_atime = buf.stx_atime.tv_sec as libc::time_t; - stat.st_atime_nsec = buf.stx_atime.tv_nsec as libc::c_long; - stat.st_mtime = buf.stx_mtime.tv_sec as libc::time_t; - stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as libc::c_long; - stat.st_ctime = buf.stx_ctime.tv_sec as libc::time_t; - stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as libc::c_long; + }; + ($($block_inner:tt)*) => { + #[cfg(all(target_os = "linux", target_env = "gnu", any( + target_arch = "x86", + target_arch = "arm", + // target_arch = "mips", + target_arch = "powerpc", + target_arch = "x86_64", + // target_arch = "aarch64", + target_arch = "powerpc64", + // target_arch = "mips64", + // target_arch = "s390x", + target_arch = "sparc64", + )))] + { + $($block_inner)* + } + }; +} - let extra = StatxExtraFields { - stx_mask: buf.stx_mask, - stx_btime: buf.stx_btime, - }; +cfg_has_statx! {{ + #[derive(Clone)] + pub struct FileAttr { + stat: stat64, + statx_extra_fields: Option, + } - Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) })) + #[derive(Clone)] + struct StatxExtraFields { + // This is needed to check if btime is supported by the filesystem. + stx_mask: u32, + stx_btime: libc::statx_timestamp, + } + + // We prefer `statx` on Linux if available, which contains file creation time. + // Default `stat64` contains no creation time. + unsafe fn try_statx( + fd: c_int, + path: *const libc::c_char, + flags: i32, + mask: u32, + ) -> Option> { + use crate::sync::atomic::{AtomicBool, Ordering}; + + // Linux kernel prior to 4.11 or glibc prior to glibc 2.28 don't support `statx` + // We store the availability in a global to avoid unnecessary syscalls + static HAS_STATX: AtomicBool = AtomicBool::new(true); + syscall! { + fn statx( + fd: c_int, + pathname: *const libc::c_char, + flags: c_int, + mask: libc::c_uint, + statxbuf: *mut libc::statx + ) -> c_int + } + + if !HAS_STATX.load(Ordering::Relaxed) { + return None; + } + + let mut buf: libc::statx = mem::zeroed(); + let ret = cvt(statx(fd, path, flags, mask, &mut buf)); + match ret { + Err(err) => match err.raw_os_error() { + Some(libc::ENOSYS) => { + HAS_STATX.store(false, Ordering::Relaxed); + return None; + } + _ => return Some(Err(err)), + } + Ok(_) => { + // We cannot fill `stat64` exhaustively because of private padding fields. + let mut stat: stat64 = mem::zeroed(); + // `c_ulong` on gnu-mips, `dev_t` otherwise + stat.st_dev = libc::makedev(buf.stx_dev_major, buf.stx_dev_minor) as _; + stat.st_ino = buf.stx_ino as libc::ino64_t; + stat.st_nlink = buf.stx_nlink as libc::nlink_t; + stat.st_mode = buf.stx_mode as libc::mode_t; + stat.st_uid = buf.stx_uid as libc::uid_t; + stat.st_gid = buf.stx_gid as libc::gid_t; + stat.st_rdev = libc::makedev(buf.stx_rdev_major, buf.stx_rdev_minor) as _; + stat.st_size = buf.stx_size as off64_t; + stat.st_blksize = buf.stx_blksize as libc::blksize_t; + stat.st_blocks = buf.stx_blocks as libc::blkcnt64_t; + stat.st_atime = buf.stx_atime.tv_sec as libc::time_t; + // `i64` on gnu-x86_64-x32, `c_ulong` otherwise. + stat.st_atime_nsec = buf.stx_atime.tv_nsec as _; + stat.st_mtime = buf.stx_mtime.tv_sec as libc::time_t; + stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as _; + stat.st_ctime = buf.stx_ctime.tv_sec as libc::time_t; + stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as _; + + let extra = StatxExtraFields { + stx_mask: buf.stx_mask, + stx_btime: buf.stx_btime, + }; + + Some(Ok(FileAttr { stat, statx_extra_fields: Some(extra) })) + } } } -} + +} else { + #[derive(Clone)] + pub struct FileAttr { + stat: stat64, + } +}} // all DirEntry's will have a reference to this struct struct InnerReadDir { @@ -175,15 +224,21 @@ pub struct FileType { mode: mode_t } #[derive(Debug)] pub struct DirBuilder { mode: mode_t } -impl FileAttr { - fn from_stat64(stat: stat64) -> Self { - Self { - stat, - #[cfg(target_os = "linux")] - statx_extra_fields: None, +cfg_has_statx! {{ + impl FileAttr { + fn from_stat64(stat: stat64) -> Self { + Self { stat, statx_extra_fields: None } } } +} else { + impl FileAttr { + fn from_stat64(stat: stat64) -> Self { + Self { stat } + } + } +}} +impl FileAttr { pub fn size(&self) -> u64 { self.stat.st_size as u64 } pub fn perm(&self) -> FilePermissions { FilePermissions { mode: (self.stat.st_mode as mode_t) } @@ -250,8 +305,7 @@ pub fn created(&self) -> io::Result { target_os = "macos", target_os = "ios")))] pub fn created(&self) -> io::Result { - #[cfg(target_os = "linux")] - { + cfg_has_statx! { if let Some(ext) = &self.statx_extra_fields { return if (ext.stx_mask & libc::STATX_BTIME) != 0 { Ok(SystemTime::from(libc::timespec { @@ -412,8 +466,7 @@ pub fn metadata(&self) -> io::Result { let fd = cvt(unsafe { dirfd(self.dir.inner.dirp.0) })?; let name = self.entry.d_name.as_ptr(); - #[cfg(target_os = "linux")] - { + cfg_has_statx! { if let Some(ret) = unsafe { try_statx( fd, name, @@ -636,8 +689,7 @@ fn ensure_cloexec(_: &FileDesc) -> io::Result<()> { pub fn file_attr(&self) -> io::Result { let fd = self.0.raw(); - #[cfg(target_os = "linux")] - { + cfg_has_statx! { if let Some(ret) = unsafe { try_statx( fd, b"\0" as *const _ as *const libc::c_char, @@ -930,8 +982,7 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> { pub fn stat(p: &Path) -> io::Result { let p = cstr(p)?; - #[cfg(target_os = "linux")] - { + cfg_has_statx! { if let Some(ret) = unsafe { try_statx( libc::AT_FDCWD, p.as_ptr(), @@ -952,8 +1003,7 @@ pub fn stat(p: &Path) -> io::Result { pub fn lstat(p: &Path) -> io::Result { let p = cstr(p)?; - #[cfg(target_os = "linux")] - { + cfg_has_statx! { if let Some(ret) = unsafe { try_statx( libc::AT_FDCWD, p.as_ptr(), From 2ee45c9da28c4de155f29d402eff1d22977cbdc7 Mon Sep 17 00:00:00 2001 From: oxalica Date: Fri, 18 Oct 2019 10:19:50 +0800 Subject: [PATCH 520/545] Fix cast of stx_btime.tv_nsec --- src/libstd/sys/unix/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index fee6eecf864a..13dd9f5f34f1 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -310,7 +310,7 @@ pub fn created(&self) -> io::Result { return if (ext.stx_mask & libc::STATX_BTIME) != 0 { Ok(SystemTime::from(libc::timespec { tv_sec: ext.stx_btime.tv_sec as libc::time_t, - tv_nsec: ext.stx_btime.tv_nsec as libc::c_long, + tv_nsec: ext.stx_btime.tv_nsec as _, })) } else { Err(io::Error::new( From f65a492afcd9cd892a1a5591f938efd41b5e0d24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 17 Oct 2019 20:26:21 -0700 Subject: [PATCH 521/545] Point at enclosing function without `self` receiver --- src/librustc_resolve/late.rs | 8 +++++++- src/librustc_resolve/late/diagnostics.rs | 3 +++ src/test/ui/error-codes/E0424.stderr | 14 ++++++++++---- src/test/ui/resolve/issue-2356.stderr | 18 ++++++++++++++---- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index bb9f895c5f39..73a282b1a0ec 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -345,6 +345,9 @@ struct LateResolutionVisitor<'a, 'b> { /// The current self item if inside an ADT (used for better errors). current_self_item: Option, + /// The current enclosing funciton (used for better errors). + current_function: Option, + /// A list of labels as of yet unused. Labels will be removed from this map when /// they are used (in a `break` or `continue` statement) unused_labels: FxHashMap, @@ -415,7 +418,8 @@ fn visit_foreign_item(&mut self, foreign_item: &'tcx ForeignItem) { } } } - fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span, _: NodeId) { + fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, sp: Span, _: NodeId) { + let previous_value = replace(&mut self.current_function, Some(sp)); debug!("(resolving function) entering function"); let rib_kind = match fn_kind { FnKind::ItemFn(..) => FnItemRibKind, @@ -441,6 +445,7 @@ fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, declaration: &'tcx FnDecl, _: Span debug!("(resolving function) leaving function"); }) }); + self.current_function = previous_value; } fn visit_generics(&mut self, generics: &'tcx Generics) { @@ -546,6 +551,7 @@ fn new(resolver: &'b mut Resolver<'a>) -> LateResolutionVisitor<'a, 'b> { current_trait_assoc_types: Vec::new(), current_self_type: None, current_self_item: None, + current_function: None, unused_labels: Default::default(), current_type_ascription: Vec::new(), } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index dba4226e9836..2721df4c6876 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -134,6 +134,9 @@ pub(crate) fn smart_resolve_report_errors( "`self` value is a keyword only available in methods with a `self` parameter", ), }); + if let Some(span) = &self.current_function { + err.span_label(*span, "this function doesn't have a `self` parameter"); + } return (err, Vec::new()); } diff --git a/src/test/ui/error-codes/E0424.stderr b/src/test/ui/error-codes/E0424.stderr index 99b5e01abb19..567d1b3cc75f 100644 --- a/src/test/ui/error-codes/E0424.stderr +++ b/src/test/ui/error-codes/E0424.stderr @@ -1,14 +1,20 @@ error[E0424]: expected value, found module `self` --> $DIR/E0424.rs:7:9 | -LL | self.bar(); - | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | / fn foo() { +LL | | self.bar(); + | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | | } + | |_____- this function doesn't have a `self` parameter error[E0424]: expected unit struct/variant or constant, found module `self` --> $DIR/E0424.rs:12:9 | -LL | let self = "self"; - | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed +LL | / fn main () { +LL | | let self = "self"; + | | ^^^^ `self` value is a keyword and may not be bound to variables or shadowed +LL | | } + | |_- this function doesn't have a `self` parameter error: aborting due to 2 previous errors diff --git a/src/test/ui/resolve/issue-2356.stderr b/src/test/ui/resolve/issue-2356.stderr index e0a2088ab8b9..329543114a61 100644 --- a/src/test/ui/resolve/issue-2356.stderr +++ b/src/test/ui/resolve/issue-2356.stderr @@ -61,8 +61,14 @@ LL | purr(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:65:8 | -LL | if self.whiskers > 3 { - | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | / fn meow() { +LL | | if self.whiskers > 3 { + | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | | +LL | | println!("MEOW"); +LL | | } +LL | | } + | |___- this function doesn't have a `self` parameter error[E0425]: cannot find function `grow_older` in this scope --> $DIR/issue-2356.rs:72:5 @@ -97,8 +103,12 @@ LL | purr_louder(); error[E0424]: expected value, found module `self` --> $DIR/issue-2356.rs:92:5 | -LL | self += 1; - | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | / fn main() { +LL | | self += 1; + | | ^^^^ `self` value is a keyword only available in methods with a `self` parameter +LL | | +LL | | } + | |_- this function doesn't have a `self` parameter error: aborting due to 17 previous errors From 0879f630741550f0d4989e908071de0bb05a50f1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Oct 2019 16:05:14 +1100 Subject: [PATCH 522/545] Remove `Copy` and `Clone` impls for `LocalInternedString`. They aren't used. --- src/libsyntax_pos/symbol.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libsyntax_pos/symbol.rs b/src/libsyntax_pos/symbol.rs index efb01ff84dcd..fa9567fb62c0 100644 --- a/src/libsyntax_pos/symbol.rs +++ b/src/libsyntax_pos/symbol.rs @@ -1106,8 +1106,8 @@ fn with_interner T>(f: F) -> T { } /// An alternative to `Symbol` and `InternedString`, useful when the chars -/// within the symbol need to be accessed. It is best used for temporary -/// values. +/// within the symbol need to be accessed. It deliberately has limited +/// functionality and should only be used for temporary values. /// /// Because the interner outlives any thread which uses this type, we can /// safely treat `string` which points to interner data, as an immortal string, @@ -1116,7 +1116,7 @@ fn with_interner T>(f: F) -> T { // FIXME: ensure that the interner outlives any thread which uses // `LocalInternedString`, by creating a new thread right after constructing the // interner. -#[derive(Clone, Copy, Eq, PartialOrd, Ord)] +#[derive(Eq, PartialOrd, Ord)] pub struct LocalInternedString { string: &'static str, } From d343ee839b6fe26c992d0609281443776839039c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Oct 2019 16:36:17 +1100 Subject: [PATCH 523/545] Remove `Hash` impls for `DefPath`, `DisambiguatedDefPathData`, and `DefKey`. They aren't used. --- src/librustc/hir/map/definitions.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index cc099fcc40f6..d2732c92d268 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -111,7 +111,7 @@ pub struct Definitions { /// A unique identifier that we can use to lookup a definition /// precisely. It combines the index of the definition's parent (if /// any) with a `DisambiguatedDefPathData`. -#[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub struct DefKey { /// The parent path. pub parent: Option, @@ -162,13 +162,13 @@ fn root_parent_stable_hash(crate_name: &str, /// between them. This introduces some artificial ordering dependency /// but means that if you have, e.g., two impls for the same type in /// the same module, they do get distinct `DefId`s. -#[derive(Clone, PartialEq, Debug, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Debug, RustcEncodable, RustcDecodable)] pub struct DisambiguatedDefPathData { pub data: DefPathData, pub disambiguator: u32 } -#[derive(Clone, Debug, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct DefPath { /// The path leading from the crate root to the item. pub data: Vec, From 769e75b40c53b5113e8206b70692fef8846de77a Mon Sep 17 00:00:00 2001 From: Tobias Rapp Date: Fri, 18 Oct 2019 08:29:18 +0200 Subject: [PATCH 524/545] Fix left/right shift typo in wrapping rotate docs This makes the note similar to the one found on rotate functions for primitive types like i32/u32. --- src/libcore/num/wrapping.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/wrapping.rs b/src/libcore/num/wrapping.rs index 59a10ae99bb6..5fe9895d8d24 100644 --- a/src/libcore/num/wrapping.rs +++ b/src/libcore/num/wrapping.rs @@ -437,7 +437,7 @@ pub const fn trailing_zeros(self) -> u32 { /// wrapping the truncated bits to the end of the resulting /// integer. /// - /// Please note this isn't the same operation as the `>>` shifting + /// Please note this isn't the same operation as the `<<` shifting /// operator! /// /// # Examples @@ -463,7 +463,7 @@ pub const fn rotate_left(self, n: u32) -> Self { /// wrapping the truncated bits to the beginning of the resulting /// integer. /// - /// Please note this isn't the same operation as the `<<` shifting + /// Please note this isn't the same operation as the `>>` shifting /// operator! /// /// # Examples From 9617014aa6c1d95bf4f59fc333b10f6b33dbe1ee Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 18 Oct 2019 18:15:16 +0900 Subject: [PATCH 525/545] Clarify diagnostics when using `~` as a unary op --- src/libsyntax/parse/parser/expr.rs | 2 +- .../issue-41679-tilde-bitwise-negation-attempt.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/parse/parser/expr.rs b/src/libsyntax/parse/parser/expr.rs index 273f5a5ffa36..67a530ec6831 100644 --- a/src/libsyntax/parse/parser/expr.rs +++ b/src/libsyntax/parse/parser/expr.rs @@ -423,7 +423,7 @@ fn parse_prefix_expr( self.struct_span_err(span_of_tilde, "`~` cannot be used as a unary operator") .span_suggestion_short( span_of_tilde, - "use `!` to perform bitwise negation", + "use `!` to perform bitwise not", "!".to_owned(), Applicability::MachineApplicable ) diff --git a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr index 84235ca4d637..79bc7d2565be 100644 --- a/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr +++ b/src/test/ui/did_you_mean/issue-41679-tilde-bitwise-negation-attempt.stderr @@ -2,7 +2,7 @@ error: `~` cannot be used as a unary operator --> $DIR/issue-41679-tilde-bitwise-negation-attempt.rs:2:13 | LL | let x = ~1; - | ^ help: use `!` to perform bitwise negation + | ^ help: use `!` to perform bitwise not error: aborting due to previous error From c8f7e18ceb29d78314ceef16979ff6ce5356f4c2 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 14 Sep 2019 09:22:07 -0400 Subject: [PATCH 526/545] [const-prop] Handle MIR Rvalue::Repeat --- src/librustc_mir/transform/const_prop.rs | 2 +- src/test/mir-opt/const_prop/repeat.rs | 37 ++++++++++++++++++++++++ src/test/ui/consts/const-prop-ice.rs | 1 + src/test/ui/consts/const-prop-ice.stderr | 8 ++++- 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/test/mir-opt/const_prop/repeat.rs diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 49ac1de8fef6..77943e9acd52 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -436,13 +436,13 @@ fn const_prop( // if this isn't a supported operation, then return None match rvalue { - Rvalue::Repeat(..) | Rvalue::Aggregate(..) | Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::Discriminant(..) => return None, Rvalue::Use(_) | Rvalue::Len(_) | + Rvalue::Repeat(..) | Rvalue::Cast(..) | Rvalue::NullaryOp(..) | Rvalue::CheckedBinaryOp(..) | diff --git a/src/test/mir-opt/const_prop/repeat.rs b/src/test/mir-opt/const_prop/repeat.rs new file mode 100644 index 000000000000..fb091ad2a3d5 --- /dev/null +++ b/src/test/mir-opt/const_prop/repeat.rs @@ -0,0 +1,37 @@ +// compile-flags: -O + +fn main() { + let x: u32 = [42; 8][2] + 0; +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _3 = [const 42u32; 8]; +// ... +// _4 = const 2usize; +// _5 = const 8usize; +// _6 = Lt(_4, _5); +// assert(move _6, "index out of bounds: the len is move _5 but the index is _4") -> bb1; +// } +// bb1: { +// _2 = _3[_4]; +// _1 = Add(move _2, const 0u32); +// ... +// return; +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// _6 = const true; +// assert(const true, "index out of bounds: the len is move _5 but the index is _4") -> bb1; +// } +// bb1: { +// _2 = const 42u32; +// _1 = Add(move _2, const 0u32); +// ... +// return; +// } +// END rustc.main.ConstProp.after.mir diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs index 13309f978b67..48c4b7da942e 100644 --- a/src/test/ui/consts/const-prop-ice.rs +++ b/src/test/ui/consts/const-prop-ice.rs @@ -1,3 +1,4 @@ fn main() { [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3 + //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr index 4b3880198bf2..8ecc6f4bc6b1 100644 --- a/src/test/ui/consts/const-prop-ice.stderr +++ b/src/test/ui/consts/const-prop-ice.stderr @@ -6,5 +6,11 @@ LL | [0; 3][3u64 as usize]; | = note: `#[deny(const_err)]` on by default -error: aborting due to previous error +error: this expression will panic at runtime + --> $DIR/const-prop-ice.rs:2:5 + | +LL | [0; 3][3u64 as usize]; + | ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3 + +error: aborting due to 2 previous errors From a2e3ed5c054b544df6ceeb9e612d39af819f4aae Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 14 Sep 2019 14:11:31 -0400 Subject: [PATCH 527/545] [const-prop] Handle MIR Rvalue::Aggregates --- src/librustc_mir/transform/const_prop.rs | 8 +++++- src/test/compile-fail/consts/const-err3.rs | 1 + src/test/mir-opt/const_prop/aggregate.rs | 25 +++++++++++++++++++ src/test/run-fail/overflowing-rsh-5.rs | 1 + src/test/run-fail/overflowing-rsh-6.rs | 1 + src/test/ui/consts/const-err2.rs | 1 + src/test/ui/consts/const-err2.stderr | 8 +++++- src/test/ui/consts/const-err3.rs | 1 + src/test/ui/consts/const-err3.stderr | 8 +++++- src/test/ui/issues/issue-54348.rs | 2 ++ src/test/ui/issues/issue-54348.stderr | 16 ++++++++++-- src/test/ui/lint/lint-exceeding-bitshifts2.rs | 2 +- .../ui/lint/lint-exceeding-bitshifts2.stderr | 8 +++++- 13 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 src/test/mir-opt/const_prop/aggregate.rs diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 77943e9acd52..2119ee1b598e 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -436,13 +436,13 @@ fn const_prop( // if this isn't a supported operation, then return None match rvalue { - Rvalue::Aggregate(..) | Rvalue::NullaryOp(NullOp::Box, _) | Rvalue::Discriminant(..) => return None, Rvalue::Use(_) | Rvalue::Len(_) | Rvalue::Repeat(..) | + Rvalue::Aggregate(..) | Rvalue::Cast(..) | Rvalue::NullaryOp(..) | Rvalue::CheckedBinaryOp(..) | @@ -535,6 +535,12 @@ fn const_prop( return None; } } + } else if let Rvalue::Aggregate(_, operands) = rvalue { + // FIXME(wesleywiser): const eval will turn this into a `const Scalar()` that + // `SimplifyLocals` doesn't know it can remove. + if operands.len() == 0 { + return None; + } } self.use_ecx(source_info, |this| { diff --git a/src/test/compile-fail/consts/const-err3.rs b/src/test/compile-fail/consts/const-err3.rs index fc10824f0c03..add4eef13c78 100644 --- a/src/test/compile-fail/consts/const-err3.rs +++ b/src/test/compile-fail/consts/const-err3.rs @@ -14,6 +14,7 @@ fn main() { //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR const_err + //~| ERROR this expression will panic at runtime black_box(b); black_box(c); black_box(d); diff --git a/src/test/mir-opt/const_prop/aggregate.rs b/src/test/mir-opt/const_prop/aggregate.rs new file mode 100644 index 000000000000..0937d37be6b6 --- /dev/null +++ b/src/test/mir-opt/const_prop/aggregate.rs @@ -0,0 +1,25 @@ +// compile-flags: -O + +fn main() { + let x = (0, 1, 2).1 + 0; +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _3 = (const 0i32, const 1i32, const 2i32); +// _2 = (_3.1: i32); +// _1 = Add(move _2, const 0i32); +// ... +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// _3 = (const 0i32, const 1i32, const 2i32); +// _2 = const 1i32; +// _1 = Add(move _2, const 0i32); +// ... +// } +// END rustc.main.ConstProp.after.mir diff --git a/src/test/run-fail/overflowing-rsh-5.rs b/src/test/run-fail/overflowing-rsh-5.rs index 793f495240d5..58dfc5710ae4 100644 --- a/src/test/run-fail/overflowing-rsh-5.rs +++ b/src/test/run-fail/overflowing-rsh-5.rs @@ -2,6 +2,7 @@ // compile-flags: -C debug-assertions #![warn(exceeding_bitshifts)] +#![warn(const_err)] fn main() { let _n = 1i64 >> [64][0]; diff --git a/src/test/run-fail/overflowing-rsh-6.rs b/src/test/run-fail/overflowing-rsh-6.rs index d6b2f8dc9f9a..c2fec5e4860a 100644 --- a/src/test/run-fail/overflowing-rsh-6.rs +++ b/src/test/run-fail/overflowing-rsh-6.rs @@ -2,6 +2,7 @@ // compile-flags: -C debug-assertions #![warn(exceeding_bitshifts)] +#![warn(const_err)] #![feature(const_indexing)] fn main() { diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index ecbcc2a4b496..e5ee90fc9f11 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -23,6 +23,7 @@ fn main() { //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR index out of bounds + //~| ERROR this expression will panic at runtime black_box(a); black_box(b); black_box(c); diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.stderr index 1d84d44dc27b..0a09a7213dab 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.stderr @@ -34,5 +34,11 @@ error: index out of bounds: the len is 1 but the index is 1 LL | let _e = [5u8][1]; | ^^^^^^^^ -error: aborting due to 5 previous errors +error: this expression will panic at runtime + --> $DIR/const-err2.rs:24:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 + +error: aborting due to 6 previous errors diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs index a9cf04cda7a5..89373f99f75c 100644 --- a/src/test/ui/consts/const-err3.rs +++ b/src/test/ui/consts/const-err3.rs @@ -23,6 +23,7 @@ fn main() { //~^ ERROR const_err let _e = [5u8][1]; //~^ ERROR const_err + //~| ERROR this expression will panic at runtime black_box(a); black_box(b); black_box(c); diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr index 0602707be704..42de247c8f7e 100644 --- a/src/test/ui/consts/const-err3.stderr +++ b/src/test/ui/consts/const-err3.stderr @@ -34,5 +34,11 @@ error: index out of bounds: the len is 1 but the index is 1 LL | let _e = [5u8][1]; | ^^^^^^^^ -error: aborting due to 5 previous errors +error: this expression will panic at runtime + --> $DIR/const-err3.rs:24:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 + +error: aborting due to 6 previous errors diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs index 68d838054776..e7221e2cbb1e 100644 --- a/src/test/ui/issues/issue-54348.rs +++ b/src/test/ui/issues/issue-54348.rs @@ -1,5 +1,7 @@ fn main() { [1][0u64 as usize]; [1][1.5 as usize]; //~ ERROR index out of bounds + //~| ERROR this expression will panic at runtime [1][1u64 as usize]; //~ ERROR index out of bounds + //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr index fa77bd6fd779..79320ef4f31c 100644 --- a/src/test/ui/issues/issue-54348.stderr +++ b/src/test/ui/issues/issue-54348.stderr @@ -6,11 +6,23 @@ LL | [1][1.5 as usize]; | = note: `#[deny(const_err)]` on by default +error: this expression will panic at runtime + --> $DIR/issue-54348.rs:3:5 + | +LL | [1][1.5 as usize]; + | ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 + error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/issue-54348.rs:4:5 + --> $DIR/issue-54348.rs:5:5 | LL | [1][1u64 as usize]; | ^^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: this expression will panic at runtime + --> $DIR/issue-54348.rs:5:5 + | +LL | [1][1u64 as usize]; + | ^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 + +error: aborting due to 4 previous errors diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.rs b/src/test/ui/lint/lint-exceeding-bitshifts2.rs index 69b627355b80..2c213daddd75 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts2.rs +++ b/src/test/ui/lint/lint-exceeding-bitshifts2.rs @@ -8,7 +8,7 @@ fn main() { let n = 1u8 << (4+3); let n = 1u8 << (4+4); //~ ERROR: attempt to shift left with overflow let n = 1i64 >> [63][0]; - let n = 1i64 >> [64][0]; // should be linting, needs to wait for const propagation + let n = 1i64 >> [64][0]; //~ ERROR: attempt to shift right with overflow #[cfg(target_pointer_width = "32")] const BITS: usize = 32; diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr index cb96982a7893..d9c76d233d03 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr @@ -10,6 +10,12 @@ note: lint level defined here LL | #![deny(exceeding_bitshifts, const_err)] | ^^^^^^^^^^^^^^^^^^^ +error: attempt to shift right with overflow + --> $DIR/lint-exceeding-bitshifts2.rs:11:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ + error: attempt to shift left with overflow --> $DIR/lint-exceeding-bitshifts2.rs:17:15 | @@ -22,5 +28,5 @@ error: attempt to shift left with overflow LL | let n = 1_usize << BITS; | ^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors From 4d89031e801e03009e74a3028007dd387e859717 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 15 Sep 2019 00:05:19 -0400 Subject: [PATCH 528/545] [const-prop] Handle MIR Rvalue::Discriminant --- src/librustc_mir/transform/const_prop.rs | 4 +- src/test/mir-opt/const_prop/discriminant.rs | 53 +++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 src/test/mir-opt/const_prop/discriminant.rs diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 2119ee1b598e..fb2cdce2d7ae 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -436,13 +436,13 @@ fn const_prop( // if this isn't a supported operation, then return None match rvalue { - Rvalue::NullaryOp(NullOp::Box, _) | - Rvalue::Discriminant(..) => return None, + Rvalue::NullaryOp(NullOp::Box, _) => return None, Rvalue::Use(_) | Rvalue::Len(_) | Rvalue::Repeat(..) | Rvalue::Aggregate(..) | + Rvalue::Discriminant(..) | Rvalue::Cast(..) | Rvalue::NullaryOp(..) | Rvalue::CheckedBinaryOp(..) | diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs new file mode 100644 index 000000000000..07bbd9202b94 --- /dev/null +++ b/src/test/mir-opt/const_prop/discriminant.rs @@ -0,0 +1,53 @@ +// compile-flags: -O + +fn main() { + let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0; +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _3 = std::option::Option::::Some(const true,); +// _4 = discriminant(_3); +// switchInt(move _4) -> [1isize: bb3, otherwise: bb2]; +// } +// bb1: { +// _2 = const 42i32; +// goto -> bb4; +// } +// bb2: { +// _2 = const 10i32; +// goto -> bb4; +// } +// bb3: { +// switchInt(((_3 as Some).0: bool)) -> [false: bb2, otherwise: bb1]; +// } +// bb4: { +// _1 = Add(move _2, const 0i32); +// ... +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// _3 = const Scalar(0x01) : std::option::Option; +// _4 = const 1isize; +// switchInt(const 1isize) -> [1isize: bb3, otherwise: bb2]; +// } +// bb1: { +// _2 = const 42i32; +// goto -> bb4; +// } +// bb2: { +// _2 = const 10i32; +// goto -> bb4; +// } +// bb3: { +// switchInt(const true) -> [false: bb2, otherwise: bb1]; +// } +// bb4: { +// _1 = Add(move _2, const 0i32); +// ... +// } +// END rustc.main.ConstProp.after.mir From 48349960e68a9d19b17ac54cd12e939a9a46ea7d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 8 Oct 2019 23:46:14 -0300 Subject: [PATCH 529/545] Use Cow to handle modifications of projection in preparation for interning --- src/librustc/mir/visit.rs | 33 ++++++++++++------- src/librustc_mir/borrow_check/nll/renumber.rs | 12 ++++--- src/librustc_mir/transform/erase_regions.rs | 12 ++++--- src/librustc_mir/transform/generator.rs | 24 +++++--------- src/librustc_mir/transform/inline.rs | 12 ++++--- src/librustc_mir/transform/promote_consts.rs | 6 ++-- src/librustc_mir/transform/simplify.rs | 11 ++++--- src/librustc_mir/util/def_use.rs | 6 ++-- 8 files changed, 67 insertions(+), 49 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index c8a6367899ba..fef406e89878 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -792,26 +792,37 @@ fn super_place( ) { self.visit_place_base(&mut place.base, context, location); - place.projection = self.process_projection(&place.projection); + if let Some(new_projection) = self.process_projection(&place.projection) { + place.projection = new_projection; + } } fn process_projection( &mut self, - projection: &Box<[PlaceElem<'tcx>]>, - ) -> Box<[PlaceElem<'tcx>]> { - let new_projection: Vec<_> = projection.iter().map(|elem| - self.process_projection_elem(elem) - ).collect(); + projection: &'a [PlaceElem<'tcx>], + ) -> Option]>> { + let mut projection = Cow::Borrowed(projection); - new_projection.into_boxed_slice() + for i in 0..projection.len() { + if let Some(elem) = projection.get(i) { + if let Some(elem) = self.process_projection_elem(elem) { + let vec = projection.to_mut(); + vec[i] = elem; + } + } + } + + match projection { + Cow::Borrowed(_) => None, + Cow::Owned(vec) => Some(vec.into_boxed_slice()), + } } fn process_projection_elem( &mut self, - elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { - // FIXME: avoid cloning here - elem.clone() + _elem: &PlaceElem<'tcx>, + ) -> Option> { + None } ); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index c4a19ce5128b..9ecd6f837750 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -65,12 +65,16 @@ fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.renumber_regions(ty)) - } else { - elem.clone() + let new_ty = self.renumber_regions(ty); + + if new_ty != *ty { + return Some(PlaceElem::Field(*field, new_ty)); + } } + + None } fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 725a8de8fe7d..439cae2093ae 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -42,12 +42,16 @@ fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) { fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { if let PlaceElem::Field(field, ty) = elem { - PlaceElem::Field(*field, self.tcx.erase_regions(ty)) - } else { - elem.clone() + let new_ty = self.tcx.erase_regions(ty); + + if new_ty != *ty { + return Some(PlaceElem::Field(*field, new_ty)); + } } + + None } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a801548efab0..6533e3c5ba81 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -89,22 +89,16 @@ fn visit_local(&mut self, } } - fn visit_place(&mut self, - place: &mut Place<'tcx>, - context: PlaceContext, - location: Location) { - self.visit_place_base(&mut place.base, context, location); - - let new_projection: Vec<_> = place.projection.iter().map(|elem| - match elem { - PlaceElem::Index(local) if *local == self.from => { - PlaceElem::Index(self.to) - } - _ => elem.clone(), + fn process_projection_elem( + &mut self, + elem: &PlaceElem<'tcx>, + ) -> Option> { + match elem { + PlaceElem::Index(local) if *local == self.from => { + Some(PlaceElem::Index(self.to)) } - ).collect(); - - place.projection = new_projection.into_boxed_slice(); + _ => None, + } } } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index dd13d0c96557..0cbdcedff478 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -703,12 +703,16 @@ fn visit_place( fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { if let PlaceElem::Index(local) = elem { - PlaceElem::Index(self.make_integrate_local(local)) - } else { - elem.clone() + let new_local = self.make_integrate_local(local); + + if new_local != *local { + return Some(PlaceElem::Index(new_local)) + } } + + None } fn visit_basic_block_data(&mut self, block: BasicBlock, data: &mut BasicBlockData<'tcx>) { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 565f260546bc..ad1785417cd9 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -408,12 +408,12 @@ fn visit_local(&mut self, fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { match elem { PlaceElem::Index(local) if self.is_temp_kind(*local) => { - PlaceElem::Index(self.promote_temp(*local)) + Some(PlaceElem::Index(self.promote_temp(*local))) } - _ => elem.clone(), + _ => None, } } } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 7dca3e357cc9..606c1a3a1cc0 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -374,11 +374,12 @@ fn visit_local(&mut self, l: &mut Local, _: PlaceContext, _: Location) { fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { - if let PlaceElem::Index(local) = elem { - PlaceElem::Index(self.map[*local].unwrap()) - } else { - elem.clone() + ) -> Option> { + match elem { + PlaceElem::Index(local) => { + Some(PlaceElem::Index(self.map[*local].unwrap())) + } + _ => None } } } diff --git a/src/librustc_mir/util/def_use.rs b/src/librustc_mir/util/def_use.rs index 25930df020aa..cdd07ad4b8ff 100644 --- a/src/librustc_mir/util/def_use.rs +++ b/src/librustc_mir/util/def_use.rs @@ -141,12 +141,12 @@ fn visit_local(&mut self, fn process_projection_elem( &mut self, elem: &PlaceElem<'tcx>, - ) -> PlaceElem<'tcx> { + ) -> Option> { match elem { PlaceElem::Index(local) if *local == self.query => { - PlaceElem::Index(self.new_local) + Some(PlaceElem::Index(self.new_local)) } - _ => elem.clone(), + _ => None, } } } From 865c4bcff6b52f69b4122e3a0f02f647cf588553 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 18 Oct 2019 08:36:46 -0700 Subject: [PATCH 530/545] review comments: help wording --- src/librustc_resolve/error_codes.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index 29ca797fc065..ee207025e0c3 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1013,12 +1013,12 @@ fn h1() -> i32 { "##, E0424: r##" -The `self` keyword was used inside of an associated function instead of inside -of a method. Associated functions have no "`self` receiver" argument, and are -equivalent to regular functions which exist in the namespace of a trait. -Methods, on the other hand, have a `self` reciver argument, like `self`, -`&self`, `&mut self` or `self: &mut Pin` (this last one is an example of -an ["abitrary `self` type"](https://github.com/rust-lang/rust/issues/44874)). +The `self` keyword was used inside of an associated function without a "`self` +receiver" parameter. The `self` keyword can only be used inside methods, which +are associated functions (functions defined inside of a `trait` or `impl` block) +that have a `self` receiver as its first parameter, like `self`, `&self`, +`&mut self` or `self: &mut Pin` (this last one is an example of an +["abitrary `self` type"](https://github.com/rust-lang/rust/issues/44874)). Erroneous code example: @@ -1026,17 +1026,18 @@ fn h1() -> i32 { struct Foo; impl Foo { - // `bar` is a method, because it has a receiver argument. + // `bar` is a method, because it has a receiver parameter. fn bar(&self) {} - // `foo` is an associated function, because it has no receiver argument. + // `foo` is not a method, because it has no receiver parameter. fn foo() { - self.bar(); // error: `self` is not available in an associated function + self.bar(); // error: `self` value is a keyword only available in + // methods with a `self` parameter } } ``` -Check if the associated function's argument list should have contained a `self` +Check if the associated function's parameter list should have contained a `self` receiver for it to be a method, and add it if so. Example: ``` From bd813bf1acbef7643a06278af48603397c7eb5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 18 Oct 2019 08:38:08 -0700 Subject: [PATCH 531/545] review comment: span bug label --- src/libsyntax_ext/deriving/generic/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax_ext/deriving/generic/mod.rs b/src/libsyntax_ext/deriving/generic/mod.rs index fd2c1552d32a..216338c1a886 100644 --- a/src/libsyntax_ext/deriving/generic/mod.rs +++ b/src/libsyntax_ext/deriving/generic/mod.rs @@ -1055,7 +1055,7 @@ fn expand_struct_method_body<'b>(&self, }) .collect() } else { - cx.span_bug(trait_.span, "no self arguments for method in generic `derive`") + cx.span_bug(trait_.span, "no `self` parameter for method in generic `derive`") }; // body of the inner most destructuring match From 2b76c8b95ff866d8806fdc82fe270c4df02efc0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 18 Oct 2019 13:00:14 -0700 Subject: [PATCH 532/545] review comments --- src/librustc_resolve/error_codes.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_resolve/error_codes.rs b/src/librustc_resolve/error_codes.rs index ee207025e0c3..2288aab3c27a 100644 --- a/src/librustc_resolve/error_codes.rs +++ b/src/librustc_resolve/error_codes.rs @@ -1014,11 +1014,7 @@ fn h1() -> i32 { E0424: r##" The `self` keyword was used inside of an associated function without a "`self` -receiver" parameter. The `self` keyword can only be used inside methods, which -are associated functions (functions defined inside of a `trait` or `impl` block) -that have a `self` receiver as its first parameter, like `self`, `&self`, -`&mut self` or `self: &mut Pin` (this last one is an example of an -["abitrary `self` type"](https://github.com/rust-lang/rust/issues/44874)). +receiver" parameter. Erroneous code example: @@ -1037,6 +1033,12 @@ fn foo() { } ``` +The `self` keyword can only be used inside methods, which are associated +functions (functions defined inside of a `trait` or `impl` block) that have a +`self` receiver as its first parameter, like `self`, `&self`, `&mut self` or +`self: &mut Pin` (this last one is an example of an ["abitrary `self` +type"](https://github.com/rust-lang/rust/issues/44874)). + Check if the associated function's parameter list should have contained a `self` receiver for it to be a method, and add it if so. Example: From 2d3c17a609e672120305e084314cba2f98308399 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Oct 2019 01:08:17 +0300 Subject: [PATCH 533/545] resolve: Mark macros starting with an underscore as used --- src/librustc_resolve/build_reduced_graph.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index eadae52c250a..50ff01b39136 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1064,8 +1064,17 @@ fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> { None } + // Mark the given macro as unused unless its name starts with `_`. + // Macro uses will remove items from this set, and the remaining + // items will be reported as `unused_macros`. + fn insert_unused_macro(&mut self, ident: Ident, node_id: NodeId, span: Span) { + if !ident.as_str().starts_with("_") { + self.r.unused_macros.insert(node_id, span); + } + } + fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> { - let parent_scope = &self.parent_scope; + let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; let (ext, ident, span, is_legacy) = match &item.kind { ItemKind::MacroDef(def) => { @@ -1105,7 +1114,7 @@ fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> { (res, vis, span, expansion, IsMacroExport)); } else { self.r.check_reserved_macro_name(ident, res); - self.r.unused_macros.insert(item.id, span); + self.insert_unused_macro(ident, item.id, span); } LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding { parent_legacy_scope: parent_scope.legacy, binding, ident @@ -1114,7 +1123,7 @@ fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> { let module = parent_scope.module; let vis = self.resolve_visibility(&item.vis); if vis != ty::Visibility::Public { - self.r.unused_macros.insert(item.id, span); + self.insert_unused_macro(ident, item.id, span); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); self.parent_scope.legacy From 7ce85f2dca545c9012fdc13c90cb2b058e58d3dd Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 10 Oct 2019 01:41:47 +0300 Subject: [PATCH 534/545] expand: Simplify expansion of derives And make it more uniform with other macros. By merging placeholders for future derives' outputs into the derive container's output fragment early. --- src/librustc/hir/map/def_collector.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 10 ------- src/librustc_resolve/macros.rs | 8 ++--- src/libsyntax/lib.rs | 1 + src/libsyntax_expand/base.rs | 3 +- src/libsyntax_expand/expand.rs | 33 ++++++++++++++------- src/libsyntax_expand/placeholders.rs | 11 +------ 7 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index fbef95fec7dc..9be339be7034 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -90,7 +90,7 @@ fn collect_field(&mut self, field: &'a StructField, index: Option) { } } - pub fn visit_macro_invoc(&mut self, id: NodeId) { + fn visit_macro_invoc(&mut self, id: NodeId) { self.definitions.set_invocation_parent(id.placeholder_to_expn_id(), self.parent_def); } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 50ff01b39136..e261d3af61ff 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -163,25 +163,15 @@ impl<'a> Resolver<'a> { Some(ext) } - // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. crate fn build_reduced_graph( &mut self, fragment: &AstFragment, - extra_placeholders: &[NodeId], parent_scope: ParentScope<'a>, ) -> LegacyScope<'a> { let mut def_collector = DefCollector::new(&mut self.definitions, parent_scope.expansion); fragment.visit_with(&mut def_collector); - for placeholder in extra_placeholders { - def_collector.visit_macro_invoc(*placeholder); - } - let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); - for placeholder in extra_placeholders { - visitor.parent_scope.legacy = visitor.visit_invoc(*placeholder); - } - visitor.parent_scope.legacy } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index c91a0b2ed985..94fe0cc57403 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -108,15 +108,11 @@ fn resolve_dollar_crates(&mut self) { }); } - // FIXME: `extra_placeholders` should be included into the `fragment` as regular placeholders. - fn visit_ast_fragment_with_placeholders( - &mut self, expansion: ExpnId, fragment: &AstFragment, extra_placeholders: &[NodeId] - ) { + fn visit_ast_fragment_with_placeholders(&mut self, expansion: ExpnId, fragment: &AstFragment) { // Integrate the new AST fragment into all the definition and module structures. // We are inside the `expansion` now, but other parent scope components are still the same. let parent_scope = ParentScope { expansion, ..self.invocation_parent_scopes[&expansion] }; - let output_legacy_scope = - self.build_reduced_graph(fragment, extra_placeholders, parent_scope); + let output_legacy_scope = self.build_reduced_graph(fragment, parent_scope); self.output_legacy_scopes.insert(expansion, output_legacy_scope); parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion); diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index a68b7fdf931a..261cc53e158c 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -11,6 +11,7 @@ #![feature(const_fn)] #![feature(const_transmute)] #![feature(crate_visibility_modifier)] +#![feature(decl_macro)] #![feature(label_break_value)] #![feature(nll)] #![feature(try_trait)] diff --git a/src/libsyntax_expand/base.rs b/src/libsyntax_expand/base.rs index 593e06f29b93..c222e7357ac7 100644 --- a/src/libsyntax_expand/base.rs +++ b/src/libsyntax_expand/base.rs @@ -851,8 +851,7 @@ pub trait Resolver { fn next_node_id(&mut self) -> NodeId; fn resolve_dollar_crates(&mut self); - fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment, - extra_placeholders: &[NodeId]); + fn visit_ast_fragment_with_placeholders(&mut self, expn_id: ExpnId, fragment: &AstFragment); fn register_builtin_macro(&mut self, ident: ast::Ident, ext: SyntaxExtension); fn expansion_for_ast_pass( diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs index 47b4bca314a2..f03d464eafb9 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -26,7 +26,6 @@ use smallvec::{smallvec, SmallVec}; use syntax_pos::{Span, DUMMY_SP, FileName}; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use std::io::ErrorKind; use std::{iter, mem, slice}; @@ -75,6 +74,22 @@ fn make_from<'a>(self, result: Box) -> Option { } impl AstFragment { + pub fn add_placeholders(&mut self, placeholders: &[NodeId]) { + if placeholders.is_empty() { + return; + } + match self { + $($(AstFragment::$Kind(ast) => ast.extend(placeholders.iter().flat_map(|id| { + // We are repeating through arguments with `many`, to do that we have to + // mention some macro variable from those arguments even if it's not used. + #[cfg_attr(bootstrap, allow(unused_macros))] + macro _repeating($flat_map_ast_elt) {} + placeholder(AstFragmentKind::$Kind, *id).$make_ast() + })),)?)* + _ => panic!("unexpected AST fragment kind") + } + } + pub fn make_opt_expr(self) -> Option> { match self { AstFragment::OptExpr(expr) => expr, @@ -342,7 +357,6 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm // Unresolved macros produce dummy outputs as a recovery measure. invocations.reverse(); let mut expanded_fragments = Vec::new(); - let mut all_derive_placeholders: FxHashMap> = FxHashMap::default(); let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { @@ -420,9 +434,7 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm self.cx.resolver.add_derives(invoc.expansion_data.id, SpecialDerives::COPY); } - let derive_placeholders = - all_derive_placeholders.entry(invoc.expansion_data.id).or_default(); - derive_placeholders.reserve(derives.len()); + let mut derive_placeholders = Vec::with_capacity(derives.len()); invocations.reserve(derives.len()); for path in derives { let expn_id = ExpnId::fresh(None); @@ -438,7 +450,7 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm } let fragment = invoc.fragment_kind .expect_from_annotatables(::std::iter::once(item)); - self.collect_invocations(fragment, derive_placeholders) + self.collect_invocations(fragment, &derive_placeholders) } }; @@ -457,10 +469,8 @@ pub fn fully_expand_fragment(&mut self, input_fragment: AstFragment) -> AstFragm let mut placeholder_expander = PlaceholderExpander::new(self.cx, self.monotonic); while let Some(expanded_fragments) = expanded_fragments.pop() { for (expn_id, expanded_fragment) in expanded_fragments.into_iter().rev() { - let derive_placeholders = - all_derive_placeholders.remove(&expn_id).unwrap_or_else(Vec::new); placeholder_expander.add(NodeId::placeholder_from_expn_id(expn_id), - expanded_fragment, derive_placeholders); + expanded_fragment); } } fragment_with_placeholders.mut_visit_with(&mut placeholder_expander); @@ -493,13 +503,14 @@ fn collect_invocations(&mut self, mut fragment: AstFragment, extra_placeholders: monotonic: self.monotonic, }; fragment.mut_visit_with(&mut collector); + fragment.add_placeholders(extra_placeholders); collector.invocations }; - // FIXME: Merge `extra_placeholders` into the `fragment` as regular placeholders. if self.monotonic { self.cx.resolver.visit_ast_fragment_with_placeholders( - self.cx.current_expansion.id, &fragment, extra_placeholders); + self.cx.current_expansion.id, &fragment + ); } (fragment, invocations) diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs index f2c89e14b53b..21d8a21aa394 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -171,17 +171,8 @@ pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self { } } - pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment, placeholders: Vec) { + pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) { fragment.mut_visit_with(self); - if let AstFragment::Items(mut items) = fragment { - for placeholder in placeholders { - match self.remove(placeholder) { - AstFragment::Items(derived_items) => items.extend(derived_items), - _ => unreachable!(), - } - } - fragment = AstFragment::Items(items); - } self.expanded_fragments.insert(id, fragment); } From 25cc99fca0650f54828e8ba7ad2bab341b231fcc Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 16 Oct 2019 00:01:47 +0300 Subject: [PATCH 535/545] privacy: Avoid one more `unwrap` causing an ICE in rustdoc The issue is rustdoc-specific because its root cause if the `everybody_loops` pass makes some def-ids to not have local hir-ids --- src/librustc_privacy/lib.rs | 10 +++++----- src/test/rustdoc/macro-in-closure.rs | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 src/test/rustdoc/macro-in-closure.rs diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index f44692b7aea7..a3a4ccf5d65d 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -880,11 +880,11 @@ fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef) { self.tcx, self.tcx.hir().local_def_id(md.hir_id) ).unwrap(); - let mut module_id = self.tcx.hir().as_local_hir_id(macro_module_def_id).unwrap(); - if !self.tcx.hir().is_hir_id_module(module_id) { - // `module_id` doesn't correspond to a `mod`, return early (#63164). - return; - } + let mut module_id = match self.tcx.hir().as_local_hir_id(macro_module_def_id) { + Some(module_id) if self.tcx.hir().is_hir_id_module(module_id) => module_id, + // `module_id` doesn't correspond to a `mod`, return early (#63164, #65252). + _ => return, + }; let level = if md.vis.node.is_pub() { self.get(module_id) } else { None }; let new_level = self.update(md.hir_id, level); if new_level.is_none() { diff --git a/src/test/rustdoc/macro-in-closure.rs b/src/test/rustdoc/macro-in-closure.rs new file mode 100644 index 000000000000..298ff601de89 --- /dev/null +++ b/src/test/rustdoc/macro-in-closure.rs @@ -0,0 +1,9 @@ +// Regression issue for rustdoc ICE encountered in PR #65252. + +#![feature(decl_macro)] + +fn main() { + || { + macro m() {} + }; +} From 7f89f04b41d4d1de85df2fd3ede61e4fc97d9e69 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 19 Oct 2019 00:54:17 +0300 Subject: [PATCH 536/545] Fix rebase --- src/libsyntax/lib.rs | 1 - src/libsyntax_expand/lib.rs | 1 + src/libsyntax_expand/placeholders.rs | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 261cc53e158c..a68b7fdf931a 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -11,7 +11,6 @@ #![feature(const_fn)] #![feature(const_transmute)] #![feature(crate_visibility_modifier)] -#![feature(decl_macro)] #![feature(label_break_value)] #![feature(nll)] #![feature(try_trait)] diff --git a/src/libsyntax_expand/lib.rs b/src/libsyntax_expand/lib.rs index 88e69d793973..db292b619be3 100644 --- a/src/libsyntax_expand/lib.rs +++ b/src/libsyntax_expand/lib.rs @@ -1,4 +1,5 @@ #![feature(crate_visibility_modifier)] +#![feature(decl_macro)] #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] diff --git a/src/libsyntax_expand/placeholders.rs b/src/libsyntax_expand/placeholders.rs index 21d8a21aa394..e595888dae7d 100644 --- a/src/libsyntax_expand/placeholders.rs +++ b/src/libsyntax_expand/placeholders.rs @@ -1,7 +1,7 @@ use crate::base::ExtCtxt; use crate::expand::{AstFragment, AstFragmentKind}; -use syntax::ast::{self, NodeId}; +use syntax::ast; use syntax::source_map::{DUMMY_SP, dummy_spanned}; use syntax::tokenstream::TokenStream; use syntax::mut_visit::*; From 227db40a98e5bd903aa3658c16f19a3d6f694deb Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 16 Oct 2019 20:33:55 +0200 Subject: [PATCH 537/545] Uninitialized boxes: add test for zero-size allocations --- src/liballoc/tests/boxed.rs | 18 ++++++++++++++++++ src/liballoc/tests/lib.rs | 2 ++ 2 files changed, 20 insertions(+) create mode 100644 src/liballoc/tests/boxed.rs diff --git a/src/liballoc/tests/boxed.rs b/src/liballoc/tests/boxed.rs new file mode 100644 index 000000000000..bc3d53bf30da --- /dev/null +++ b/src/liballoc/tests/boxed.rs @@ -0,0 +1,18 @@ +use std::ptr::NonNull; +use std::mem::MaybeUninit; + +#[test] +fn unitialized_zero_size_box() { + assert_eq!( + &*Box::<()>::new_uninit() as *const _, + NonNull::>::dangling().as_ptr(), + ); + assert_eq!( + Box::<[()]>::new_uninit_slice(4).as_ptr(), + NonNull::>::dangling().as_ptr(), + ); + assert_eq!( + Box::<[String]>::new_uninit_slice(0).as_ptr(), + NonNull::>::dangling().as_ptr(), + ); +} diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index 5723a30c0f34..59f5c8dfb8a8 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -2,6 +2,7 @@ #![feature(box_syntax)] #![feature(drain_filter)] #![feature(exact_size_is_empty)] +#![feature(new_uninit)] #![feature(option_flattening)] #![feature(pattern)] #![feature(repeat_generic_slice)] @@ -15,6 +16,7 @@ mod arc; mod binary_heap; +mod boxed; mod btree; mod cow_str; mod fmt; From 2d22063e4c6fbdb61ce2a2dd9ce50d12fe9f0e9b Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 15 Sep 2019 12:03:52 -0400 Subject: [PATCH 538/545] [const-prop] Handle MIR Rvalue::Box --- src/librustc_mir/transform/const_prop.rs | 19 +------- src/test/mir-opt/const_prop/boxes.rs | 56 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 18 deletions(-) create mode 100644 src/test/mir-opt/const_prop/boxes.rs diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index fb2cdce2d7ae..984938d00b2f 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -8,7 +8,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, - Local, NullOp, UnOp, StatementKind, Statement, LocalKind, + Local, UnOp, StatementKind, Statement, LocalKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, SourceScope, SourceScopeLocalData, LocalDecl, BasicBlock, }; @@ -434,23 +434,6 @@ fn const_prop( ) -> Option> { let span = source_info.span; - // if this isn't a supported operation, then return None - match rvalue { - Rvalue::NullaryOp(NullOp::Box, _) => return None, - - Rvalue::Use(_) | - Rvalue::Len(_) | - Rvalue::Repeat(..) | - Rvalue::Aggregate(..) | - Rvalue::Discriminant(..) | - Rvalue::Cast(..) | - Rvalue::NullaryOp(..) | - Rvalue::CheckedBinaryOp(..) | - Rvalue::Ref(..) | - Rvalue::UnaryOp(..) | - Rvalue::BinaryOp(..) => { } - } - // perform any special checking for specific Rvalue types if let Rvalue::UnaryOp(op, arg) = rvalue { trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg); diff --git a/src/test/mir-opt/const_prop/boxes.rs b/src/test/mir-opt/const_prop/boxes.rs new file mode 100644 index 000000000000..cf134dadf278 --- /dev/null +++ b/src/test/mir-opt/const_prop/boxes.rs @@ -0,0 +1,56 @@ +// compile-flags: -O +// ignore-emscripten compiled with panic=abort by default +// ignore-wasm32 +// ignore-wasm64 + +#![feature(box_syntax)] + +// Note: this test verifies that we, in fact, do not const prop `box` + +fn main() { + let x = *(box 42) + 0; +} + +// END RUST SOURCE +// START rustc.main.ConstProp.before.mir +// bb0: { +// ... +// _4 = Box(i32); +// (*_4) = const 42i32; +// _3 = move _4; +// ... +// _2 = (*_3); +// _1 = Add(move _2, const 0i32); +// ... +// drop(_3) -> [return: bb2, unwind: bb1]; +// } +// bb1 (cleanup): { +// resume; +// } +// bb2: { +// ... +// _0 = (); +// ... +// } +// END rustc.main.ConstProp.before.mir +// START rustc.main.ConstProp.after.mir +// bb0: { +// ... +// _4 = Box(i32); +// (*_4) = const 42i32; +// _3 = move _4; +// ... +// _2 = (*_3); +// _1 = Add(move _2, const 0i32); +// ... +// drop(_3) -> [return: bb2, unwind: bb1]; +// } +// bb1 (cleanup): { +// resume; +// } +// bb2: { +// ... +// _0 = (); +// ... +// } +// END rustc.main.ConstProp.after.mir From 8cf6c23d66ce4d80d6d76291c10cbbe6cab9cb00 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 15 Sep 2019 12:08:09 -0400 Subject: [PATCH 539/545] Cleanup const_prop() some --- src/librustc_mir/transform/const_prop.rs | 141 ++++++++++++----------- 1 file changed, 72 insertions(+), 69 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 984938d00b2f..abb880fd6241 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -118,7 +118,7 @@ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<' struct ConstPropMachine; impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { - type MemoryKinds= !; + type MemoryKinds = !; type PointerTag = (); type ExtraFnVal = !; @@ -435,79 +435,80 @@ fn const_prop( let span = source_info.span; // perform any special checking for specific Rvalue types - if let Rvalue::UnaryOp(op, arg) = rvalue { - trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg); - let overflow_check = self.tcx.sess.overflow_checks(); + match rvalue { + Rvalue::UnaryOp(UnOp::Neg, arg) => { + trace!("checking UnaryOp(op = Neg, arg = {:?})", arg); + let overflow_check = self.tcx.sess.overflow_checks(); - self.use_ecx(source_info, |this| { - // We check overflow in debug mode already - // so should only check in release mode. - if *op == UnOp::Neg && !overflow_check { - let ty = arg.ty(&this.local_decls, this.tcx); + self.use_ecx(source_info, |this| { + // We check overflow in debug mode already + // so should only check in release mode. + if !overflow_check { + let ty = arg.ty(&this.local_decls, this.tcx); - if ty.is_integral() { - let arg = this.ecx.eval_operand(arg, None)?; - let prim = this.ecx.read_immediate(arg)?; - // Need to do overflow check here: For actual CTFE, MIR - // generation emits code that does this before calling the op. - if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { - throw_panic!(OverflowNeg) + if ty.is_integral() { + let arg = this.ecx.eval_operand(arg, None)?; + let prim = this.ecx.read_immediate(arg)?; + // Need to do overflow check here: For actual CTFE, MIR + // generation emits code that does this before calling the op. + if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { + throw_panic!(OverflowNeg) + } } } - } - Ok(()) - })?; - } else if let Rvalue::BinaryOp(op, left, right) = rvalue { - trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); - - let r = self.use_ecx(source_info, |this| { - this.ecx.read_immediate(this.ecx.eval_operand(right, None)?) - })?; - if *op == BinOp::Shr || *op == BinOp::Shl { - let left_bits = place_layout.size.bits(); - let right_size = r.layout.size; - let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); - if r_bits.ok().map_or(false, |b| b >= left_bits as u128) { - let source_scope_local_data = match self.source_scope_local_data { - ClearCrossCrate::Set(ref data) => data, - ClearCrossCrate::Clear => return None, - }; - let dir = if *op == BinOp::Shr { - "right" - } else { - "left" - }; - let hir_id = source_scope_local_data[source_info.scope].lint_root; - self.tcx.lint_hir( - ::rustc::lint::builtin::EXCEEDING_BITSHIFTS, - hir_id, - span, - &format!("attempt to shift {} with overflow", dir)); - return None; - } + Ok(()) + })?; } - self.use_ecx(source_info, |this| { - let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; - let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?; - // We check overflow in debug mode already - // so should only check in release mode. - if !this.tcx.sess.overflow_checks() && overflow { - let err = err_panic!(Overflow(*op)).into(); - return Err(err); + Rvalue::BinaryOp(op, left, right) => { + trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); + + let r = self.use_ecx(source_info, |this| { + this.ecx.read_immediate(this.ecx.eval_operand(right, None)?) + })?; + if *op == BinOp::Shr || *op == BinOp::Shl { + let left_bits = place_layout.size.bits(); + let right_size = r.layout.size; + let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); + if r_bits.ok().map_or(false, |b| b >= left_bits as u128) { + let source_scope_local_data = match self.source_scope_local_data { + ClearCrossCrate::Set(ref data) => data, + ClearCrossCrate::Clear => return None, + }; + let dir = if *op == BinOp::Shr { + "right" + } else { + "left" + }; + let hir_id = source_scope_local_data[source_info.scope].lint_root; + self.tcx.lint_hir( + ::rustc::lint::builtin::EXCEEDING_BITSHIFTS, + hir_id, + span, + &format!("attempt to shift {} with overflow", dir)); + return None; + } } + self.use_ecx(source_info, |this| { + let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; + let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?; - Ok(()) - })?; - } else if let Rvalue::Ref(_, _, place) = rvalue { - trace!("checking Ref({:?})", place); - // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref - // from a function argument that hasn't been assigned to in this function. - if let Place { - base: PlaceBase::Local(local), - projection: box [] - } = place { + // We check overflow in debug mode already + // so should only check in release mode. + if !this.tcx.sess.overflow_checks() && overflow { + let err = err_panic!(Overflow(*op)).into(); + return Err(err); + } + + Ok(()) + })?; + } + + Rvalue::Ref(_, _, Place { base: PlaceBase::Local(local), projection: box [] }) => { + trace!("checking Ref({:?})", place); + // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref + // from a function argument that hasn't been assigned to in this function. let alive = if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value { true @@ -518,12 +519,14 @@ fn const_prop( return None; } } - } else if let Rvalue::Aggregate(_, operands) = rvalue { - // FIXME(wesleywiser): const eval will turn this into a `const Scalar()` that - // `SimplifyLocals` doesn't know it can remove. - if operands.len() == 0 { + + Rvalue::Aggregate(_, operands) if operands.len() == 0 => { + // FIXME(wesleywiser): const eval will turn this into a `const Scalar()` that + // `SimplifyLocals` doesn't know it can remove. return None; } + + _ => { } } self.use_ecx(source_info, |this| { From b71ea80172136fe4b597aef1001ca72a8588fe15 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 9 Oct 2019 06:08:46 -0400 Subject: [PATCH 540/545] Don't ICE when evaluating writes to uninhabited enum variants --- src/librustc/mir/interpret/error.rs | 7 +++-- src/librustc_mir/interpret/operand.rs | 8 +++--- src/librustc_mir/interpret/place.rs | 16 +++++++---- src/librustc_mir/interpret/validity.rs | 2 +- .../write-to-uninhabited-enum-variant.rs | 28 +++++++++++++++++++ 5 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index ac99ccd45eaf..d918b9ee6734 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -363,6 +363,8 @@ pub enum UndefinedBehaviorInfo { UbExperimental(String), /// Unreachable code was executed. Unreachable, + /// An enum discriminant was set to a value which was outside the range of valid values. + InvalidDiscriminant(ScalarMaybeUndef), } impl fmt::Debug for UndefinedBehaviorInfo { @@ -373,6 +375,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", msg), Unreachable => write!(f, "entered unreachable code"), + InvalidDiscriminant(val) => + write!(f, "encountered invalid enum discriminant {}", val), } } } @@ -400,7 +404,6 @@ pub enum UnsupportedOpInfo<'tcx> { InvalidMemoryAccess, InvalidFunctionPointer, InvalidBool, - InvalidDiscriminant(ScalarMaybeUndef), PointerOutOfBounds { ptr: Pointer, msg: CheckInAllocMsg, @@ -485,8 +488,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "incorrect alloc info: expected size {} and align {}, \ got size {} and align {}", size.bytes(), align.bytes(), size2.bytes(), align2.bytes()), - InvalidDiscriminant(val) => - write!(f, "encountered invalid enum discriminant {}", val), InvalidMemoryAccess => write!(f, "tried to access memory through an invalid pointer"), DanglingPointerDeref => diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 4bdd71f9602a..4d9be55945e0 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -647,7 +647,7 @@ pub fn read_discriminant( let bits_discr = raw_discr .not_undef() .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size)) - .map_err(|_| err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())))?; + .map_err(|_| err_ub!(InvalidDiscriminant(raw_discr.erase_tag())))?; let real_discr = if discr_val.layout.ty.is_signed() { // going from layout tag type to typeck discriminant type // requires first sign extending with the discriminant layout @@ -677,7 +677,7 @@ pub fn read_discriminant( _ => bug!("tagged layout for non-adt non-generator"), }.ok_or_else( - || err_unsup!(InvalidDiscriminant(raw_discr.erase_tag())) + || err_ub!(InvalidDiscriminant(raw_discr.erase_tag())) )?; (real_discr, index.0) }, @@ -689,7 +689,7 @@ pub fn read_discriminant( let variants_start = niche_variants.start().as_u32(); let variants_end = niche_variants.end().as_u32(); let raw_discr = raw_discr.not_undef().map_err(|_| { - err_unsup!(InvalidDiscriminant(ScalarMaybeUndef::Undef)) + err_ub!(InvalidDiscriminant(ScalarMaybeUndef::Undef)) })?; match raw_discr.to_bits_or_ptr(discr_val.layout.size, self) { Err(ptr) => { @@ -697,7 +697,7 @@ pub fn read_discriminant( let ptr_valid = niche_start == 0 && variants_start == variants_end && !self.memory.ptr_may_be_null(ptr); if !ptr_valid { - throw_unsup!(InvalidDiscriminant(raw_discr.erase_tag().into())) + throw_ub!(InvalidDiscriminant(raw_discr.erase_tag().into())) } (dataful_variant.as_u32() as u128, dataful_variant) }, diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 903eb3c1c44b..0289c52fd374 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -1031,9 +1031,13 @@ pub fn write_discriminant_index( variant_index: VariantIdx, dest: PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { + let variant_scalar = Scalar::from_u32(variant_index.as_u32()).into(); + match dest.layout.variants { layout::Variants::Single { index } => { - assert_eq!(index, variant_index); + if index != variant_index { + throw_ub!(InvalidDiscriminant(variant_scalar)); + } } layout::Variants::Multiple { discr_kind: layout::DiscriminantKind::Tag, @@ -1041,7 +1045,9 @@ pub fn write_discriminant_index( discr_index, .. } => { - assert!(dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index)); + if !dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index) { + throw_ub!(InvalidDiscriminant(variant_scalar)); + } let discr_val = dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val; @@ -1064,9 +1070,9 @@ pub fn write_discriminant_index( discr_index, .. } => { - assert!( - variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len(), - ); + if !variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len() { + throw_ub!(InvalidDiscriminant(variant_scalar)); + } if variant_index != dataful_variant { let variants_start = niche_variants.start().as_u32(); let variant_index_relative = variant_index.as_u32() diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 853fcb1beabf..3444fb60f333 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -344,7 +344,7 @@ fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> match self.walk_value(op) { Ok(()) => Ok(()), Err(err) => match err.kind { - err_unsup!(InvalidDiscriminant(val)) => + err_ub!(InvalidDiscriminant(val)) => throw_validation_failure!( val, self.path, "a valid enum discriminant" ), diff --git a/src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs b/src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs new file mode 100644 index 000000000000..cccb7879fc0f --- /dev/null +++ b/src/test/ui/consts/const-eval/write-to-uninhabited-enum-variant.rs @@ -0,0 +1,28 @@ +// run-pass + +#![allow(dead_code)] + +enum Empty { } +enum Test1 { + A(u8), + B(Empty), +} +enum Test2 { + A(u8), + B(Empty), + C, +} + +fn bar() -> Option { + None +} + +fn main() { + if let Some(x) = bar() { + Test1::B(x); + } + + if let Some(x) = bar() { + Test2::B(x); + } +} From fd20dbed004c5c84fe846e04255608dc78b60a0d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 13 Oct 2019 13:48:26 -0400 Subject: [PATCH 541/545] Improve comments and structure of `ConstProp::const_prop()` Per code review feedback --- src/librustc_mir/transform/const_prop.rs | 78 +++++++++++++++--------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index abb880fd6241..f0c0e5734438 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -434,26 +434,32 @@ fn const_prop( ) -> Option> { let span = source_info.span; - // perform any special checking for specific Rvalue types + let overflow_check = self.tcx.sess.overflow_checks(); + + // Perform any special handling for specific Rvalue types. + // Generally, checks here fall into one of two categories: + // 1. Additional checking to provide useful lints to the user + // - In this case, we will do some validation and then fall through to the + // end of the function which evals the assignment. + // 2. Working around bugs in other parts of the compiler + // - In this case, we'll return `None` from this function to stop evaluation. match rvalue { - Rvalue::UnaryOp(UnOp::Neg, arg) => { + // Additional checking: if overflow checks are disabled (which is usually the case in + // release mode), then we need to do additional checking here to give lints to the user + // if an overflow would occur. + Rvalue::UnaryOp(UnOp::Neg, arg) if !overflow_check => { trace!("checking UnaryOp(op = Neg, arg = {:?})", arg); - let overflow_check = self.tcx.sess.overflow_checks(); self.use_ecx(source_info, |this| { - // We check overflow in debug mode already - // so should only check in release mode. - if !overflow_check { - let ty = arg.ty(&this.local_decls, this.tcx); + let ty = arg.ty(&this.local_decls, this.tcx); - if ty.is_integral() { - let arg = this.ecx.eval_operand(arg, None)?; - let prim = this.ecx.read_immediate(arg)?; - // Need to do overflow check here: For actual CTFE, MIR - // generation emits code that does this before calling the op. - if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { - throw_panic!(OverflowNeg) - } + if ty.is_integral() { + let arg = this.ecx.eval_operand(arg, None)?; + let prim = this.ecx.read_immediate(arg)?; + // Need to do overflow check here: For actual CTFE, MIR + // generation emits code that does this before calling the op. + if prim.to_bits()? == (1 << (prim.layout.size.bits() - 1)) { + throw_panic!(OverflowNeg) } } @@ -461,6 +467,8 @@ fn const_prop( })?; } + // Additional checking: check for overflows on integer binary operations and report + // them to the user as lints. Rvalue::BinaryOp(op, left, right) => { trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); @@ -490,25 +498,34 @@ fn const_prop( return None; } } - self.use_ecx(source_info, |this| { - let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; - let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?; - // We check overflow in debug mode already - // so should only check in release mode. - if !this.tcx.sess.overflow_checks() && overflow { - let err = err_panic!(Overflow(*op)).into(); - return Err(err); - } + // If overflow checking is enabled (like in debug mode by default), + // then we'll already catch overflow when we evaluate the `Assert` statement + // in MIR. However, if overflow checking is disabled, then there won't be any + // `Assert` statement and so we have to do additional checking here. + if !overflow_check { + self.use_ecx(source_info, |this| { + let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; + let (_, overflow, _ty) = this.ecx.overflowing_binary_op(*op, l, r)?; - Ok(()) - })?; + if overflow { + let err = err_panic!(Overflow(*op)).into(); + return Err(err); + } + + Ok(()) + })?; + } } + // Work around: avoid ICE in miri. + // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref + // from a function argument that hasn't been assigned to in this function. The main + // issue is if an arg is a fat-pointer, miri `expects()` to be able to read the value + // of that pointer to get size info. However, since this is `ConstProp`, that argument + // doesn't actually have a backing value and so this causes an ICE. Rvalue::Ref(_, _, Place { base: PlaceBase::Local(local), projection: box [] }) => { trace!("checking Ref({:?})", place); - // FIXME(wesleywiser) we don't currently handle the case where we try to make a ref - // from a function argument that hasn't been assigned to in this function. let alive = if let LocalValue::Live(_) = self.ecx.frame().locals[*local].value { true @@ -520,9 +537,10 @@ fn const_prop( } } + // Work around: avoid extra unnecessary locals. + // FIXME(wesleywiser): const eval will turn this into a `const Scalar()` that + // `SimplifyLocals` doesn't know it can remove. Rvalue::Aggregate(_, operands) if operands.len() == 0 => { - // FIXME(wesleywiser): const eval will turn this into a `const Scalar()` that - // `SimplifyLocals` doesn't know it can remove. return None; } From 696cba6e25fc7a8ee90e4db00f4df89dfe963d8e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Oct 2019 10:14:10 +0200 Subject: [PATCH 542/545] the exampleis about drop, not (de)allocation --- 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 1cab8026514e..205f0d7b4085 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -112,9 +112,9 @@ //! //! // Despite dropping `gadget_owner`, we're still able to print out the name //! // of the `Owner` of the `Gadget`s. This is because we've only dropped a -//! // single `Rc`, not the `Owner` allocation it points to. As long as there are +//! // single `Rc`, not the `Owner` it points to. As long as there are //! // other `Rc` pointing at the same `Owner` allocation, it will remain -//! // allocated. The field projection `gadget1.owner.name` works because +//! // live. The field projection `gadget1.owner.name` works because //! // `Rc` automatically dereferences to `Owner`. //! println!("Gadget {} owned by {}", gadget1.id, gadget1.owner.name); //! println!("Gadget {} owned by {}", gadget2.id, gadget2.owner.name); From 52a31f7a00095d99a1f56542f093b92d78ba1be3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Oct 2019 13:47:32 +0200 Subject: [PATCH 543/545] some more Rc tweaks --- src/liballoc/rc.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 205f0d7b4085..f1c4c32e116e 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -25,7 +25,7 @@ //! to an [`Rc`], but this will return [`None`] if the value stored in the allocation has //! already been dropped. In other words, `Weak` pointers do not keep the value //! inside the allocation alive; however, they *do* keep the allocation -//! (the backing store for the value) alive. +//! (the backing store for the inner value) alive. //! //! A cycle between [`Rc`] pointers will never be deallocated. For this reason, //! [`Weak`] is used to break cycles. For example, a tree could have strong @@ -44,8 +44,8 @@ //! Rc::downgrade(&my_rc); //! ``` //! -//! [`Weak`][`Weak`] does not auto-dereference to `T`, because the allocation may have -//! already been destroyed. +//! [`Weak`][`Weak`] does not auto-dereference to `T`, because the inner value may have +//! already been dropped. //! //! # Cloning references //! @@ -449,7 +449,7 @@ impl Rc> { /// # Safety /// /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the value + /// it is up to the caller to guarantee that the inner value /// really is in an initialized state. /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. @@ -488,7 +488,7 @@ impl Rc<[mem::MaybeUninit]> { /// # Safety /// /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the value + /// it is up to the caller to guarantee that the inner value /// really is in an initialized state. /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. @@ -883,7 +883,7 @@ pub fn downcast(self) -> Result, Rc> { impl Rc { /// Allocates an `RcBox` with sufficient space for - /// a possibly-unsized value where the value has the layout provided. + /// a possibly-unsized inner value where the value has the layout provided. /// /// The function `mem_to_rcbox` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `RcBox`. @@ -913,7 +913,7 @@ unsafe fn allocate_for_layout( inner } - /// Allocates an `RcBox` with sufficient space for an unsized value + /// Allocates an `RcBox` with sufficient space for an unsized inner value unsafe fn allocate_for_ptr(ptr: *const T) -> *mut RcBox { // Allocate for the `RcBox` using the given value. Self::allocate_for_layout( @@ -1177,6 +1177,8 @@ impl RcEqIdent for Rc { /// store large values, that are slow to clone, but also heavy to check for equality, causing this /// cost to pay off more easily. It's also more likely to have two `Rc` clones, that point to /// the same value, than two `&T`s. +/// +/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. #[stable(feature = "rust1", since = "1.0.0")] impl RcEqIdent for Rc { #[inline] @@ -1759,10 +1761,10 @@ pub(crate) fn is_dangling(ptr: NonNull) -> bool { } impl Weak { - /// Attempts to upgrade the `Weak` pointer to an [`Rc`], extending - /// the lifetime of the allocation if successful. + /// Attempts to upgrade the `Weak` pointer to an [`Rc`], delaying + /// dropping of the inner value if successful. /// - /// Returns [`None`] if the value stored in the allocation has since been dropped. + /// Returns [`None`] if the inner value has since been dropped. /// /// [`Rc`]: struct.Rc.html /// [`None`]: ../../std/option/enum.Option.html From 1b3846359a084f62eaab74390134011ed9e6cd48 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Oct 2019 13:48:02 +0200 Subject: [PATCH 544/545] do all the same edits with Arc --- src/liballoc/sync.rs | 116 ++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 51 deletions(-) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 5977e69b7fa0..69f8f71197c1 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -45,10 +45,10 @@ /// /// The type `Arc` provides shared ownership of a value of type `T`, /// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces -/// a new `Arc` instance, which points to the same value on the heap as the +/// a new `Arc` instance, which points to the same allocation on the heap as the /// source `Arc`, while increasing a reference count. When the last `Arc` -/// pointer to a given value is destroyed, the pointed-to value is also -/// destroyed. +/// pointer to a given allocation is destroyed, the value stored in that allocation (often +/// referred to as "inner value") is also dropped. /// /// Shared references in Rust disallow mutation by default, and `Arc` is no /// exception: you cannot generally obtain a mutable reference to something @@ -61,7 +61,7 @@ /// Unlike [`Rc`], `Arc` uses atomic operations for its reference /// counting. This means that it is thread-safe. The disadvantage is that /// atomic operations are more expensive than ordinary memory accesses. If you -/// are not sharing reference-counted values between threads, consider using +/// are not sharing reference-counted allocations between threads, consider using /// [`Rc`] for lower overhead. [`Rc`] is a safe default, because the /// compiler will catch any attempt to send an [`Rc`] between threads. /// However, a library might choose `Arc` in order to give library consumers @@ -85,8 +85,10 @@ /// /// The [`downgrade`][downgrade] method can be used to create a non-owning /// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d -/// to an `Arc`, but this will return [`None`] if the value has already been -/// dropped. +/// to an `Arc`, but this will return [`None`] if the value stored in the allocation has +/// already been dropped. In other words, `Weak` pointers do not keep the value +/// inside the allocation alive; however, they *do* keep the allocation +/// (the backing store for the value) alive. /// /// A cycle between `Arc` pointers will never be deallocated. For this reason, /// [`Weak`][weak] is used to break cycles. For example, a tree could have @@ -121,8 +123,8 @@ /// Arc::downgrade(&my_arc); /// ``` /// -/// [`Weak`][weak] does not auto-dereference to `T`, because the value may have -/// already been destroyed. +/// [`Weak`][weak] does not auto-dereference to `T`, because the inner value may have +/// already been dropped. /// /// [arc]: struct.Arc.html /// [weak]: struct.Weak.html @@ -221,17 +223,18 @@ unsafe fn from_ptr(ptr: *mut ArcInner) -> Self { } /// `Weak` is a version of [`Arc`] that holds a non-owning reference to the -/// managed value. The value is accessed by calling [`upgrade`] on the `Weak` +/// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [`Option`]`<`[`Arc`]`>`. /// /// Since a `Weak` reference does not count towards ownership, it will not -/// prevent the inner value from being dropped, and `Weak` itself makes no -/// guarantees about the value still being present and may return [`None`] -/// when [`upgrade`]d. +/// prevent the value stored in the allocation from being dropped, and `Weak` itself makes no +/// guarantees about the value still being present. Thus it may return [`None`] +/// when [`upgrade`]d. Note however that a `Weak` reference *does* prevent the allocation +/// itself (the backing store) from being deallocated. /// -/// A `Weak` pointer is useful for keeping a temporary reference to the value -/// within [`Arc`] without extending its lifetime. It is also used to prevent -/// circular references between [`Arc`] pointers, since mutual owning references +/// A `Weak` pointer is useful for keeping a temporary reference to the allocation +/// managed by [`Arc`] without preventing its inner value from being dropped. It is also used to +/// prevent circular references between [`Arc`] pointers, since mutual owning references /// would never allow either [`Arc`] to be dropped. For example, a tree could /// have strong [`Arc`] pointers from parent nodes to children, and `Weak` /// pointers from children back to their parents. @@ -345,7 +348,7 @@ pub fn pin(data: T) -> Pin> { unsafe { Pin::new_unchecked(Arc::new(data)) } } - /// Returns the contained value, if the `Arc` has exactly one strong reference. + /// Returns the inner value, if the `Arc` has exactly one strong reference. /// /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was /// passed in. @@ -426,7 +429,7 @@ impl Arc> { /// # Safety /// /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the value + /// it is up to the caller to guarantee that the inner value /// really is in an initialized state. /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. @@ -465,7 +468,7 @@ impl Arc<[mem::MaybeUninit]> { /// # Safety /// /// As with [`MaybeUninit::assume_init`], - /// it is up to the caller to guarantee that the value + /// it is up to the caller to guarantee that the inner value /// really is in an initialized state. /// Calling this when the content is not yet fully initialized /// causes immediate undefined behavior. @@ -584,7 +587,7 @@ pub fn into_raw_non_null(this: Self) -> NonNull { unsafe { NonNull::new_unchecked(Arc::into_raw(this) as *mut _) } } - /// Creates a new [`Weak`][weak] pointer to this value. + /// Creates a new [`Weak`][weak] pointer to this allocation. /// /// [weak]: struct.Weak.html /// @@ -628,7 +631,7 @@ pub fn downgrade(this: &Self) -> Weak { } } - /// Gets the number of [`Weak`][weak] pointers to this value. + /// Gets the number of [`Weak`][weak] pointers to this allocation. /// /// [weak]: struct.Weak.html /// @@ -659,7 +662,7 @@ pub fn weak_count(this: &Self) -> usize { if cnt == usize::MAX { 0 } else { cnt - 1 } } - /// Gets the number of strong (`Arc`) pointers to this value. + /// Gets the number of strong (`Arc`) pointers to this allocation. /// /// # Safety /// @@ -710,8 +713,8 @@ unsafe fn drop_slow(&mut self) { #[inline] #[stable(feature = "ptr_eq", since = "1.17.0")] - /// Returns `true` if the two `Arc`s point to the same value (not - /// just values that compare as equal). + /// Returns `true` if the two `Arc`s point to the same allocation + /// (in a vein similar to [`ptr::eq`]). /// /// # Examples /// @@ -725,6 +728,8 @@ unsafe fn drop_slow(&mut self) { /// assert!(Arc::ptr_eq(&five, &same_five)); /// assert!(!Arc::ptr_eq(&five, &other_five)); /// ``` + /// + /// [`ptr::eq`]: ../../std/ptr/fn.eq.html pub fn ptr_eq(this: &Self, other: &Self) -> bool { this.ptr.as_ptr() == other.ptr.as_ptr() } @@ -732,7 +737,7 @@ pub fn ptr_eq(this: &Self, other: &Self) -> bool { impl Arc { /// Allocates an `ArcInner` with sufficient space for - /// a possibly-unsized value where the value has the layout provided. + /// a possibly-unsized inner value where the value has the layout provided. /// /// The function `mem_to_arcinner` is called with the data pointer /// and must return back a (potentially fat)-pointer for the `ArcInner`. @@ -761,7 +766,7 @@ unsafe fn allocate_for_layout( inner } - /// Allocates an `ArcInner` with sufficient space for an unsized value. + /// Allocates an `ArcInner` with sufficient space for an unsized inner value. unsafe fn allocate_for_ptr(ptr: *const T) -> *mut ArcInner { // Allocate for the `ArcInner` using the given value. Self::allocate_for_layout( @@ -903,7 +908,7 @@ fn from_slice(v: &[T]) -> Self { impl Clone for Arc { /// Makes a clone of the `Arc` pointer. /// - /// This creates another pointer to the same inner value, increasing the + /// This creates another pointer to the same allocation, increasing the /// strong reference count. /// /// # Examples @@ -965,15 +970,19 @@ impl Receiver for Arc {} impl Arc { /// Makes a mutable reference into the given `Arc`. /// - /// If there are other `Arc` or [`Weak`][weak] pointers to the same value, - /// then `make_mut` will invoke [`clone`][clone] on the inner value to - /// ensure unique ownership. This is also referred to as clone-on-write. + /// If there are other `Arc` or [`Weak`][weak] pointers to the same allocation, + /// then `make_mut` will create a new allocation and invoke [`clone`][clone] on the inner value + /// to ensure unique ownership. This is also referred to as clone-on-write. + /// + /// Note that this differs from the behavior of [`Rc::make_mut`] which disassociates + /// any remaining `Weak` pointers. /// /// See also [`get_mut`][get_mut], which will fail rather than cloning. /// /// [weak]: struct.Weak.html /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone /// [get_mut]: struct.Arc.html#method.get_mut + /// [`Rc::make_mut`]: ../rc/struct.Rc.html#method.make_mut /// /// # Examples /// @@ -988,7 +997,7 @@ impl Arc { /// *Arc::make_mut(&mut data) += 1; // Won't clone anything /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything /// - /// // Now `data` and `other_data` point to different values. + /// // Now `data` and `other_data` point to different allocations. /// assert_eq!(*data, 8); /// assert_eq!(*other_data, 12); /// ``` @@ -1048,14 +1057,14 @@ pub fn make_mut(this: &mut Self) -> &mut T { } impl Arc { - /// Returns a mutable reference to the inner value, if there are - /// no other `Arc` or [`Weak`][weak] pointers to the same value. + /// Returns a mutable reference into the given `Arc`, if there are + /// no other `Arc` or [`Weak`][weak] pointers to the same allocation. /// /// Returns [`None`][option] otherwise, because it is not safe to /// mutate a shared value. /// /// See also [`make_mut`][make_mut], which will [`clone`][clone] - /// the inner value when it's shared. + /// the inner value when there are other pointers. /// /// [weak]: struct.Weak.html /// [option]: ../../std/option/enum.Option.html @@ -1091,7 +1100,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> { } } - /// Returns a mutable reference to the inner value, + /// Returns a mutable reference into the given `Arc`, /// without any check. /// /// See also [`get_mut`], which is safe and does appropriate checks. @@ -1100,7 +1109,7 @@ pub fn get_mut(this: &mut Self) -> Option<&mut T> { /// /// # Safety /// - /// Any other `Arc` or [`Weak`] pointers to the same value must not be dereferenced + /// Any other `Arc` or [`Weak`] pointers to the same allocation must not be dereferenced /// for the duration of the returned borrow. /// This is trivially the case if no such pointers exist, /// for example immediately after `Arc::new`. @@ -1424,10 +1433,10 @@ pub unsafe fn from_raw(ptr: *const T) -> Self { } impl Weak { - /// Attempts to upgrade the `Weak` pointer to an [`Arc`], extending - /// the lifetime of the value if successful. + /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying + /// dropping of the inner value if successful. /// - /// Returns [`None`] if the value has since been dropped. + /// Returns [`None`] if the inner value has since been dropped. /// /// [`Arc`]: struct.Arc.html /// [`None`]: ../../std/option/enum.Option.html#variant.None @@ -1482,7 +1491,7 @@ pub fn upgrade(&self) -> Option> { } } - /// Gets the number of strong (`Arc`) pointers pointing to this value. + /// Gets the number of strong (`Arc`) pointers pointing to this allocation. /// /// If `self` was created using [`Weak::new`], this will return 0. /// @@ -1497,17 +1506,17 @@ pub fn strong_count(&self) -> usize { } /// Gets an approximation of the number of `Weak` pointers pointing to this - /// value. + /// allocation. /// /// If `self` was created using [`Weak::new`], this will return 0. If not, /// the returned value is at least 1, since `self` still points to the - /// value. + /// allocation. /// /// # Accuracy /// /// Due to implementation details, the returned value can be off by 1 in /// either direction when other threads are manipulating any `Arc`s or - /// `Weak`s pointing to the same value. + /// `Weak`s pointing to the same allocation. /// /// [`Weak::new`]: #method.new #[unstable(feature = "weak_counts", issue = "57977")] @@ -1548,14 +1557,14 @@ fn inner(&self) -> Option<&ArcInner> { } } - /// Returns `true` if the two `Weak`s point to the same value (not just - /// values that compare as equal), or if both don't point to any value + /// Returns `true` if the two `Weak`s point to the same allocation (similar to + /// [`ptr::eq`]), or if both don't point to any allocation /// (because they were created with `Weak::new()`). /// /// # Notes /// /// Since this compares pointers it means that `Weak::new()` will equal each - /// other, even though they don't point to any value. + /// other, even though they don't point to any allocation. /// /// # Examples /// @@ -1587,6 +1596,8 @@ fn inner(&self) -> Option<&ArcInner> { /// let third = Arc::downgrade(&third_rc); /// assert!(!first.ptr_eq(&third)); /// ``` + /// + /// [`ptr::eq`]: ../../std/ptr/fn.eq.html #[inline] #[stable(feature = "weak_ptr_eq", since = "1.39.0")] pub fn ptr_eq(&self, other: &Self) -> bool { @@ -1596,7 +1607,7 @@ pub fn ptr_eq(&self, other: &Self) -> bool { #[stable(feature = "arc_weak", since = "1.4.0")] impl Clone for Weak { - /// Makes a clone of the `Weak` pointer that points to the same value. + /// Makes a clone of the `Weak` pointer that points to the same allocation. /// /// # Examples /// @@ -1726,6 +1737,8 @@ impl ArcEqIdent for Arc { /// store large values, that are slow to clone, but also heavy to check for equality, causing this /// cost to pay off more easily. It's also more likely to have two `Arc` clones, that point to /// the same value, than two `&T`s. +/// +/// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. #[stable(feature = "rust1", since = "1.0.0")] impl ArcEqIdent for Arc { #[inline] @@ -1743,10 +1756,11 @@ fn ne(&self, other: &Arc) -> bool { impl PartialEq for Arc { /// Equality for two `Arc`s. /// - /// Two `Arc`s are equal if their inner values are equal. + /// Two `Arc`s are equal if their inner values are equal, even if they are + /// stored in different allocation. /// - /// If `T` also implements `Eq`, two `Arc`s that point to the same value are - /// always equal. + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Arc`s that point to the same allocation are always equal. /// /// # Examples /// @@ -1766,8 +1780,8 @@ fn eq(&self, other: &Arc) -> bool { /// /// Two `Arc`s are unequal if their inner values are unequal. /// - /// If `T` also implements `Eq`, two `Arc`s that point to the same value are - /// never unequal. + /// If `T` also implements `Eq` (implying reflexivity of equality), + /// two `Arc`s that point to the same value are never unequal. /// /// # Examples /// From 90df0f4ec913e47294a5e1948dcd2c34e6c47c6e Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Sat, 19 Oct 2019 08:00:48 -0700 Subject: [PATCH 545/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 e979eb4cc55f..cbedd97b3a58 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit e979eb4cc55ffd357158c7d30133cbf894e93fe9 +Subproject commit cbedd97b3a58023eff365a2fa74700d06115144a