From f264d28f2cb941500d89e97a053ae96322c8ed86 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 28 Sep 2023 12:11:20 -0400 Subject: [PATCH 01/51] time: cfg(any(x)) is the same as cfg(x) This was left over in c043a0e7d6f347f9b2c7f08c5b3a179470e0f0c5. --- library/std/src/sys/unix/time.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 4fe61b28488b..c94a29b510a0 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -217,7 +217,7 @@ impl From<__timespec64> for Timespec { } #[cfg(any( - all(target_os = "macos", any(not(target_arch = "aarch64"))), + all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" @@ -338,7 +338,7 @@ mod inner { } #[cfg(not(any( - all(target_os = "macos", any(not(target_arch = "aarch64"))), + all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" From b21eb4f046284040b8e91aff0fd1e7c5125864d1 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 28 Sep 2023 12:27:24 -0400 Subject: [PATCH 02/51] time: use clock_gettime on macos Replace `gettimeofday` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `gettimeofday` was first used in https://github.com/time-rs/time/commit/cc367edd953e72756ed6f0980918795c11e469b1 which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca958d917a89124da248735926f86c59a149. --- library/std/src/sys/unix/time.rs | 84 +++++++++++++------------------- library/std/src/time.rs | 3 +- 2 files changed, 36 insertions(+), 51 deletions(-) diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index c94a29b510a0..3ad6e5d5d482 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -40,6 +40,10 @@ impl SystemTime { SystemTime { t: Timespec::new(tv_sec, tv_nsec) } } + pub fn now() -> SystemTime { + SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) } + } + pub fn sub_time(&self, other: &SystemTime) -> Result { self.t.sub_timespec(&other.t) } @@ -79,6 +83,36 @@ impl Timespec { Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32) } } } + pub fn now(clock: libc::clockid_t) -> Timespec { + use crate::mem::MaybeUninit; + use crate::sys::cvt; + + // Try to use 64-bit time in preparation for Y2038. + #[cfg(all( + target_os = "linux", + target_env = "gnu", + target_pointer_width = "32", + not(target_arch = "riscv32") + ))] + { + use crate::sys::weak::weak; + + // __clock_gettime64 was added to 32-bit arches in glibc 2.34, + // and it handles both vDSO calls and ENOSYS fallbacks itself. + weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int); + + if let Some(clock_gettime64) = __clock_gettime64.get() { + let mut t = MaybeUninit::uninit(); + cvt(unsafe { clock_gettime64(clock, t.as_mut_ptr()) }).unwrap(); + return Timespec::from(unsafe { t.assume_init() }); + } + } + + let mut t = MaybeUninit::uninit(); + cvt(unsafe { libc::clock_gettime(clock, t.as_mut_ptr()) }).unwrap(); + Timespec::from(unsafe { t.assume_init() }) + } + pub fn sub_timespec(&self, other: &Timespec) -> Result { if self >= other { // NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM @@ -224,7 +258,6 @@ impl From<__timespec64> for Timespec { ))] mod inner { use crate::sync::atomic::{AtomicU64, Ordering}; - use crate::sys::cvt; use crate::sys_common::mul_div_u64; use crate::time::Duration; @@ -268,16 +301,6 @@ mod inner { } } - impl SystemTime { - pub fn now() -> SystemTime { - use crate::ptr; - - let mut s = libc::timeval { tv_sec: 0, tv_usec: 0 }; - cvt(unsafe { libc::gettimeofday(&mut s, ptr::null_mut()) }).unwrap(); - return SystemTime::from(s); - } - } - impl From for Timespec { fn from(t: libc::timeval) -> Timespec { Timespec::new(t.tv_sec as i64, 1000 * t.tv_usec as i64) @@ -345,11 +368,9 @@ mod inner { )))] mod inner { use crate::fmt; - use crate::mem::MaybeUninit; - use crate::sys::cvt; use crate::time::Duration; - use super::{SystemTime, Timespec}; + use super::Timespec; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Instant { @@ -386,39 +407,4 @@ mod inner { .finish() } } - - impl SystemTime { - pub fn now() -> SystemTime { - SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) } - } - } - - impl Timespec { - pub fn now(clock: libc::clockid_t) -> Timespec { - // Try to use 64-bit time in preparation for Y2038. - #[cfg(all( - target_os = "linux", - target_env = "gnu", - target_pointer_width = "32", - not(target_arch = "riscv32") - ))] - { - use crate::sys::weak::weak; - - // __clock_gettime64 was added to 32-bit arches in glibc 2.34, - // and it handles both vDSO calls and ENOSYS fallbacks itself. - weak!(fn __clock_gettime64(libc::clockid_t, *mut super::__timespec64) -> libc::c_int); - - if let Some(clock_gettime64) = __clock_gettime64.get() { - let mut t = MaybeUninit::uninit(); - cvt(unsafe { clock_gettime64(clock, t.as_mut_ptr()) }).unwrap(); - return Timespec::from(unsafe { t.assume_init() }); - } - } - - let mut t = MaybeUninit::uninit(); - cvt(unsafe { libc::clock_gettime(clock, t.as_mut_ptr()) }).unwrap(); - Timespec::from(unsafe { t.assume_init() }) - } - } } diff --git a/library/std/src/time.rs b/library/std/src/time.rs index c638cc61856f..ddac069df760 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -221,7 +221,7 @@ pub struct Instant(time::Instant); /// |-----------|----------------------------------------------------------------------| /// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] | /// | UNIX | [clock_gettime (Realtime Clock)] | -/// | Darwin | [gettimeofday] | +/// | Darwin | [clock_gettime (Realtime Clock)] | /// | VXWorks | [clock_gettime (Realtime Clock)] | /// | SOLID | `SOLID_RTC_ReadTime` | /// | WASI | [__wasi_clock_time_get (Realtime Clock)] | @@ -230,7 +230,6 @@ pub struct Instant(time::Instant); /// [currently]: crate::io#platform-specific-behavior /// [`insecure_time` usercall]: https://edp.fortanix.com/docs/api/fortanix_sgx_abi/struct.Usercalls.html#method.insecure_time /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode -/// [gettimeofday]: https://man7.org/linux/man-pages/man2/gettimeofday.2.html /// [clock_gettime (Realtime Clock)]: https://linux.die.net/man/3/clock_gettime /// [__wasi_clock_time_get (Realtime Clock)]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get /// [GetSystemTimePreciseAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime From bc300102d4388860afa895149c1f52393a7aa964 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Thu, 28 Sep 2023 17:34:41 -0400 Subject: [PATCH 03/51] time: use clock_gettime on macos Replace `mach_{absolute_time,timebase_info}` with `clock_gettime(CLOCK_REALTIME)` on: ``` all(target_os = "macos", not(target_arch = "aarch64")), target_os = "ios", target_os = "watchos", target_os = "tvos" ))] ``` `mach_{absolute_time,timebase_info}` were first used in https://github.com/time-rs/time/commit/cc367edd953e72756ed6f0980918795c11e469b1 which predated the introduction of `clock_gettime` support in macOS 10.12 Sierra which became the minimum supported version in 58bbca958d917a89124da248735926f86c59a149. Note that this change was made for aarch64 in 5008a317ce8e508c390ed12bff281f307313376e which predated 10.12 becoming the minimum supported version. The discussion took place in https://github.com/rust-lang/rust/issues/91417 and in particular https://github.com/rust-lang/rust/issues/91417#issuecomment-992151582 and https://github.com/rust-lang/rust/issues/91417#issuecomment-1033048064 are relevant. --- library/std/src/sys/unix/time.rs | 194 +++++++------------------------ library/std/src/time.rs | 3 +- 2 files changed, 46 insertions(+), 151 deletions(-) diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 3ad6e5d5d482..e4540b99413b 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -1,8 +1,6 @@ use crate::fmt; use crate::time::Duration; -pub use self::inner::Instant; - const NSEC_PER_SEC: u64 = 1_000_000_000; pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() }; #[allow(dead_code)] // Used for pthread condvar timeouts @@ -250,161 +248,59 @@ impl From<__timespec64> for Timespec { } } -#[cfg(any( - all(target_os = "macos", not(target_arch = "aarch64")), - target_os = "ios", - target_os = "watchos", - target_os = "tvos" -))] -mod inner { - use crate::sync::atomic::{AtomicU64, Ordering}; - use crate::sys_common::mul_div_u64; - use crate::time::Duration; +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Instant { + t: Timespec, +} - use super::{SystemTime, Timespec, NSEC_PER_SEC}; - - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] - pub struct Instant { - t: u64, - } - - #[repr(C)] - #[derive(Copy, Clone)] - struct mach_timebase_info { - numer: u32, - denom: u32, - } - type mach_timebase_info_t = *mut mach_timebase_info; - type kern_return_t = libc::c_int; - - impl Instant { - pub fn now() -> Instant { - extern "C" { - fn mach_absolute_time() -> u64; - } - Instant { t: unsafe { mach_absolute_time() } } - } - - pub fn checked_sub_instant(&self, other: &Instant) -> Option { - let diff = self.t.checked_sub(other.t)?; - let info = info(); - let nanos = mul_div_u64(diff, info.numer as u64, info.denom as u64); - Some(Duration::new(nanos / NSEC_PER_SEC, (nanos % NSEC_PER_SEC) as u32)) - } - - pub fn checked_add_duration(&self, other: &Duration) -> Option { - Some(Instant { t: self.t.checked_add(checked_dur2intervals(other)?)? }) - } - - pub fn checked_sub_duration(&self, other: &Duration) -> Option { - Some(Instant { t: self.t.checked_sub(checked_dur2intervals(other)?)? }) - } - } - - impl From for Timespec { - fn from(t: libc::timeval) -> Timespec { - Timespec::new(t.tv_sec as i64, 1000 * t.tv_usec as i64) - } - } - - impl From for SystemTime { - fn from(t: libc::timeval) -> SystemTime { - SystemTime { t: Timespec::from(t) } - } - } - - fn checked_dur2intervals(dur: &Duration) -> Option { - let nanos = - dur.as_secs().checked_mul(NSEC_PER_SEC)?.checked_add(dur.subsec_nanos() as u64)?; - let info = info(); - Some(mul_div_u64(nanos, info.denom as u64, info.numer as u64)) - } - - fn info() -> mach_timebase_info { - // INFO_BITS conceptually is an `Option`. We can do - // this in 64 bits because we know 0 is never a valid value for the - // `denom` field. +impl Instant { + pub fn now() -> Instant { + // https://www.manpagez.com/man/3/clock_gettime/ // - // Encoding this as a single `AtomicU64` allows us to use `Relaxed` - // operations, as we are only interested in the effects on a single - // memory location. - static INFO_BITS: AtomicU64 = AtomicU64::new(0); - - // If a previous thread has initialized `INFO_BITS`, use it. - let info_bits = INFO_BITS.load(Ordering::Relaxed); - if info_bits != 0 { - return info_from_bits(info_bits); - } - - // ... otherwise learn for ourselves ... - extern "C" { - fn mach_timebase_info(info: mach_timebase_info_t) -> kern_return_t; - } - - let mut info = info_from_bits(0); - unsafe { - mach_timebase_info(&mut info); - } - INFO_BITS.store(info_to_bits(info), Ordering::Relaxed); - info + // CLOCK_UPTIME_RAW clock that increments monotonically, in the same man- + // ner as CLOCK_MONOTONIC_RAW, but that does not incre- + // ment while the system is asleep. The returned value + // is identical to the result of mach_absolute_time() + // after the appropriate mach_timebase conversion is + // applied. + // + // Instant on macos was historically implemented using mach_absolute_time; + // we preserve this value domain out of an abundance of caution. + #[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "watchos", + target_os = "tvos" + ))] + const clock_id: libc::clockid_t = libc::CLOCK_UPTIME_RAW; + #[cfg(not(any( + target_os = "macos", + target_os = "ios", + target_os = "watchos", + target_os = "tvos" + )))] + const clock_id: libc::clockid_t = libc::CLOCK_MONOTONIC; + Instant { t: Timespec::now(clock_id) } } - #[inline] - fn info_to_bits(info: mach_timebase_info) -> u64 { - ((info.denom as u64) << 32) | (info.numer as u64) + pub fn checked_sub_instant(&self, other: &Instant) -> Option { + self.t.sub_timespec(&other.t).ok() } - #[inline] - fn info_from_bits(bits: u64) -> mach_timebase_info { - mach_timebase_info { numer: bits as u32, denom: (bits >> 32) as u32 } + pub fn checked_add_duration(&self, other: &Duration) -> Option { + Some(Instant { t: self.t.checked_add_duration(other)? }) + } + + pub fn checked_sub_duration(&self, other: &Duration) -> Option { + Some(Instant { t: self.t.checked_sub_duration(other)? }) } } -#[cfg(not(any( - all(target_os = "macos", not(target_arch = "aarch64")), - target_os = "ios", - target_os = "watchos", - target_os = "tvos" -)))] -mod inner { - use crate::fmt; - use crate::time::Duration; - - use super::Timespec; - - #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub struct Instant { - t: Timespec, - } - - impl Instant { - pub fn now() -> Instant { - #[cfg(target_os = "macos")] - const clock_id: libc::clockid_t = libc::CLOCK_UPTIME_RAW; - #[cfg(not(target_os = "macos"))] - const clock_id: libc::clockid_t = libc::CLOCK_MONOTONIC; - Instant { t: Timespec::now(clock_id) } - } - - pub fn checked_sub_instant(&self, other: &Instant) -> Option { - self.t.sub_timespec(&other.t).ok() - } - - pub fn checked_add_duration(&self, other: &Duration) -> Option { - Some(Instant { t: self.t.checked_add_duration(other)? }) - } - - pub fn checked_sub_duration(&self, other: &Duration) -> Option { - Some(Instant { t: self.t.checked_sub_duration(other)? }) - } - } - - impl fmt::Debug for Instant { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Instant") - .field("tv_sec", &self.t.tv_sec) - .field("tv_nsec", &self.t.tv_nsec.0) - .finish() - } +impl fmt::Debug for Instant { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Instant") + .field("tv_sec", &self.t.tv_sec) + .field("tv_nsec", &self.t.tv_nsec.0) + .finish() } } diff --git a/library/std/src/time.rs b/library/std/src/time.rs index ddac069df760..04229ec6c548 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -109,7 +109,7 @@ pub use core::time::TryFromFloatSecsError; /// |-----------|----------------------------------------------------------------------| /// | SGX | [`insecure_time` usercall]. More information on [timekeeping in SGX] | /// | UNIX | [clock_gettime (Monotonic Clock)] | -/// | Darwin | [mach_absolute_time] | +/// | Darwin | [clock_gettime (Monotonic Clock)] | /// | VXWorks | [clock_gettime (Monotonic Clock)] | /// | SOLID | `get_tim` | /// | WASI | [__wasi_clock_time_get (Monotonic Clock)] | @@ -121,7 +121,6 @@ pub use core::time::TryFromFloatSecsError; /// [timekeeping in SGX]: https://edp.fortanix.com/docs/concepts/rust-std/#codestdtimecode /// [__wasi_clock_time_get (Monotonic Clock)]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#clock_time_get /// [clock_gettime (Monotonic Clock)]: https://linux.die.net/man/3/clock_gettime -/// [mach_absolute_time]: https://developer.apple.com/library/archive/documentation/Darwin/Conceptual/KernelProgramming/services/services.html /// /// **Disclaimer:** These system calls might change over time. /// From fca182b6a0c43f3240d6c76397cad1c143e3774c Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Thu, 5 Oct 2023 23:54:33 +0100 Subject: [PATCH 04/51] Windows: Support sub-millisecond sleep Use `CreateWaitableTimerExW` with `CREATE_WAITABLE_TIMER_HIGH_RESOLUTION`. Does not work before Windows 10, version 1803 so in that case we fallback to using `Sleep`. --- library/std/src/sys/windows/c/windows_sys.lst | 6 +++ library/std/src/sys/windows/c/windows_sys.rs | 32 ++++++++++++++++ library/std/src/sys/windows/thread.rs | 13 ++++++- library/std/src/sys/windows/time.rs | 38 +++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/windows/c/windows_sys.lst b/library/std/src/sys/windows/c/windows_sys.lst index 0aca37e2d454..9aabac32211a 100644 --- a/library/std/src/sys/windows/c/windows_sys.lst +++ b/library/std/src/sys/windows/c/windows_sys.lst @@ -2503,9 +2503,12 @@ Windows.Win32.System.Threading.CREATE_SEPARATE_WOW_VDM Windows.Win32.System.Threading.CREATE_SHARED_WOW_VDM Windows.Win32.System.Threading.CREATE_SUSPENDED Windows.Win32.System.Threading.CREATE_UNICODE_ENVIRONMENT +Windows.Win32.System.Threading.CREATE_WAITABLE_TIMER_HIGH_RESOLUTION +Windows.Win32.System.Threading.CREATE_WAITABLE_TIMER_MANUAL_RESET Windows.Win32.System.Threading.CreateEventW Windows.Win32.System.Threading.CreateProcessW Windows.Win32.System.Threading.CreateThread +Windows.Win32.System.Threading.CreateWaitableTimerExW Windows.Win32.System.Threading.DEBUG_ONLY_THIS_PROCESS Windows.Win32.System.Threading.DEBUG_PROCESS Windows.Win32.System.Threading.DeleteProcThreadAttributeList @@ -2542,6 +2545,7 @@ Windows.Win32.System.Threading.REALTIME_PRIORITY_CLASS Windows.Win32.System.Threading.ReleaseSRWLockExclusive Windows.Win32.System.Threading.ReleaseSRWLockShared Windows.Win32.System.Threading.SetThreadStackGuarantee +Windows.Win32.System.Threading.SetWaitableTimer Windows.Win32.System.Threading.Sleep Windows.Win32.System.Threading.SleepConditionVariableSRW Windows.Win32.System.Threading.SleepEx @@ -2568,6 +2572,8 @@ Windows.Win32.System.Threading.TerminateProcess Windows.Win32.System.Threading.THREAD_CREATE_RUN_IMMEDIATELY Windows.Win32.System.Threading.THREAD_CREATE_SUSPENDED Windows.Win32.System.Threading.THREAD_CREATION_FLAGS +Windows.Win32.System.Threading.TIMER_ALL_ACCESS +Windows.Win32.System.Threading.TIMER_MODIFY_STATE Windows.Win32.System.Threading.TLS_OUT_OF_INDEXES Windows.Win32.System.Threading.TlsAlloc Windows.Win32.System.Threading.TlsFree diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs index 851d15915c7d..a22854367bea 100644 --- a/library/std/src/sys/windows/c/windows_sys.rs +++ b/library/std/src/sys/windows/c/windows_sys.rs @@ -151,6 +151,15 @@ extern "system" { ) -> HANDLE; } #[link(name = "kernel32")] +extern "system" { + pub fn CreateWaitableTimerExW( + lptimerattributes: *const SECURITY_ATTRIBUTES, + lptimername: PCWSTR, + dwflags: u32, + dwdesiredaccess: u32, + ) -> HANDLE; +} +#[link(name = "kernel32")] extern "system" { pub fn DeleteFileW(lpfilename: PCWSTR) -> BOOL; } @@ -508,6 +517,17 @@ extern "system" { pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; } #[link(name = "kernel32")] +extern "system" { + pub fn SetWaitableTimer( + htimer: HANDLE, + lpduetime: *const i64, + lperiod: i32, + pfncompletionroutine: PTIMERAPCROUTINE, + lpargtocompletionroutine: *const ::core::ffi::c_void, + fresume: BOOL, + ) -> BOOL; +} +#[link(name = "kernel32")] extern "system" { pub fn Sleep(dwmilliseconds: u32) -> (); } @@ -1164,6 +1184,8 @@ pub const CREATE_SEPARATE_WOW_VDM: PROCESS_CREATION_FLAGS = 2048u32; pub const CREATE_SHARED_WOW_VDM: PROCESS_CREATION_FLAGS = 4096u32; pub const CREATE_SUSPENDED: PROCESS_CREATION_FLAGS = 4u32; pub const CREATE_UNICODE_ENVIRONMENT: PROCESS_CREATION_FLAGS = 1024u32; +pub const CREATE_WAITABLE_TIMER_HIGH_RESOLUTION: u32 = 2u32; +pub const CREATE_WAITABLE_TIMER_MANUAL_RESET: u32 = 1u32; pub const CSTR_EQUAL: COMPARESTRING_RESULT = 2i32; pub const CSTR_GREATER_THAN: COMPARESTRING_RESULT = 3i32; pub const CSTR_LESS_THAN: COMPARESTRING_RESULT = 1i32; @@ -3774,6 +3796,13 @@ pub const PROFILE_SERVER: PROCESS_CREATION_FLAGS = 1073741824u32; pub const PROFILE_USER: PROCESS_CREATION_FLAGS = 268435456u32; pub const PROGRESS_CONTINUE: u32 = 0u32; pub type PSTR = *mut u8; +pub type PTIMERAPCROUTINE = ::core::option::Option< + unsafe extern "system" fn( + lpargtocompletionroutine: *const ::core::ffi::c_void, + dwtimerlowvalue: u32, + dwtimerhighvalue: u32, + ) -> (), +>; pub type PWSTR = *mut u16; pub const READ_CONTROL: FILE_ACCESS_RIGHTS = 131072u32; pub const REALTIME_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 256u32; @@ -3910,6 +3939,7 @@ pub type SYMBOLIC_LINK_FLAGS = u32; pub const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE: SYMBOLIC_LINK_FLAGS = 2u32; pub const SYMBOLIC_LINK_FLAG_DIRECTORY: SYMBOLIC_LINK_FLAGS = 1u32; pub const SYMLINK_FLAG_RELATIVE: u32 = 1u32; +pub type SYNCHRONIZATION_ACCESS_RIGHTS = u32; pub const SYNCHRONIZE: FILE_ACCESS_RIGHTS = 1048576u32; #[repr(C)] pub struct SYSTEM_INFO { @@ -3956,6 +3986,8 @@ pub const TCP_NODELAY: i32 = 1i32; pub const THREAD_CREATE_RUN_IMMEDIATELY: THREAD_CREATION_FLAGS = 0u32; pub const THREAD_CREATE_SUSPENDED: THREAD_CREATION_FLAGS = 4u32; pub type THREAD_CREATION_FLAGS = u32; +pub const TIMER_ALL_ACCESS: SYNCHRONIZATION_ACCESS_RIGHTS = 2031619u32; +pub const TIMER_MODIFY_STATE: SYNCHRONIZATION_ACCESS_RIGHTS = 2u32; #[repr(C)] pub struct TIMEVAL { pub tv_sec: i32, diff --git a/library/std/src/sys/windows/thread.rs b/library/std/src/sys/windows/thread.rs index 18cecb65681d..4117760dae3f 100644 --- a/library/std/src/sys/windows/thread.rs +++ b/library/std/src/sys/windows/thread.rs @@ -12,6 +12,7 @@ use crate::time::Duration; use libc::c_void; +use super::time::WaitableTimer; use super::to_u16s; pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024; @@ -87,7 +88,17 @@ impl Thread { } pub fn sleep(dur: Duration) { - unsafe { c::Sleep(super::dur2timeout(dur)) } + fn high_precision_sleep(dur: Duration) -> Result<(), ()> { + let timer = WaitableTimer::high_resolution()?; + timer.set(dur)?; + timer.wait() + } + // Attempt to use high-precision sleep (Windows 10, version 1803+). + // On error fallback to the standard `Sleep` function. + // Also preserves the zero duration behaviour of `Sleep`. + if dur.is_zero() || high_precision_sleep(dur).is_err() { + unsafe { c::Sleep(super::dur2timeout(dur)) } + } } pub fn handle(&self) -> &Handle { diff --git a/library/std/src/sys/windows/time.rs b/library/std/src/sys/windows/time.rs index b8209a854458..bece48e799f8 100644 --- a/library/std/src/sys/windows/time.rs +++ b/library/std/src/sys/windows/time.rs @@ -1,11 +1,13 @@ use crate::cmp::Ordering; use crate::fmt; use crate::mem; +use crate::ptr::{null, null_mut}; use crate::sys::c; use crate::sys_common::IntoInner; use crate::time::Duration; use core::hash::{Hash, Hasher}; +use core::ops::Neg; const NANOS_PER_SEC: u64 = 1_000_000_000; const INTERVALS_PER_SEC: u64 = NANOS_PER_SEC / 100; @@ -222,3 +224,39 @@ mod perf_counter { qpc_value } } + +/// A timer you can wait on. +pub(super) struct WaitableTimer { + handle: c::HANDLE, +} +impl WaitableTimer { + /// Create a high-resolution timer. Will fail before Windows 10, version 1803. + pub fn high_resolution() -> Result { + let handle = unsafe { + c::CreateWaitableTimerExW( + null(), + null(), + c::CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, + c::TIMER_ALL_ACCESS, + ) + }; + if handle != null_mut() { Ok(Self { handle }) } else { Err(()) } + } + pub fn set(&self, duration: Duration) -> Result<(), ()> { + // Convert the Duration to a format similar to FILETIME. + // Negative values are relative times whereas positive values are absolute. + // Therefore we negate the relative duration. + let time = checked_dur2intervals(&duration).ok_or(())?.neg(); + let result = unsafe { c::SetWaitableTimer(self.handle, &time, 0, None, null(), c::FALSE) }; + if result != 0 { Ok(()) } else { Err(()) } + } + pub fn wait(&self) -> Result<(), ()> { + let result = unsafe { c::WaitForSingleObject(self.handle, c::INFINITE) }; + if result != c::WAIT_FAILED { Ok(()) } else { Err(()) } + } +} +impl Drop for WaitableTimer { + fn drop(&mut self) { + unsafe { c::CloseHandle(self.handle) }; + } +} From fbf256716e499d9b2ee15c722c63d90d960f2859 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 6 Oct 2023 01:16:36 +0100 Subject: [PATCH 05/51] Miri: Add `CreateWaitableTimerEx` stub This function will always fail, allowing std's `Sleep` fallback path to be taken instead. --- src/tools/miri/src/shims/windows/foreign_items.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index d76d01b07891..24bb51ef5cb6 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -267,6 +267,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.Sleep(timeout)?; } + "CreateWaitableTimerExW" => { + let [attributes, name, flags, access] = + this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; + this.read_pointer(attributes)?; + this.read_pointer(name)?; + this.read_scalar(flags)?.to_u32()?; + this.read_scalar(access)?.to_u32()?; + // Unimplemented. Always return failure. + let not_supported = this.eval_windows("c", "ERROR_NOT_SUPPORTED"); + this.set_last_error(not_supported)?; + this.write_null(dest)?; + } // Synchronization primitives "AcquireSRWLockExclusive" => { From 963131e99ccd3a85e6df6676dc2d3ac7cf6ae7e3 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sat, 14 Oct 2023 00:40:18 +0000 Subject: [PATCH 06/51] Derive `Ord`, `PartialOrd` and `Hash` for `SocketAddr*` ...instead of hand rolling impls, since 1. It's nicer 2. It fixes a buggy `Ord` impl of `SocketAddrV6`, which ignored half of the fields --- library/core/src/net/socket_addr.rs | 51 ++--------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) diff --git a/library/core/src/net/socket_addr.rs b/library/core/src/net/socket_addr.rs index 8396aecf947a..55116285842a 100644 --- a/library/core/src/net/socket_addr.rs +++ b/library/core/src/net/socket_addr.rs @@ -1,6 +1,4 @@ -use crate::cmp::Ordering; use crate::fmt::{self, Write}; -use crate::hash; use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use super::display_buffer::DisplayBuffer; @@ -63,7 +61,7 @@ pub enum SocketAddr { /// assert_eq!(socket.ip(), &Ipv4Addr::new(127, 0, 0, 1)); /// assert_eq!(socket.port(), 8080); /// ``` -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SocketAddrV4 { ip: Ipv4Addr, @@ -96,7 +94,7 @@ pub struct SocketAddrV4 { /// assert_eq!(socket.ip(), &Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1)); /// assert_eq!(socket.port(), 8080); /// ``` -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[stable(feature = "rust1", since = "1.0.0")] pub struct SocketAddrV6 { ip: Ipv6Addr, @@ -644,48 +642,3 @@ impl fmt::Debug for SocketAddrV6 { fmt::Display::fmt(self, fmt) } } - -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl PartialOrd for SocketAddrV4 { - #[inline] - fn partial_cmp(&self, other: &SocketAddrV4) -> Option { - Some(self.cmp(other)) - } -} - -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl PartialOrd for SocketAddrV6 { - #[inline] - fn partial_cmp(&self, other: &SocketAddrV6) -> Option { - Some(self.cmp(other)) - } -} - -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl Ord for SocketAddrV4 { - #[inline] - fn cmp(&self, other: &SocketAddrV4) -> Ordering { - self.ip().cmp(other.ip()).then(self.port().cmp(&other.port())) - } -} - -#[stable(feature = "socketaddr_ordering", since = "1.45.0")] -impl Ord for SocketAddrV6 { - #[inline] - fn cmp(&self, other: &SocketAddrV6) -> Ordering { - self.ip().cmp(other.ip()).then(self.port().cmp(&other.port())) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for SocketAddrV4 { - fn hash(&self, s: &mut H) { - (self.port, self.ip).hash(s) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for SocketAddrV6 { - fn hash(&self, s: &mut H) { - (self.port, &self.ip, self.flowinfo, self.scope_id).hash(s) - } -} From 5c13c69f63dccdc637d28b403ae1fb687e0a5143 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 15 Oct 2023 12:25:58 +0000 Subject: [PATCH 07/51] Add tests for `SocketAddrV6` ordering with scope_id and flowinfo --- library/core/tests/net/socket_addr.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/core/tests/net/socket_addr.rs b/library/core/tests/net/socket_addr.rs index 35a69cead482..3d013d37e04a 100644 --- a/library/core/tests/net/socket_addr.rs +++ b/library/core/tests/net/socket_addr.rs @@ -199,6 +199,9 @@ fn compare() { let v6_1 = "[2001:db8:f00::1002]:23456".parse::().unwrap(); let v6_2 = "[2001:db8:f00::2001]:12345".parse::().unwrap(); let v6_3 = "[2001:db8:f00::2001]:23456".parse::().unwrap(); + let v6_4 = "[2001:db8:f00::2001%42]:23456".parse::().unwrap(); + let mut v6_5 = "[2001:db8:f00::2001]:23456".parse::().unwrap(); + v6_5.set_flowinfo(17); // equality assert_eq!(v4_1, v4_1); @@ -207,6 +210,8 @@ fn compare() { assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1)); assert!(v4_1 != v4_2); assert!(v6_1 != v6_2); + assert!(v6_3 != v6_4); + assert!(v6_3 != v6_5); // compare different addresses assert!(v4_1 < v4_2); @@ -226,6 +231,12 @@ fn compare() { assert!(v4_3 > v4_1); assert!(v6_3 > v6_1); + // compare the same address with different scope_id + assert!(v6_3 < v6_4); + + // compare the same address with different flowinfo + assert!(v6_3 < v6_5); + // compare with an inferred right-hand side assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap()); assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap()); From 2bba98b1216e21fcb18e2242c491ae7205af8308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jon=C3=A1=C5=A1=20Fiala?= Date: Mon, 16 Oct 2023 14:29:36 +0200 Subject: [PATCH 08/51] Avoid unnecessary renumbering --- compiler/rustc_borrowck/src/renumber.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 5d6f5cc89678..ec0131c5349a 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -81,6 +81,10 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> { #[instrument(skip(self), level = "debug")] fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { + if matches!(ty_context, TyContext::ReturnTy(_)) { + // We will renumber the return ty when called again with `TyContext::LocalDecl` + return; + } *ty = self.renumber_regions(*ty, || RegionCtxt::TyContext(ty_context)); debug!(?ty); From 5cc83fd4a5fb4860f67cf0b92b41c1aa9f87a54b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 5 Oct 2023 14:57:14 +0000 Subject: [PATCH 09/51] Fix inline const pattern unsafety checking in THIR THIR unsafety checking was getting a cycle of function unsafety checking -> building THIR for the function -> evaluating pattern inline constants in the function -> building MIR for the inline constant -> checking unsafety of functions (so that THIR can be stolen) This is fixed by not stealing THIR when generating MIR but instead when unsafety checking. This leaves an issue with pattern inline constants not being unsafety checked because they are evaluated away when generating THIR. To fix that we now represent inline constants in THIR patterns and visit them in THIR unsafety checking. --- compiler/rustc_interface/src/passes.rs | 8 ++++-- compiler/rustc_middle/src/thir.rs | 11 +++++++- compiler/rustc_middle/src/thir/visit.rs | 7 ++--- .../rustc_mir_build/src/build/matches/mod.rs | 4 +++ .../src/build/matches/simplify.rs | 24 ++++++++++++++--- .../rustc_mir_build/src/build/matches/test.rs | 2 ++ compiler/rustc_mir_build/src/build/mod.rs | 25 ++++++++++------- .../rustc_mir_build/src/check_unsafety.rs | 27 ++++++++++++++++--- .../src/thir/pattern/deconstruct_pat.rs | 3 ++- .../rustc_mir_build/src/thir/pattern/mod.rs | 13 ++++++--- compiler/rustc_mir_build/src/thir/print.rs | 7 +++++ .../async-unsafe-fn-call-in-safe.mir.stderr | 2 +- .../async-unsafe-fn-call-in-safe.rs | 8 ++++-- .../async-unsafe-fn-call-in-safe.thir.stderr | 18 ++++++++++++- .../const-extern-fn-requires-unsafe.rs | 1 + ...onst-extern-fn-requires-unsafe.thir.stderr | 10 ++++++- tests/ui/inline-const/pat-unsafe-err.rs | 14 ++++++++-- .../inline-const/pat-unsafe-err.thir.stderr | 19 +++++++++++++ tests/ui/inline-const/pat-unsafe.rs | 15 +++++++++-- tests/ui/inline-const/pat-unsafe.thir.stderr | 26 ++++++++++++++++++ .../non-structural-match-types.mir.stderr | 14 ++++++++++ .../ui/pattern/non-structural-match-types.rs | 3 +++ .../pattern/non-structural-match-types.stderr | 14 ---------- .../non-structural-match-types.thir.stderr | 14 ++++++++++ 24 files changed, 239 insertions(+), 50 deletions(-) create mode 100644 tests/ui/inline-const/pat-unsafe-err.thir.stderr create mode 100644 tests/ui/inline-const/pat-unsafe.thir.stderr create mode 100644 tests/ui/pattern/non-structural-match-types.mir.stderr delete mode 100644 tests/ui/pattern/non-structural-match-types.stderr create mode 100644 tests/ui/pattern/non-structural-match-types.thir.stderr diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 718dbaaafcce..461952ac4b4c 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -775,12 +775,16 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> { rustc_hir_analysis::check_crate(tcx)?; sess.time("MIR_borrow_checking", || { - tcx.hir().par_body_owners(|def_id| tcx.ensure().mir_borrowck(def_id)); + tcx.hir().par_body_owners(|def_id| { + // Run THIR unsafety check because it's responsible for stealing + // and deallocating THIR when enabled. + tcx.ensure().thir_check_unsafety(def_id); + tcx.ensure().mir_borrowck(def_id) + }); }); sess.time("MIR_effect_checking", || { for def_id in tcx.hir().body_owners() { - tcx.ensure().thir_check_unsafety(def_id); if !tcx.sess.opts.unstable_opts.thir_unsafeck { rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id); } diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 67804998a329..80d11c8b8f89 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -636,7 +636,8 @@ impl<'tcx> Pat<'tcx> { Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } | Error(_) => {} AscribeUserType { subpattern, .. } | Binding { subpattern: Some(subpattern), .. } - | Deref { subpattern } => subpattern.walk_(it), + | Deref { subpattern } + | InlineConstant { subpattern, .. } => subpattern.walk_(it), Leaf { subpatterns } | Variant { subpatterns, .. } => { subpatterns.iter().for_each(|field| field.pattern.walk_(it)) } @@ -764,6 +765,11 @@ pub enum PatKind<'tcx> { value: mir::Const<'tcx>, }, + InlineConstant { + value: mir::UnevaluatedConst<'tcx>, + subpattern: Box>, + }, + Range(Box>), /// Matches against a slice, checking the length and extracting elements. @@ -924,6 +930,9 @@ impl<'tcx> fmt::Display for Pat<'tcx> { write!(f, "{subpattern}") } PatKind::Constant { value } => write!(f, "{value}"), + PatKind::InlineConstant { value: _, ref subpattern } => { + write!(f, "{} (from inline const)", subpattern) + } PatKind::Range(box PatRange { lo, hi, end }) => { write!(f, "{lo}")?; write!(f, "{end}")?; diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index afb58438519c..3da484e6f1b3 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -233,16 +233,17 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' } } Constant { value: _ } => {} + InlineConstant { value: _, subpattern } => visitor.visit_pat(subpattern), Range(_) => {} Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { for subpattern in prefix.iter() { - visitor.visit_pat(&subpattern); + visitor.visit_pat(subpattern); } if let Some(pat) = slice { - visitor.visit_pat(&pat); + visitor.visit_pat(pat); } for subpattern in suffix.iter() { - visitor.visit_pat(&subpattern); + visitor.visit_pat(subpattern); } } Or { pats } => { diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 24c6e0eae367..1cf8c202ea4b 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -847,6 +847,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.visit_primary_bindings(subpattern, subpattern_user_ty, f) } + PatKind::InlineConstant { ref subpattern, .. } => { + self.visit_primary_bindings(subpattern, pattern_user_ty.clone(), f) + } + PatKind::Leaf { ref subpatterns } => { for subpattern in subpatterns { let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field); diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index f340feb40d4a..e55daa6ee5f1 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -204,6 +204,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Err(match_pair) } + PatKind::InlineConstant { subpattern: ref pattern, value: _ } => { + candidate.match_pairs.push(MatchPair::new(match_pair.place, pattern, self)); + + Ok(()) + } + PatKind::Range(box PatRange { lo, hi, end }) => { let (range, bias) = match *lo.ty().kind() { ty::Char => { @@ -229,11 +235,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // correct the comparison. This is achieved by XORing with a bias (see // pattern/_match.rs for another pertinent example of this pattern). // - // Also, for performance, it's important to only do the second `try_to_bits` if - // necessary. - let lo = lo.try_to_bits(sz).unwrap() ^ bias; + // Also, for performance, it's important to only do the second + // `try_eval_scalar_int` if necessary. + let lo = lo + .try_eval_scalar_int(self.tcx, self.param_env) + .unwrap() + .to_bits(sz) + .unwrap() + ^ bias; if lo <= min { - let hi = hi.try_to_bits(sz).unwrap() ^ bias; + let hi = hi + .try_eval_scalar_int(self.tcx, self.param_env) + .unwrap() + .to_bits(sz) + .unwrap() + ^ bias; if hi > max || hi == max && end == RangeEnd::Included { // Irrefutable pattern match. return Ok(()); diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index 30ce37a7ac1d..5e7db7413df4 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -73,6 +73,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Or { .. } => bug!("or-patterns should have already been handled"), PatKind::AscribeUserType { .. } + | PatKind::InlineConstant { .. } | PatKind::Array { .. } | PatKind::Wild | PatKind::Binding { .. } @@ -111,6 +112,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | PatKind::Or { .. } | PatKind::Binding { .. } | PatKind::AscribeUserType { .. } + | PatKind::InlineConstant { .. } | PatKind::Leaf { .. } | PatKind::Deref { .. } | PatKind::Error(_) => { diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index d9098bac1c2b..3ef173c63e71 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -53,10 +53,7 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>( } /// Construct the MIR for a given `DefId`. -fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { - // Ensure unsafeck and abstract const building is ran before we steal the THIR. - tcx.ensure_with_value() - .thir_check_unsafety(tcx.typeck_root_def_id(def.to_def_id()).expect_local()); +fn mir_build<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { tcx.ensure_with_value().thir_abstract_const(def); if let Err(e) = tcx.check_match(def) { return construct_error(tcx, def, e); @@ -65,9 +62,10 @@ fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { let body = match tcx.thir_body(def) { Err(error_reported) => construct_error(tcx, def, error_reported), Ok((thir, expr)) => { - // We ran all queries that depended on THIR at the beginning - // of `mir_build`, so now we can steal it - let thir = thir.steal(); + let build_mir = |thir: &Thir<'tcx>| match thir.body_type { + thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, thir, expr, fn_sig), + thir::BodyTy::Const(ty) => construct_const(tcx, def, thir, expr, ty), + }; tcx.ensure().check_match(def); // this must run before MIR dump, because @@ -76,9 +74,16 @@ fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { // maybe move the check to a MIR pass? tcx.ensure().check_liveness(def); - match thir.body_type { - thir::BodyTy::Fn(fn_sig) => construct_fn(tcx, def, &thir, expr, fn_sig), - thir::BodyTy::Const(ty) => construct_const(tcx, def, &thir, expr, ty), + if tcx.sess.opts.unstable_opts.thir_unsafeck { + // Don't steal here if THIR unsafeck is being used. Instead + // steal in unsafeck. This is so that pattern inline constants + // can be evaluated as part of building the THIR of the parent + // function without a cycle. + build_mir(&thir.borrow()) + } else { + // We ran all queries that depended on THIR at the beginning + // of `mir_build`, so now we can steal it + build_mir(&thir.steal()) } } }; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 2d221b826c9b..f0b01e94587d 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -3,7 +3,7 @@ use crate::errors::*; use rustc_middle::thir::visit::{self, Visitor}; use rustc_hir as hir; -use rustc_middle::mir::BorrowKind; +use rustc_middle::mir::{BorrowKind, Const}; use rustc_middle::thir::*; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; @@ -124,7 +124,8 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { /// Handle closures/generators/inline-consts, which is unsafecked with their parent body. fn visit_inner_body(&mut self, def: LocalDefId) { if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) { - let inner_thir = &inner_thir.borrow(); + let _ = self.tcx.ensure_with_value().mir_built(def); + let inner_thir = &inner_thir.steal(); let hir_context = self.tcx.hir().local_def_id_to_hir_id(def); let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self }; inner_visitor.visit_expr(&inner_thir[expr]); @@ -224,6 +225,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { PatKind::Wild | // these just wrap other patterns PatKind::Or { .. } | + PatKind::InlineConstant { .. } | PatKind::AscribeUserType { .. } | PatKind::Error(_) => {} } @@ -277,6 +279,24 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { visit::walk_pat(self, pat); self.inside_adt = old_inside_adt; } + PatKind::Range(range) => { + if let Const::Unevaluated(c, _) = range.lo { + if let hir::def::DefKind::InlineConst = self.tcx.def_kind(c.def) { + let def_id = c.def.expect_local(); + self.visit_inner_body(def_id); + } + } + if let Const::Unevaluated(c, _) = range.hi { + if let hir::def::DefKind::InlineConst = self.tcx.def_kind(c.def) { + let def_id = c.def.expect_local(); + self.visit_inner_body(def_id); + } + } + } + PatKind::InlineConstant { value, .. } => { + let def_id = value.def.expect_local(); + self.visit_inner_body(def_id); + } _ => { visit::walk_pat(self, pat); } @@ -788,7 +808,8 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { } let Ok((thir, expr)) = tcx.thir_body(def) else { return }; - let thir = &thir.borrow(); + let _ = tcx.ensure_with_value().mir_built(def); + let thir = &thir.steal(); // If `thir` is empty, a type error occurred, skip this body. if thir.exprs.is_empty() { return; diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index bbc0aeb66cfd..06b7557c03af 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -1356,7 +1356,8 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { let ctor; let fields; match &pat.kind { - PatKind::AscribeUserType { subpattern, .. } => return mkpat(subpattern), + PatKind::AscribeUserType { subpattern, .. } + | PatKind::InlineConstant { subpattern, .. } => return mkpat(subpattern), PatKind::Binding { subpattern: Some(subpat), .. } => return mkpat(subpat), PatKind::Binding { subpattern: None, .. } | PatKind::Wild => { ctor = Wildcard; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 76ed6d2b6d73..0d066d9800b2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -93,6 +93,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { None => Ok((None, None)), Some(expr) => { let (kind, ascr) = match self.lower_lit(expr) { + PatKind::InlineConstant { subpattern, value } => ( + PatKind::Constant { value: Const::Unevaluated(value, subpattern.ty) }, + None, + ), PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { (kind, Some(ascription)) } @@ -633,13 +637,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span)) { - self.const_to_pat( + let subpattern = self.const_to_pat( Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span, None, - ) - .kind + ); + PatKind::InlineConstant { subpattern, value: uneval } } else { // If that fails, convert it to an opaque constant pattern. match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) { @@ -822,6 +826,9 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { PatKind::Deref { subpattern: subpattern.fold_with(folder) } } PatKind::Constant { value } => PatKind::Constant { value }, + PatKind::InlineConstant { value, subpattern: ref pattern } => { + PatKind::InlineConstant { value, subpattern: pattern.fold_with(folder) } + } PatKind::Range(ref range) => PatKind::Range(range.clone()), PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice { prefix: prefix.fold_with(folder), diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index c957611b975c..519622d450a8 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -701,6 +701,13 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("value: {:?}", value), depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } + PatKind::InlineConstant { value, subpattern } => { + print_indented!(self, "InlineConstant {", depth_lvl + 1); + print_indented!(self, format!("value: {:?}", value), depth_lvl + 2); + print_indented!(self, "subpattern: ", depth_lvl + 2); + self.print_pat(subpattern, depth_lvl + 2); + print_indented!(self, "}", depth_lvl + 1); + } PatKind::Range(pat_range) => { print_indented!(self, format!("Range ( {:?} )", pat_range), depth_lvl + 1); } diff --git a/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr b/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr index 2114fb59ba3a..f9e5bf675cbd 100644 --- a/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr +++ b/tests/ui/async-await/async-unsafe-fn-call-in-safe.mir.stderr @@ -23,7 +23,7 @@ LL | S::f(); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/async-unsafe-fn-call-in-safe.rs:24:5 + --> $DIR/async-unsafe-fn-call-in-safe.rs:26:5 | LL | f(); | ^^^ call to unsafe function diff --git a/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs b/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs index c941dc27aa30..14cc0dc614fc 100644 --- a/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs +++ b/tests/ui/async-await/async-unsafe-fn-call-in-safe.rs @@ -20,6 +20,10 @@ async fn g() { } fn main() { - S::f(); //[mir]~ ERROR call to unsafe function is unsafe - f(); //[mir]~ ERROR call to unsafe function is unsafe + S::f(); + //[mir]~^ ERROR call to unsafe function is unsafe + //[thir]~^^ ERROR call to unsafe function `S::f` is unsafe + f(); + //[mir]~^ ERROR call to unsafe function is unsafe + //[thir]~^^ ERROR call to unsafe function `f` is unsafe } diff --git a/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr b/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr index 68d97d3fd7d5..ba3303fe7939 100644 --- a/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr +++ b/tests/ui/async-await/async-unsafe-fn-call-in-safe.thir.stderr @@ -14,6 +14,22 @@ LL | f(); | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to 2 previous errors +error[E0133]: call to unsafe function `S::f` is unsafe and requires unsafe function or block + --> $DIR/async-unsafe-fn-call-in-safe.rs:23:5 + | +LL | S::f(); + | ^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `f` is unsafe and requires unsafe function or block + --> $DIR/async-unsafe-fn-call-in-safe.rs:26:5 + | +LL | f(); + | ^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs index afe645ae8815..6c4f0a5accf9 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.rs @@ -11,4 +11,5 @@ fn main() { //[thir]~^^ call to unsafe function `foo` is unsafe and requires unsafe function or block foo(); //[mir]~^ ERROR call to unsafe function is unsafe and requires unsafe function or block + //[thir]~^^ ERROR call to unsafe function `foo` is unsafe and requires unsafe function or block } diff --git a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr index b313f06539ff..e6b8173eb051 100644 --- a/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr +++ b/tests/ui/consts/const-extern-fn/const-extern-fn-requires-unsafe.thir.stderr @@ -1,3 +1,11 @@ +error[E0133]: call to unsafe function `foo` is unsafe and requires unsafe function or block + --> $DIR/const-extern-fn-requires-unsafe.rs:12: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 `foo` is unsafe and requires unsafe function or block --> $DIR/const-extern-fn-requires-unsafe.rs:9:17 | @@ -6,6 +14,6 @@ LL | let a: [u8; foo()]; | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/inline-const/pat-unsafe-err.rs b/tests/ui/inline-const/pat-unsafe-err.rs index e290b438c514..6df281c6d945 100644 --- a/tests/ui/inline-const/pat-unsafe-err.rs +++ b/tests/ui/inline-const/pat-unsafe-err.rs @@ -1,11 +1,13 @@ -// ignore-test This is currently broken // revisions: mir thir +// [mir]ignore-test This is currently broken // [thir]compile-flags: -Z thir-unsafeck #![allow(incomplete_features)] #![feature(inline_const_pat)] -const unsafe fn require_unsafe() -> usize { 1 } +const unsafe fn require_unsafe() -> usize { + 1 +} fn main() { match () { @@ -14,4 +16,12 @@ fn main() { //~^ ERROR [E0133] } => (), } + + match 1 { + const { + require_unsafe() + //~^ ERROR [E0133] + }..=4 => (), + _ => (), + } } diff --git a/tests/ui/inline-const/pat-unsafe-err.thir.stderr b/tests/ui/inline-const/pat-unsafe-err.thir.stderr new file mode 100644 index 000000000000..48a2cb4c704d --- /dev/null +++ b/tests/ui/inline-const/pat-unsafe-err.thir.stderr @@ -0,0 +1,19 @@ +error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block + --> $DIR/pat-unsafe-err.rs:15:13 + | +LL | require_unsafe(); + | ^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `require_unsafe` is unsafe and requires unsafe function or block + --> $DIR/pat-unsafe-err.rs:22:13 + | +LL | require_unsafe() + | ^^^^^^^^^^^^^^^^ 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/tests/ui/inline-const/pat-unsafe.rs b/tests/ui/inline-const/pat-unsafe.rs index bcf7f6e01804..36f8632af673 100644 --- a/tests/ui/inline-const/pat-unsafe.rs +++ b/tests/ui/inline-const/pat-unsafe.rs @@ -1,13 +1,15 @@ -// ignore-test This is currently broken // check-pass // revisions: mir thir +// [mir]ignore-test This is currently broken // [thir]compile-flags: -Z thir-unsafeck #![allow(incomplete_features)] #![warn(unused_unsafe)] #![feature(inline_const_pat)] -const unsafe fn require_unsafe() -> usize { 1 } +const unsafe fn require_unsafe() -> usize { + 1 +} fn main() { unsafe { @@ -18,5 +20,14 @@ fn main() { //~^ WARNING unnecessary `unsafe` block } => (), } + + match 1 { + const { + unsafe {} + //~^ WARNING unnecessary `unsafe` block + require_unsafe() + }..=4 => (), + _ => (), + } } } diff --git a/tests/ui/inline-const/pat-unsafe.thir.stderr b/tests/ui/inline-const/pat-unsafe.thir.stderr new file mode 100644 index 000000000000..d62c87fc8f3c --- /dev/null +++ b/tests/ui/inline-const/pat-unsafe.thir.stderr @@ -0,0 +1,26 @@ +warning: unnecessary `unsafe` block + --> $DIR/pat-unsafe.rs:19:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/pat-unsafe.rs:7:9 + | +LL | #![warn(unused_unsafe)] + | ^^^^^^^^^^^^^ + +warning: unnecessary `unsafe` block + --> $DIR/pat-unsafe.rs:26:17 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | unsafe {} + | ^^^^^^ unnecessary `unsafe` block + +warning: 2 warnings emitted + diff --git a/tests/ui/pattern/non-structural-match-types.mir.stderr b/tests/ui/pattern/non-structural-match-types.mir.stderr new file mode 100644 index 000000000000..7a9e5b7e02ea --- /dev/null +++ b/tests/ui/pattern/non-structural-match-types.mir.stderr @@ -0,0 +1,14 @@ +error: `{closure@$DIR/non-structural-match-types.rs:12:17: 12:19}` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:12:9 + | +LL | const { || {} } => {} + | ^^^^^^^^^^^^^^^ + +error: `{async block@$DIR/non-structural-match-types.rs:15:17: 15:25}` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:15:9 + | +LL | const { async {} } => {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/pattern/non-structural-match-types.rs b/tests/ui/pattern/non-structural-match-types.rs index fc52ee3d013c..fb7779fa8088 100644 --- a/tests/ui/pattern/non-structural-match-types.rs +++ b/tests/ui/pattern/non-structural-match-types.rs @@ -1,4 +1,7 @@ // edition:2021 +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck + #![allow(incomplete_features)] #![allow(unreachable_code)] #![feature(const_async_blocks)] diff --git a/tests/ui/pattern/non-structural-match-types.stderr b/tests/ui/pattern/non-structural-match-types.stderr deleted file mode 100644 index f3e0665fef51..000000000000 --- a/tests/ui/pattern/non-structural-match-types.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: `{closure@$DIR/non-structural-match-types.rs:9:17: 9:19}` cannot be used in patterns - --> $DIR/non-structural-match-types.rs:9:9 - | -LL | const { || {} } => {} - | ^^^^^^^^^^^^^^^ - -error: `{async block@$DIR/non-structural-match-types.rs:12:17: 12:25}` cannot be used in patterns - --> $DIR/non-structural-match-types.rs:12:9 - | -LL | const { async {} } => {} - | ^^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - diff --git a/tests/ui/pattern/non-structural-match-types.thir.stderr b/tests/ui/pattern/non-structural-match-types.thir.stderr new file mode 100644 index 000000000000..7a9e5b7e02ea --- /dev/null +++ b/tests/ui/pattern/non-structural-match-types.thir.stderr @@ -0,0 +1,14 @@ +error: `{closure@$DIR/non-structural-match-types.rs:12:17: 12:19}` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:12:9 + | +LL | const { || {} } => {} + | ^^^^^^^^^^^^^^^ + +error: `{async block@$DIR/non-structural-match-types.rs:15:17: 15:25}` cannot be used in patterns + --> $DIR/non-structural-match-types.rs:15:9 + | +LL | const { async {} } => {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 8aea0e959088c0a879b0cd1682ec9db6c9914ee4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 9 Oct 2023 16:31:44 +0000 Subject: [PATCH 10/51] Address review comments Clean up code and add comments. Use InlineConstant to wrap range patterns. --- compiler/rustc_middle/src/thir.rs | 15 +++++- compiler/rustc_middle/src/thir/visit.rs | 2 +- .../src/build/matches/simplify.rs | 18 ++----- compiler/rustc_mir_build/src/build/mod.rs | 1 - .../rustc_mir_build/src/check_unsafety.rs | 27 +++------- .../rustc_mir_build/src/thir/pattern/mod.rs | 49 +++++++++++-------- compiler/rustc_mir_build/src/thir/print.rs | 8 +-- 7 files changed, 57 insertions(+), 63 deletions(-) diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 80d11c8b8f89..1c51c41d5a4d 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -765,8 +765,19 @@ pub enum PatKind<'tcx> { value: mir::Const<'tcx>, }, + /// Inline constant found while lowering a pattern. InlineConstant { - value: mir::UnevaluatedConst<'tcx>, + /// [LocalDefId] of the constant, we need this so that we have a + /// reference that can be used by unsafety checking to visit nested + /// unevaluated constants. + def: LocalDefId, + /// If the inline constant is used in a range pattern, this subpattern + /// represents the range (if both ends are inline constants, there will + /// be multiple InlineConstant wrappers). + /// + /// Otherwise, the actual pattern that the constant lowered to. As with + /// other constants, inline constants are matched structurally where + /// possible. subpattern: Box>, }, @@ -930,7 +941,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> { write!(f, "{subpattern}") } PatKind::Constant { value } => write!(f, "{value}"), - PatKind::InlineConstant { value: _, ref subpattern } => { + PatKind::InlineConstant { def: _, ref subpattern } => { write!(f, "{} (from inline const)", subpattern) } PatKind::Range(box PatRange { lo, hi, end }) => { diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs index 3da484e6f1b3..d03d92c3a4b8 100644 --- a/compiler/rustc_middle/src/thir/visit.rs +++ b/compiler/rustc_middle/src/thir/visit.rs @@ -233,7 +233,7 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<' } } Constant { value: _ } => {} - InlineConstant { value: _, subpattern } => visitor.visit_pat(subpattern), + InlineConstant { def: _, subpattern } => visitor.visit_pat(subpattern), Range(_) => {} Slice { prefix, slice, suffix } | Array { prefix, slice, suffix } => { for subpattern in prefix.iter() { diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index e55daa6ee5f1..32573b4d53af 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -204,7 +204,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Err(match_pair) } - PatKind::InlineConstant { subpattern: ref pattern, value: _ } => { + PatKind::InlineConstant { subpattern: ref pattern, def: _ } => { candidate.match_pairs.push(MatchPair::new(match_pair.place, pattern, self)); Ok(()) @@ -236,20 +236,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // pattern/_match.rs for another pertinent example of this pattern). // // Also, for performance, it's important to only do the second - // `try_eval_scalar_int` if necessary. - let lo = lo - .try_eval_scalar_int(self.tcx, self.param_env) - .unwrap() - .to_bits(sz) - .unwrap() - ^ bias; + // `try_to_bits` if necessary. + let lo = lo.try_to_bits(sz).unwrap() ^ bias; if lo <= min { - let hi = hi - .try_eval_scalar_int(self.tcx, self.param_env) - .unwrap() - .to_bits(sz) - .unwrap() - ^ bias; + let hi = hi.try_to_bits(sz).unwrap() ^ bias; if hi > max || hi == max && end == RangeEnd::Included { // Irrefutable pattern match. return Ok(()); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 3ef173c63e71..bd96ab453b80 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -67,7 +67,6 @@ fn mir_build<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { thir::BodyTy::Const(ty) => construct_const(tcx, def, thir, expr, ty), }; - tcx.ensure().check_match(def); // this must run before MIR dump, because // "not all control paths return a value" is reported here. // diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index f0b01e94587d..3e0af6c56ab6 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -3,7 +3,7 @@ use crate::errors::*; use rustc_middle::thir::visit::{self, Visitor}; use rustc_hir as hir; -use rustc_middle::mir::{BorrowKind, Const}; +use rustc_middle::mir::BorrowKind; use rustc_middle::thir::*; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt}; @@ -124,7 +124,8 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { /// Handle closures/generators/inline-consts, which is unsafecked with their parent body. fn visit_inner_body(&mut self, def: LocalDefId) { if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) { - let _ = self.tcx.ensure_with_value().mir_built(def); + // Runs all other queries that depend on THIR. + self.tcx.ensure_with_value().mir_built(def); let inner_thir = &inner_thir.steal(); let hir_context = self.tcx.hir().local_def_id_to_hir_id(def); let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self }; @@ -279,23 +280,8 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { visit::walk_pat(self, pat); self.inside_adt = old_inside_adt; } - PatKind::Range(range) => { - if let Const::Unevaluated(c, _) = range.lo { - if let hir::def::DefKind::InlineConst = self.tcx.def_kind(c.def) { - let def_id = c.def.expect_local(); - self.visit_inner_body(def_id); - } - } - if let Const::Unevaluated(c, _) = range.hi { - if let hir::def::DefKind::InlineConst = self.tcx.def_kind(c.def) { - let def_id = c.def.expect_local(); - self.visit_inner_body(def_id); - } - } - } - PatKind::InlineConstant { value, .. } => { - let def_id = value.def.expect_local(); - self.visit_inner_body(def_id); + PatKind::InlineConstant { def, .. } => { + self.visit_inner_body(*def); } _ => { visit::walk_pat(self, pat); @@ -808,7 +794,8 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { } let Ok((thir, expr)) = tcx.thir_body(def) else { return }; - let _ = tcx.ensure_with_value().mir_built(def); + // Runs all other queries that depend on THIR. + tcx.ensure_with_value().mir_built(def); let thir = &thir.steal(); // If `thir` is empty, a type error occurred, skip this body. if thir.exprs.is_empty() { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 0d066d9800b2..dd71ab1f8e55 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -27,6 +27,7 @@ use rustc_middle::ty::{ self, AdtDef, CanonicalUserTypeAnnotation, GenericArg, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt, UserType, }; +use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span, Symbol}; use rustc_target::abi::{FieldIdx, Integer}; @@ -88,19 +89,21 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { fn lower_pattern_range_endpoint( &mut self, expr: Option<&'tcx hir::Expr<'tcx>>, - ) -> Result<(Option>, Option>), ErrorGuaranteed> { + ) -> Result< + (Option>, Option>, Option), + ErrorGuaranteed, + > { match expr { - None => Ok((None, None)), + None => Ok((None, None, None)), Some(expr) => { - let (kind, ascr) = match self.lower_lit(expr) { - PatKind::InlineConstant { subpattern, value } => ( - PatKind::Constant { value: Const::Unevaluated(value, subpattern.ty) }, - None, - ), - PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { - (kind, Some(ascription)) + let (kind, ascr, inline_const) = match self.lower_lit(expr) { + PatKind::InlineConstant { subpattern, def } => { + (subpattern.kind, None, Some(def)) } - kind => (kind, None), + PatKind::AscribeUserType { ascription, subpattern: box Pat { kind, .. } } => { + (kind, Some(ascription), None) + } + kind => (kind, None, None), }; let value = if let PatKind::Constant { value } = kind { value @@ -110,7 +113,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { ); return Err(self.tcx.sess.delay_span_bug(expr.span, msg)); }; - Ok((Some(value), ascr)) + Ok((Some(value), ascr, inline_const)) } } } @@ -181,8 +184,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { return Err(self.tcx.sess.delay_span_bug(span, msg)); } - let (lo, lo_ascr) = self.lower_pattern_range_endpoint(lo_expr)?; - let (hi, hi_ascr) = self.lower_pattern_range_endpoint(hi_expr)?; + let (lo, lo_ascr, lo_inline) = self.lower_pattern_range_endpoint(lo_expr)?; + let (hi, hi_ascr, hi_inline) = self.lower_pattern_range_endpoint(hi_expr)?; let lo = lo.unwrap_or_else(|| { // Unwrap is ok because the type is known to be numeric. @@ -241,6 +244,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; } } + for inline_const in [lo_inline, hi_inline] { + if let Some(def) = inline_const { + kind = + PatKind::InlineConstant { def, subpattern: Box::new(Pat { span, ty, kind }) }; + } + } Ok(kind) } @@ -603,11 +612,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // const eval path below. // FIXME: investigate the performance impact of removing this. let lit_input = match expr.kind { - hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), - hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind { - hir::ExprKind::Lit(ref lit) => { - Some(LitToConstInput { lit: &lit.node, ty, neg: true }) - } + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }), + hir::ExprKind::Unary(hir::UnOp::Neg, expr) => match expr.kind { + hir::ExprKind::Lit(lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: true }), _ => None, }, _ => None, @@ -643,7 +650,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { span, None, ); - PatKind::InlineConstant { subpattern, value: uneval } + PatKind::InlineConstant { subpattern, def: def_id } } else { // If that fails, convert it to an opaque constant pattern. match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) { @@ -826,8 +833,8 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { PatKind::Deref { subpattern: subpattern.fold_with(folder) } } PatKind::Constant { value } => PatKind::Constant { value }, - PatKind::InlineConstant { value, subpattern: ref pattern } => { - PatKind::InlineConstant { value, subpattern: pattern.fold_with(folder) } + PatKind::InlineConstant { def, subpattern: ref pattern } => { + PatKind::InlineConstant { def, subpattern: pattern.fold_with(folder) } } PatKind::Range(ref range) => PatKind::Range(range.clone()), PatKind::Slice { ref prefix, ref slice, ref suffix } => PatKind::Slice { diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 519622d450a8..c3b2309b7cda 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -692,7 +692,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { } PatKind::Deref { subpattern } => { print_indented!(self, "Deref { ", depth_lvl + 1); - print_indented!(self, "subpattern: ", depth_lvl + 2); + print_indented!(self, "subpattern:", depth_lvl + 2); self.print_pat(subpattern, depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } @@ -701,10 +701,10 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("value: {:?}", value), depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } - PatKind::InlineConstant { value, subpattern } => { + PatKind::InlineConstant { def, subpattern } => { print_indented!(self, "InlineConstant {", depth_lvl + 1); - print_indented!(self, format!("value: {:?}", value), depth_lvl + 2); - print_indented!(self, "subpattern: ", depth_lvl + 2); + print_indented!(self, format!("def: {:?}", def), depth_lvl + 2); + print_indented!(self, "subpattern:", depth_lvl + 2); self.print_pat(subpattern, depth_lvl + 2); print_indented!(self, "}", depth_lvl + 1); } From 31d101093c134e69a31ba58893e56647a5831299 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 12 Sep 2023 16:44:53 +0000 Subject: [PATCH 11/51] Generate ValTrees in DataflowConstProp. --- .../src/dataflow_const_prop.rs | 99 ++++++++++++++++++- .../const_debuginfo.main.ConstDebugInfo.diff | 5 +- ...ed.main.DataflowConstProp.panic-abort.diff | 4 +- ...d.main.DataflowConstProp.panic-unwind.diff | 4 +- .../enum.simple.DataflowConstProp.32bit.diff | 3 +- .../enum.simple.DataflowConstProp.64bit.diff | 3 +- .../enum.statics.DataflowConstProp.32bit.diff | 3 +- .../enum.statics.DataflowConstProp.64bit.diff | 3 +- ...ow.main.DataflowConstProp.panic-abort.diff | 2 +- ...w.main.DataflowConstProp.panic-unwind.diff | 2 +- ...pr_transparent.main.DataflowConstProp.diff | 5 +- .../struct.main.DataflowConstProp.32bit.diff | 59 ++++++++--- .../struct.main.DataflowConstProp.64bit.diff | 59 ++++++++--- tests/mir-opt/dataflow-const-prop/struct.rs | 2 + .../tuple.main.DataflowConstProp.diff | 29 +++++- tests/mir-opt/dataflow-const-prop/tuple.rs | 2 + 16 files changed, 234 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 85a0be8a44c4..762f57ad29e1 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -557,11 +557,102 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> { state: &State>, map: &Map, ) -> Option> { - let FlatSet::Elem(Scalar::Int(value)) = state.get(place.as_ref(), &map) else { - return None; - }; let ty = place.ty(self.local_decls, self.patch.tcx).ty; - Some(Const::Val(ConstValue::Scalar(value.into()), ty)) + let place = map.find(place.as_ref())?; + if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) { + Some(Const::Val(ConstValue::Scalar(value.into()), ty)) + } else { + let valtree = self.try_make_valtree(place, ty, state, map)?; + let constant = ty::Const::new_value(self.patch.tcx, valtree, ty); + Some(Const::Ty(constant)) + } + } + + fn try_make_valtree( + &self, + place: PlaceIndex, + ty: Ty<'tcx>, + state: &State>, + map: &Map, + ) -> Option> { + let tcx = self.patch.tcx; + match ty.kind() { + // ZSTs. + ty::FnDef(..) => Some(ty::ValTree::zst()), + + // Scalars. + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { + if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) { + Some(ty::ValTree::Leaf(value)) + } else { + None + } + } + + // Unsupported for now. + ty::Array(_, _) => None, + + ty::Tuple(elem_tys) => { + let branches = elem_tys + .iter() + .enumerate() + .map(|(i, ty)| { + let field = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i)))?; + self.try_make_valtree(field, ty, state, map) + }) + .collect::>>()?; + Some(ty::ValTree::Branch(tcx.arena.alloc_from_iter(branches.into_iter()))) + } + + ty::Adt(def, args) => { + if def.is_union() { + return None; + } + + let (variant_idx, variant_def, variant_place) = if def.is_enum() { + let discr = map.apply(place, TrackElem::Discriminant)?; + let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else { + return None; + }; + let discr_bits = discr.assert_bits(discr.size()); + let (variant, _) = + def.discriminants(tcx).find(|(_, var)| discr_bits == var.val)?; + let variant_place = map.apply(place, TrackElem::Variant(variant))?; + let variant_int = ty::ValTree::Leaf(variant.as_u32().into()); + (Some(variant_int), def.variant(variant), variant_place) + } else { + (None, def.non_enum_variant(), place) + }; + + let branches = variant_def + .fields + .iter_enumerated() + .map(|(i, field)| { + let ty = field.ty(tcx, args); + let field = map.apply(variant_place, TrackElem::Field(i))?; + self.try_make_valtree(field, ty, state, map) + }) + .collect::>>()?; + Some(ty::ValTree::Branch( + tcx.arena.alloc_from_iter(variant_idx.into_iter().chain(branches)), + )) + } + + // Do not attempt to support indirection in constants. + ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_) => None, + + ty::Never + | ty::Foreign(..) + | ty::Alias(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Closure(..) + | ty::Coroutine(..) + | ty::Dynamic(..) => None, + + ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) => bug!(), + } } } diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index ed47baa67dab..0934ee346174 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -41,7 +41,8 @@ + debug ((f: (bool, bool, u32)).2: u32) => const 123_u32; let _10: std::option::Option; scope 7 { - debug o => _10; +- debug o => _10; ++ debug o => const Option::::Some(99); let _17: u32; let _18: u32; scope 8 { @@ -81,7 +82,7 @@ _15 = const false; _16 = const 123_u32; StorageLive(_10); - _10 = Option::::Some(const 99_u16); + _10 = const Option::::Some(99); _17 = const 32_u32; _18 = const 32_u32; StorageLive(_11); diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff index 2f1a70f32d03..111be450c799 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff @@ -43,7 +43,7 @@ - _6 = CheckedAdd(_4, _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind unreachable]; + _5 = const 2_i32; -+ _6 = CheckedAdd(const 1_i32, const 2_i32); ++ _6 = const (3, false); + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind unreachable]; } @@ -60,7 +60,7 @@ - _10 = CheckedAdd(_9, const 1_i32); - assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind unreachable]; + _9 = const i32::MAX; -+ _10 = CheckedAdd(const i32::MAX, const 1_i32); ++ _10 = const (i32::MIN, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> [success: bb2, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff index 0d8a9aca3d8c..733100a889b6 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff @@ -43,7 +43,7 @@ - _6 = CheckedAdd(_4, _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue]; + _5 = const 2_i32; -+ _6 = CheckedAdd(const 1_i32, const 2_i32); ++ _6 = const (3, false); + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind continue]; } @@ -60,7 +60,7 @@ - _10 = CheckedAdd(_9, const 1_i32); - assert(!move (_10.1: bool), "attempt to compute `{} + {}`, which would overflow", move _9, const 1_i32) -> [success: bb2, unwind continue]; + _9 = const i32::MAX; -+ _10 = CheckedAdd(const i32::MAX, const 1_i32); ++ _10 = const (i32::MIN, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const i32::MAX, const 1_i32) -> [success: bb2, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff index 3946e7c7d96c..1e7fdd3b1a0b 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff @@ -23,7 +23,8 @@ bb0: { StorageLive(_1); - _1 = E::V1(const 0_i32); +- _1 = E::V1(const 0_i32); ++ _1 = const E::V1(0); StorageLive(_2); - _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff index 3946e7c7d96c..1e7fdd3b1a0b 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff @@ -23,7 +23,8 @@ bb0: { StorageLive(_1); - _1 = E::V1(const 0_i32); +- _1 = E::V1(const 0_i32); ++ _1 = const E::V1(0); StorageLive(_2); - _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index 1348b2793308..c5c95bc6cd18 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -44,7 +44,8 @@ StorageLive(_1); StorageLive(_2); _2 = const {ALLOC1: &E}; - _1 = (*_2); +- _1 = (*_2); ++ _1 = const E::V1(0); StorageDead(_2); StorageLive(_3); - _4 = discriminant(_1); diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index 66929e886d3c..48897b93e46c 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -44,7 +44,8 @@ StorageLive(_1); StorageLive(_2); _2 = const {ALLOC1: &E}; - _1 = (*_2); +- _1 = (*_2); ++ _1 = const E::V1(0); StorageDead(_2); StorageLive(_3); - _4 = discriminant(_1); diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff index 87bb1454c962..b5f7f2a472c4 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff @@ -23,7 +23,7 @@ StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; -+ _4 = CheckedAdd(const u8::MAX, const 1_u8); ++ _4 = const (0, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable]; } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff index b2f13640a4c0..e2e799650aa4 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff @@ -23,7 +23,7 @@ StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; -+ _4 = CheckedAdd(const u8::MAX, const 1_u8); ++ _4 = const (0, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue]; } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff index 4b1a8d932c65..4530d8b627bd 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff @@ -17,7 +17,8 @@ bb0: { StorageLive(_1); - _1 = I32(const 0_i32); +- _1 = I32(const 0_i32); ++ _1 = const I32(0); StorageLive(_2); StorageLive(_3); StorageLive(_4); @@ -31,7 +32,7 @@ StorageDead(_5); StorageDead(_4); - _2 = I32(move _3); -+ _2 = I32(const 0_i32); ++ _2 = const I32(0); StorageDead(_3); _0 = const (); StorageDead(_2); diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index e80f31ca9348..8d277459d3bd 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -9,11 +9,15 @@ let mut _6: i32; let mut _11: BigStruct; let mut _16: &&BigStruct; - let mut _17: &BigStruct; - let mut _18: &BigStruct; - let mut _19: &BigStruct; - let mut _20: &BigStruct; - let mut _21: &BigStruct; + let mut _18: S; + let mut _19: u8; + let mut _20: f32; + let mut _21: S; + let mut _22: &BigStruct; + let mut _23: &BigStruct; + let mut _24: &BigStruct; + let mut _25: &BigStruct; + let mut _26: &BigStruct; scope 1 { debug s => _1; let _2: i32; @@ -40,6 +44,10 @@ debug b => _13; debug c => _14; debug d => _15; + let _17: BigStruct; + scope 6 { + debug bs => _17; + } } } } @@ -48,7 +56,8 @@ bb0: { StorageLive(_1); - _1 = S(const 1_i32); +- _1 = S(const 1_i32); ++ _1 = const S(1); StorageLive(_2); StorageLive(_3); - _3 = (_1.0: i32); @@ -85,25 +94,45 @@ StorageDead(_11); StorageLive(_16); _16 = const {ALLOC1: &&BigStruct}; - _17 = deref_copy (*_16); + _22 = deref_copy (*_16); StorageLive(_12); - _18 = deref_copy (*_16); -- _12 = ((*_18).0: S); + _23 = deref_copy (*_16); +- _12 = ((*_23).0: S); + _12 = const S(1_i32); StorageLive(_13); - _19 = deref_copy (*_16); -- _13 = ((*_19).1: u8); + _24 = deref_copy (*_16); +- _13 = ((*_24).1: u8); + _13 = const 5_u8; StorageLive(_14); - _20 = deref_copy (*_16); -- _14 = ((*_20).2: f32); + _25 = deref_copy (*_16); +- _14 = ((*_25).2: f32); + _14 = const 7f32; StorageLive(_15); - _21 = deref_copy (*_16); -- _15 = ((*_21).3: S); + _26 = deref_copy (*_16); +- _15 = ((*_26).3: S); + _15 = const S(13_i32); StorageDead(_16); + StorageLive(_17); + StorageLive(_18); +- _18 = _12; ++ _18 = const S(1_i32); + StorageLive(_19); +- _19 = _13; ++ _19 = const 5_u8; + StorageLive(_20); +- _20 = _14; ++ _20 = const 7f32; + StorageLive(_21); +- _21 = _15; +- _17 = BigStruct(move _18, move _19, move _20, move _21); ++ _21 = const S(13_i32); ++ _17 = const BigStruct(S(1), 5, 7f32, S(13)); + StorageDead(_21); + StorageDead(_20); + StorageDead(_19); + StorageDead(_18); _0 = const (); + StorageDead(_17); StorageDead(_15); StorageDead(_14); StorageDead(_13); diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index de9cf1971997..fca94beb9ab5 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -9,11 +9,15 @@ let mut _6: i32; let mut _11: BigStruct; let mut _16: &&BigStruct; - let mut _17: &BigStruct; - let mut _18: &BigStruct; - let mut _19: &BigStruct; - let mut _20: &BigStruct; - let mut _21: &BigStruct; + let mut _18: S; + let mut _19: u8; + let mut _20: f32; + let mut _21: S; + let mut _22: &BigStruct; + let mut _23: &BigStruct; + let mut _24: &BigStruct; + let mut _25: &BigStruct; + let mut _26: &BigStruct; scope 1 { debug s => _1; let _2: i32; @@ -40,6 +44,10 @@ debug b => _13; debug c => _14; debug d => _15; + let _17: BigStruct; + scope 6 { + debug bs => _17; + } } } } @@ -48,7 +56,8 @@ bb0: { StorageLive(_1); - _1 = S(const 1_i32); +- _1 = S(const 1_i32); ++ _1 = const S(1); StorageLive(_2); StorageLive(_3); - _3 = (_1.0: i32); @@ -85,25 +94,45 @@ StorageDead(_11); StorageLive(_16); _16 = const {ALLOC1: &&BigStruct}; - _17 = deref_copy (*_16); + _22 = deref_copy (*_16); StorageLive(_12); - _18 = deref_copy (*_16); -- _12 = ((*_18).0: S); + _23 = deref_copy (*_16); +- _12 = ((*_23).0: S); + _12 = const S(1_i32); StorageLive(_13); - _19 = deref_copy (*_16); -- _13 = ((*_19).1: u8); + _24 = deref_copy (*_16); +- _13 = ((*_24).1: u8); + _13 = const 5_u8; StorageLive(_14); - _20 = deref_copy (*_16); -- _14 = ((*_20).2: f32); + _25 = deref_copy (*_16); +- _14 = ((*_25).2: f32); + _14 = const 7f32; StorageLive(_15); - _21 = deref_copy (*_16); -- _15 = ((*_21).3: S); + _26 = deref_copy (*_16); +- _15 = ((*_26).3: S); + _15 = const S(13_i32); StorageDead(_16); + StorageLive(_17); + StorageLive(_18); +- _18 = _12; ++ _18 = const S(1_i32); + StorageLive(_19); +- _19 = _13; ++ _19 = const 5_u8; + StorageLive(_20); +- _20 = _14; ++ _20 = const 7f32; + StorageLive(_21); +- _21 = _15; +- _17 = BigStruct(move _18, move _19, move _20, move _21); ++ _21 = const S(13_i32); ++ _17 = const BigStruct(S(1), 5, 7f32, S(13)); + StorageDead(_21); + StorageDead(_20); + StorageDead(_19); + StorageDead(_18); _0 = const (); + StorageDead(_17); StorageDead(_15); StorageDead(_14); StorageDead(_13); diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 7b0646a53564..5c6edeb3866e 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -20,4 +20,6 @@ fn main() { static STAT: &BigStruct = &BigStruct(S(1), 5, 7., S(13)); let BigStruct(a, b, c, d) = *STAT; + + let bs = BigStruct(a, b, c, d); } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff index 5e385d21ec60..21c9b9d1eb96 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff @@ -11,6 +11,9 @@ let mut _8: i32; let mut _9: i32; let mut _10: i32; + let mut _12: i32; + let mut _13: (i32, i32); + let mut _14: i32; scope 1 { debug a => _1; let _2: i32; @@ -19,13 +22,18 @@ let _6: i32; scope 3 { debug c => _6; + let _11: (i32, (i32, i32), i32); + scope 4 { + debug d => _11; + } } } } bb0: { StorageLive(_1); - _1 = (const 1_i32, const 2_i32); +- _1 = (const 1_i32, const 2_i32); ++ _1 = const (1, 2); StorageLive(_2); StorageLive(_3); StorageLive(_4); @@ -41,7 +49,8 @@ - _2 = Add(move _3, const 3_i32); + _2 = const 6_i32; StorageDead(_3); - _1 = (const 2_i32, const 3_i32); +- _1 = (const 2_i32, const 3_i32); ++ _1 = const (2, 3); StorageLive(_6); StorageLive(_7); StorageLive(_8); @@ -61,7 +70,23 @@ + _6 = const 11_i32; StorageDead(_10); StorageDead(_7); + StorageLive(_11); + StorageLive(_12); +- _12 = _2; ++ _12 = const 6_i32; + StorageLive(_13); +- _13 = _1; ++ _13 = const (2, 3); + StorageLive(_14); +- _14 = _6; +- _11 = (move _12, move _13, move _14); ++ _14 = const 11_i32; ++ _11 = const (6, (2, 3), 11); + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); _0 = const (); + StorageDead(_11); StorageDead(_6); StorageDead(_2); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index c63ce8b140f8..7691bc8d7c50 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -7,4 +7,6 @@ fn main() { let b = a.0 + a.1 + 3; a = (2, 3); let c = a.0 + a.1 + b; + + let d = (b, a, c); } From 8c1b039d482149f643a88c6d7af526b18f56dd8f Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 17 Sep 2023 09:35:06 +0000 Subject: [PATCH 12/51] Use a ConstValue instead. --- .../src/dataflow_const_prop.rs | 255 +++++++++++------- .../const_debuginfo.main.ConstDebugInfo.diff | 8 +- ...ed.main.DataflowConstProp.panic-abort.diff | 10 +- ...d.main.DataflowConstProp.panic-unwind.diff | 10 +- tests/mir-opt/dataflow-const-prop/checked.rs | 2 +- .../enum.simple.DataflowConstProp.32bit.diff | 6 +- .../enum.simple.DataflowConstProp.64bit.diff | 6 +- .../enum.statics.DataflowConstProp.32bit.diff | 6 +- .../enum.statics.DataflowConstProp.64bit.diff | 6 +- ...ow.main.DataflowConstProp.panic-abort.diff | 6 +- ...w.main.DataflowConstProp.panic-unwind.diff | 6 +- ...pr_transparent.main.DataflowConstProp.diff | 12 +- .../struct.main.DataflowConstProp.32bit.diff | 243 +++++++++++------ .../struct.main.DataflowConstProp.64bit.diff | 243 +++++++++++------ tests/mir-opt/dataflow-const-prop/struct.rs | 25 +- .../mir-opt/dataflow-const-prop/transmute.rs | 4 +- ...on_as_integer.DataflowConstProp.32bit.diff | 6 +- ...on_as_integer.DataflowConstProp.64bit.diff | 6 +- ...chable_direct.DataflowConstProp.32bit.diff | 6 +- ...chable_direct.DataflowConstProp.64bit.diff | 6 +- ...> tuple.main.DataflowConstProp.32bit.diff} | 24 +- .../tuple.main.DataflowConstProp.64bit.diff | 112 ++++++++ tests/mir-opt/dataflow-const-prop/tuple.rs | 1 + 23 files changed, 726 insertions(+), 283 deletions(-) rename tests/mir-opt/dataflow-const-prop/{tuple.main.DataflowConstProp.diff => tuple.main.DataflowConstProp.32bit.diff} (80%) create mode 100644 tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 762f57ad29e1..2c29978173ff 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -2,13 +2,13 @@ //! //! Currently, this pass only propagates scalar values. -use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, Projectable}; +use rustc_const_eval::interpret::{ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{AllocId, ConstAllocation, InterpResult, Scalar}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::layout::TyAndLayout; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::value_analysis::{ Map, PlaceIndex, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace, @@ -16,8 +16,9 @@ use rustc_mir_dataflow::value_analysis::{ use rustc_mir_dataflow::{lattice::FlatSet, Analysis, Results, ResultsVisitor}; use rustc_span::def_id::DefId; use rustc_span::DUMMY_SP; -use rustc_target::abi::{FieldIdx, VariantIdx}; +use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT}; +use crate::const_prop::throw_machine_stop_str; use crate::MirPass; // These constants are somewhat random guesses and have not been optimized. @@ -553,107 +554,151 @@ impl<'tcx, 'locals> Collector<'tcx, 'locals> { fn try_make_constant( &self, + ecx: &mut InterpCx<'tcx, 'tcx, DummyMachine>, place: Place<'tcx>, state: &State>, map: &Map, ) -> Option> { let ty = place.ty(self.local_decls, self.patch.tcx).ty; + let layout = ecx.layout_of(ty).ok()?; + + if layout.is_zst() { + return Some(Const::zero_sized(ty)); + } + + if layout.is_unsized() { + return None; + } + let place = map.find(place.as_ref())?; - if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) { - Some(Const::Val(ConstValue::Scalar(value.into()), ty)) - } else { - let valtree = self.try_make_valtree(place, ty, state, map)?; - let constant = ty::Const::new_value(self.patch.tcx, valtree, ty); - Some(Const::Ty(constant)) + if layout.abi.is_scalar() + && let Some(value) = propagatable_scalar(place, state, map) + { + return Some(Const::Val(ConstValue::Scalar(value), ty)); } + + if matches!(layout.abi, Abi::Scalar(..) | Abi::ScalarPair(..)) { + let alloc_id = ecx + .intern_with_temp_alloc(layout, |ecx, dest| { + try_write_constant(ecx, dest, place, ty, state, map) + }) + .ok()?; + return Some(Const::Val(ConstValue::Indirect { alloc_id, offset: Size::ZERO }, ty)); + } + + None + } +} + +fn propagatable_scalar( + place: PlaceIndex, + state: &State>, + map: &Map, +) -> Option { + if let FlatSet::Elem(value) = state.get_idx(place, map) && value.try_to_int().is_ok() { + // Do not attempt to propagate pointers, as we may fail to preserve their identity. + Some(value) + } else { + None + } +} + +#[instrument(level = "trace", skip(ecx, state, map))] +fn try_write_constant<'tcx>( + ecx: &mut InterpCx<'_, 'tcx, DummyMachine>, + dest: &PlaceTy<'tcx>, + place: PlaceIndex, + ty: Ty<'tcx>, + state: &State>, + map: &Map, +) -> InterpResult<'tcx> { + let layout = ecx.layout_of(ty)?; + + // Fast path for ZSTs. + if layout.is_zst() { + return Ok(()); } - fn try_make_valtree( - &self, - place: PlaceIndex, - ty: Ty<'tcx>, - state: &State>, - map: &Map, - ) -> Option> { - let tcx = self.patch.tcx; - match ty.kind() { - // ZSTs. - ty::FnDef(..) => Some(ty::ValTree::zst()), + // Fast path for scalars. + if layout.abi.is_scalar() + && let Some(value) = propagatable_scalar(place, state, map) + { + return ecx.write_immediate(Immediate::Scalar(value), dest); + } - // Scalars. - ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => { - if let FlatSet::Elem(Scalar::Int(value)) = state.get_idx(place, map) { - Some(ty::ValTree::Leaf(value)) - } else { - None - } - } + match ty.kind() { + // ZSTs. Nothing to do. + ty::FnDef(..) => {} - // Unsupported for now. - ty::Array(_, _) => None, + // Those are scalars, must be handled above. + ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Char => throw_machine_stop_str!("primitive type with provenance"), - ty::Tuple(elem_tys) => { - let branches = elem_tys - .iter() - .enumerate() - .map(|(i, ty)| { - let field = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i)))?; - self.try_make_valtree(field, ty, state, map) - }) - .collect::>>()?; - Some(ty::ValTree::Branch(tcx.arena.alloc_from_iter(branches.into_iter()))) - } - - ty::Adt(def, args) => { - if def.is_union() { - return None; - } - - let (variant_idx, variant_def, variant_place) = if def.is_enum() { - let discr = map.apply(place, TrackElem::Discriminant)?; - let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else { - return None; - }; - let discr_bits = discr.assert_bits(discr.size()); - let (variant, _) = - def.discriminants(tcx).find(|(_, var)| discr_bits == var.val)?; - let variant_place = map.apply(place, TrackElem::Variant(variant))?; - let variant_int = ty::ValTree::Leaf(variant.as_u32().into()); - (Some(variant_int), def.variant(variant), variant_place) - } else { - (None, def.non_enum_variant(), place) + ty::Tuple(elem_tys) => { + for (i, elem) in elem_tys.iter().enumerate() { + let Some(field) = map.apply(place, TrackElem::Field(FieldIdx::from_usize(i))) else { + throw_machine_stop_str!("missing field in tuple") }; + let field_dest = ecx.project_field(dest, i)?; + try_write_constant(ecx, &field_dest, field, elem, state, map)?; + } + } - let branches = variant_def - .fields - .iter_enumerated() - .map(|(i, field)| { - let ty = field.ty(tcx, args); - let field = map.apply(variant_place, TrackElem::Field(i))?; - self.try_make_valtree(field, ty, state, map) - }) - .collect::>>()?; - Some(ty::ValTree::Branch( - tcx.arena.alloc_from_iter(variant_idx.into_iter().chain(branches)), - )) + ty::Adt(def, args) => { + if def.is_union() { + throw_machine_stop_str!("cannot propagate unions") } - // Do not attempt to support indirection in constants. - ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_) => None, + let (variant_idx, variant_def, variant_place, variant_dest) = if def.is_enum() { + let Some(discr) = map.apply(place, TrackElem::Discriminant) else { + throw_machine_stop_str!("missing discriminant for enum") + }; + let FlatSet::Elem(Scalar::Int(discr)) = state.get_idx(discr, map) else { + throw_machine_stop_str!("discriminant with provenance") + }; + let discr_bits = discr.assert_bits(discr.size()); + let Some((variant, _)) = def.discriminants(*ecx.tcx).find(|(_, var)| discr_bits == var.val) else { + throw_machine_stop_str!("illegal discriminant for enum") + }; + let Some(variant_place) = map.apply(place, TrackElem::Variant(variant)) else { + throw_machine_stop_str!("missing variant for enum") + }; + let variant_dest = ecx.project_downcast(dest, variant)?; + (variant, def.variant(variant), variant_place, variant_dest) + } else { + (FIRST_VARIANT, def.non_enum_variant(), place, dest.clone()) + }; - ty::Never - | ty::Foreign(..) - | ty::Alias(..) - | ty::Param(_) - | ty::Bound(..) - | ty::Placeholder(..) - | ty::Closure(..) - | ty::Coroutine(..) - | ty::Dynamic(..) => None, - - ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) => bug!(), + for (i, field) in variant_def.fields.iter_enumerated() { + let ty = field.ty(*ecx.tcx, args); + let Some(field) = map.apply(variant_place, TrackElem::Field(i)) else { + throw_machine_stop_str!("missing field in ADT") + }; + let field_dest = ecx.project_field(&variant_dest, i.as_usize())?; + try_write_constant(ecx, &field_dest, field, ty, state, map)?; + } + ecx.write_discriminant(variant_idx, dest)?; } + + // Unsupported for now. + ty::Array(_, _) + + // Do not attempt to support indirection in constants. + | ty::Ref(..) | ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_) + + | ty::Never + | ty::Foreign(..) + | ty::Alias(..) + | ty::Param(_) + | ty::Bound(..) + | ty::Placeholder(..) + | ty::Closure(..) + | ty::Coroutine(..) + | ty::Dynamic(..) => throw_machine_stop_str!("unsupported type"), + + ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) => bug!(), } + + Ok(()) } impl<'mir, 'tcx> @@ -671,8 +716,13 @@ impl<'mir, 'tcx> ) { match &statement.kind { StatementKind::Assign(box (_, rvalue)) => { - OperandCollector { state, visitor: self, map: &results.analysis.0.map } - .visit_rvalue(rvalue, location); + OperandCollector { + state, + visitor: self, + ecx: &mut results.analysis.0.ecx, + map: &results.analysis.0.map, + } + .visit_rvalue(rvalue, location); } _ => (), } @@ -690,7 +740,12 @@ impl<'mir, 'tcx> // Don't overwrite the assignment if it already uses a constant (to keep the span). } StatementKind::Assign(box (place, _)) => { - if let Some(value) = self.try_make_constant(place, state, &results.analysis.0.map) { + if let Some(value) = self.try_make_constant( + &mut results.analysis.0.ecx, + place, + state, + &results.analysis.0.map, + ) { self.patch.assignments.insert(location, value); } } @@ -705,8 +760,13 @@ impl<'mir, 'tcx> terminator: &'mir Terminator<'tcx>, location: Location, ) { - OperandCollector { state, visitor: self, map: &results.analysis.0.map } - .visit_terminator(terminator, location); + OperandCollector { + state, + visitor: self, + ecx: &mut results.analysis.0.ecx, + map: &results.analysis.0.map, + } + .visit_terminator(terminator, location); } } @@ -761,6 +821,7 @@ impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> { struct OperandCollector<'tcx, 'map, 'locals, 'a> { state: &'a State>, visitor: &'a mut Collector<'tcx, 'locals>, + ecx: &'map mut InterpCx<'tcx, 'tcx, DummyMachine>, map: &'map Map, } @@ -773,7 +834,7 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> { location: Location, ) { if let PlaceElem::Index(local) = elem - && let Some(value) = self.visitor.try_make_constant(local.into(), self.state, self.map) + && let Some(value) = self.visitor.try_make_constant(self.ecx, local.into(), self.state, self.map) { self.visitor.patch.before_effect.insert((location, local.into()), value); } @@ -781,7 +842,9 @@ impl<'tcx> Visitor<'tcx> for OperandCollector<'tcx, '_, '_, '_> { fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) { if let Some(place) = operand.place() { - if let Some(value) = self.visitor.try_make_constant(place, self.state, self.map) { + if let Some(value) = + self.visitor.try_make_constant(self.ecx, place, self.state, self.map) + { self.visitor.patch.before_effect.insert((location, place), value); } else if !place.projection.is_empty() { // Try to propagate into `Index` projections. @@ -804,7 +867,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm } fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>, _layout: TyAndLayout<'tcx>) -> bool { - unimplemented!() + false } fn before_access_global( @@ -816,13 +879,13 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm is_write: bool, ) -> InterpResult<'tcx> { if is_write { - crate::const_prop::throw_machine_stop_str!("can't write to global"); + throw_machine_stop_str!("can't write to global"); } // If the static allocation is mutable, then we can't const prop it as its content // might be different at runtime. if alloc.inner().mutability.is_mut() { - crate::const_prop::throw_machine_stop_str!("can't access mutable globals in ConstProp"); + throw_machine_stop_str!("can't access mutable globals in ConstProp"); } Ok(()) @@ -872,7 +935,7 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm _left: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, _right: &rustc_const_eval::interpret::ImmTy<'tcx, Self::Provenance>, ) -> interpret::InterpResult<'tcx, (ImmTy<'tcx, Self::Provenance>, bool)> { - crate::const_prop::throw_machine_stop_str!("can't do pointer arithmetic"); + throw_machine_stop_str!("can't do pointer arithmetic"); } fn expose_ptr( diff --git a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff index 0934ee346174..313e5dddbbba 100644 --- a/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff +++ b/tests/mir-opt/const_debuginfo.main.ConstDebugInfo.diff @@ -42,7 +42,7 @@ let _10: std::option::Option; scope 7 { - debug o => _10; -+ debug o => const Option::::Some(99); ++ debug o => const Option::::Some(99_u16); let _17: u32; let _18: u32; scope 8 { @@ -82,7 +82,7 @@ _15 = const false; _16 = const 123_u32; StorageLive(_10); - _10 = const Option::::Some(99); + _10 = const Option::::Some(99_u16); _17 = const 32_u32; _18 = const 32_u32; StorageLive(_11); @@ -98,3 +98,7 @@ } } + ALLOC0 (size: 4, align: 2) { + 01 00 63 00 │ ..c. + } + diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff index 111be450c799..4569ffe483b3 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff @@ -43,7 +43,7 @@ - _6 = CheckedAdd(_4, _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind unreachable]; + _5 = const 2_i32; -+ _6 = const (3, false); ++ _6 = const (3_i32, false); + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind unreachable]; } @@ -76,5 +76,13 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 80 01 __ __ __ │ .....░░░ ++ } ++ ++ ALLOC1 (size: 8, align: 4) { ++ 03 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff index 733100a889b6..aa7e404eb9f5 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff @@ -43,7 +43,7 @@ - _6 = CheckedAdd(_4, _5); - assert(!move (_6.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, move _5) -> [success: bb1, unwind continue]; + _5 = const 2_i32; -+ _6 = const (3, false); ++ _6 = const (3_i32, false); + assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 1_i32, const 2_i32) -> [success: bb1, unwind continue]; } @@ -76,5 +76,13 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 80 01 __ __ __ │ .....░░░ ++ } ++ ++ ALLOC1 (size: 8, align: 4) { ++ 03 00 00 00 00 __ __ __ │ .....░░░ } diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs index b41ac0b3d2af..f7fac8890a05 100644 --- a/tests/mir-opt/dataflow-const-prop/checked.rs +++ b/tests/mir-opt/dataflow-const-prop/checked.rs @@ -1,7 +1,7 @@ // skip-filecheck -// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // unit-test: DataflowConstProp // compile-flags: -Coverflow-checks=on +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR checked.main.DataflowConstProp.diff #[allow(arithmetic_overflow)] diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff index 1e7fdd3b1a0b..798b0c041b4e 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.32bit.diff @@ -24,7 +24,7 @@ bb0: { StorageLive(_1); - _1 = E::V1(const 0_i32); -+ _1 = const E::V1(0); ++ _1 = const E::V1(0_i32); StorageLive(_2); - _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; @@ -60,5 +60,9 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff index 1e7fdd3b1a0b..798b0c041b4e 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.simple.DataflowConstProp.64bit.diff @@ -24,7 +24,7 @@ bb0: { StorageLive(_1); - _1 = E::V1(const 0_i32); -+ _1 = const E::V1(0); ++ _1 = const E::V1(0_i32); StorageLive(_2); - _3 = discriminant(_1); - switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; @@ -60,5 +60,9 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 00 00 00 00 00 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff index c5c95bc6cd18..d502b1982399 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.32bit.diff @@ -45,7 +45,7 @@ StorageLive(_2); _2 = const {ALLOC1: &E}; - _1 = (*_2); -+ _1 = const E::V1(0); ++ _1 = const E::V1(0_i32); StorageDead(_2); StorageLive(_3); - _4 = discriminant(_1); @@ -111,6 +111,10 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC3 (size: 8, align: 4) { ++ 00 00 00 00 00 00 00 00 │ ........ } ALLOC2 (static: RC, size: 4, align: 4) { diff --git a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff index 48897b93e46c..5d69572b5074 100644 --- a/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/enum.statics.DataflowConstProp.64bit.diff @@ -45,7 +45,7 @@ StorageLive(_2); _2 = const {ALLOC1: &E}; - _1 = (*_2); -+ _1 = const E::V1(0); ++ _1 = const E::V1(0_i32); StorageDead(_2); StorageLive(_3); - _4 = discriminant(_1); @@ -111,6 +111,10 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC3 (size: 8, align: 4) { ++ 00 00 00 00 00 00 00 00 │ ........ } ALLOC2 (static: RC, size: 8, align: 8) { diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff index b5f7f2a472c4..2d4591ea2d3d 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-abort.diff @@ -23,7 +23,7 @@ StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind unreachable]; -+ _4 = const (0, true); ++ _4 = const (0_u8, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind unreachable]; } @@ -37,5 +37,9 @@ _0 = const (); return; } ++ } ++ ++ ALLOC0 (size: 2, align: 1) { ++ 00 01 │ .. } diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff index e2e799650aa4..e99ac782a2ff 100644 --- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff +++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.panic-unwind.diff @@ -23,7 +23,7 @@ StorageLive(_4); - _4 = CheckedAdd(_2, _3); - assert(!move (_4.1: bool), "attempt to compute `{} + {}`, which would overflow", _2, _3) -> [success: bb1, unwind continue]; -+ _4 = const (0, true); ++ _4 = const (0_u8, true); + assert(!const true, "attempt to compute `{} + {}`, which would overflow", const u8::MAX, const 1_u8) -> [success: bb1, unwind continue]; } @@ -37,5 +37,9 @@ _0 = const (); return; } ++ } ++ ++ ALLOC0 (size: 2, align: 1) { ++ 00 01 │ .. } diff --git a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff index 4530d8b627bd..98bd40ab2c3d 100644 --- a/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/repr_transparent.main.DataflowConstProp.diff @@ -18,7 +18,7 @@ bb0: { StorageLive(_1); - _1 = I32(const 0_i32); -+ _1 = const I32(0); ++ _1 = const I32(0_i32); StorageLive(_2); StorageLive(_3); StorageLive(_4); @@ -32,12 +32,20 @@ StorageDead(_5); StorageDead(_4); - _2 = I32(move _3); -+ _2 = const I32(0); ++ _2 = const I32(0_i32); StorageDead(_3); _0 = const (); StorageDead(_2); StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 4, align: 4) { ++ 00 00 00 00 │ .... ++ } ++ ++ ALLOC1 (size: 4, align: 4) { ++ 00 00 00 00 │ .... } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 8d277459d3bd..944b061f9939 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -7,17 +7,24 @@ let mut _3: i32; let mut _5: i32; let mut _6: i32; - let mut _11: BigStruct; - let mut _16: &&BigStruct; - let mut _18: S; - let mut _19: u8; - let mut _20: f32; - let mut _21: S; - let mut _22: &BigStruct; - let mut _23: &BigStruct; - let mut _24: &BigStruct; - let mut _25: &BigStruct; - let mut _26: &BigStruct; + let mut _10: SmallStruct; + let mut _14: &&SmallStruct; + let mut _16: f32; + let mut _17: std::option::Option; + let mut _18: &[f32]; + let mut _22: BigStruct; + let mut _26: &&BigStruct; + let mut _28: f32; + let mut _29: std::option::Option; + let mut _30: &[f64]; + let mut _31: &SmallStruct; + let mut _32: &SmallStruct; + let mut _33: &SmallStruct; + let mut _34: &SmallStruct; + let mut _35: &BigStruct; + let mut _36: &BigStruct; + let mut _37: &BigStruct; + let mut _38: &BigStruct; scope 1 { debug s => _1; let _2: i32; @@ -26,27 +33,43 @@ let _4: i32; scope 3 { debug b => _4; - let _7: S; - let _8: u8; - let _9: f32; - let _10: S; + let _7: f32; + let _8: std::option::Option; + let _9: &[f32]; scope 4 { debug a => _7; debug b => _8; debug c => _9; - debug d => _10; - let _12: S; - let _13: u8; - let _14: f32; - let _15: S; + let _11: f32; + let _12: std::option::Option; + let _13: &[f32]; scope 5 { - debug a => _12; - debug b => _13; - debug c => _14; - debug d => _15; - let _17: BigStruct; + debug a => _11; + debug b => _12; + debug c => _13; + let _15: SmallStruct; scope 6 { - debug bs => _17; + debug ss => _15; + let _19: f32; + let _20: std::option::Option; + let _21: &[f64]; + scope 7 { + debug a => _19; + debug b => _20; + debug c => _21; + let _23: f32; + let _24: std::option::Option; + let _25: &[f64]; + scope 8 { + debug a => _23; + debug b => _24; + debug c => _25; + let _27: BigStruct; + scope 9 { + debug bs => _27; + } + } + } } } } @@ -57,7 +80,7 @@ bb0: { StorageLive(_1); - _1 = S(const 1_i32); -+ _1 = const S(1); ++ _1 = const S(1_i32); StorageLive(_2); StorageLive(_3); - _3 = (_1.0: i32); @@ -77,67 +100,95 @@ + _4 = const 6_i32; StorageDead(_6); StorageDead(_5); - StorageLive(_11); - _11 = const _; - StorageLive(_7); -- _7 = (_11.0: S); -+ _7 = const S(1_i32); - StorageLive(_8); -- _8 = (_11.1: u8); -+ _8 = const 5_u8; - StorageLive(_9); -- _9 = (_11.2: f32); -+ _9 = const 7f32; StorageLive(_10); -- _10 = (_11.3: S); -+ _10 = const S(13_i32); - StorageDead(_11); - StorageLive(_16); - _16 = const {ALLOC1: &&BigStruct}; - _22 = deref_copy (*_16); - StorageLive(_12); - _23 = deref_copy (*_16); -- _12 = ((*_23).0: S); -+ _12 = const S(1_i32); - StorageLive(_13); - _24 = deref_copy (*_16); -- _13 = ((*_24).1: u8); -+ _13 = const 5_u8; + _10 = const _; + StorageLive(_7); +- _7 = (_10.0: f32); ++ _7 = const 4f32; + StorageLive(_8); +- _8 = (_10.1: std::option::Option); ++ _8 = const Option::::Some(S(1_i32)); + StorageLive(_9); + _9 = (_10.2: &[f32]); + StorageDead(_10); StorageLive(_14); - _25 = deref_copy (*_16); -- _14 = ((*_25).2: f32); -+ _14 = const 7f32; + _14 = const {ALLOC4: &&SmallStruct}; + _31 = deref_copy (*_14); + StorageLive(_11); + _32 = deref_copy (*_14); +- _11 = ((*_32).0: f32); ++ _11 = const 9f32; + StorageLive(_12); + _33 = deref_copy (*_14); + _12 = ((*_33).1: std::option::Option); + StorageLive(_13); + _34 = deref_copy (*_14); + _13 = ((*_34).2: &[f32]); + StorageDead(_14); StorageLive(_15); - _26 = deref_copy (*_16); -- _15 = ((*_26).3: S); -+ _15 = const S(13_i32); - StorageDead(_16); + StorageLive(_16); +- _16 = _11; ++ _16 = const 9f32; StorageLive(_17); + _17 = _12; StorageLive(_18); -- _18 = _12; -+ _18 = const S(1_i32); + _18 = _13; +- _15 = SmallStruct(move _16, move _17, move _18); ++ _15 = SmallStruct(const 9f32, move _17, move _18); + StorageDead(_18); + StorageDead(_17); + StorageDead(_16); + StorageLive(_22); + _22 = const _; StorageLive(_19); -- _19 = _13; -+ _19 = const 5_u8; +- _19 = (_22.0: f32); ++ _19 = const 25f32; StorageLive(_20); -- _20 = _14; -+ _20 = const 7f32; + _20 = (_22.1: std::option::Option); StorageLive(_21); -- _21 = _15; -- _17 = BigStruct(move _18, move _19, move _20, move _21); -+ _21 = const S(13_i32); -+ _17 = const BigStruct(S(1), 5, 7f32, S(13)); + _21 = (_22.2: &[f64]); + StorageDead(_22); + StorageLive(_26); + _26 = const {ALLOC5: &&BigStruct}; + _35 = deref_copy (*_26); + StorageLive(_23); + _36 = deref_copy (*_26); +- _23 = ((*_36).0: f32); ++ _23 = const 82f32; + StorageLive(_24); + _37 = deref_copy (*_26); +- _24 = ((*_37).1: std::option::Option); ++ _24 = const Option::::Some(S(35_i32)); + StorageLive(_25); + _38 = deref_copy (*_26); + _25 = ((*_38).2: &[f64]); + StorageDead(_26); + StorageLive(_27); + StorageLive(_28); +- _28 = _23; ++ _28 = const 82f32; + StorageLive(_29); +- _29 = _24; ++ _29 = const Option::::Some(S(35_i32)); + StorageLive(_30); + _30 = _25; +- _27 = BigStruct(move _28, move _29, move _30); ++ _27 = BigStruct(const 82f32, const Option::::Some(S(35_i32)), move _30); + StorageDead(_30); + StorageDead(_29); + StorageDead(_28); + _0 = const (); + StorageDead(_27); + StorageDead(_25); + StorageDead(_24); + StorageDead(_23); StorageDead(_21); StorageDead(_20); StorageDead(_19); - StorageDead(_18); - _0 = const (); - StorageDead(_17); StorageDead(_15); - StorageDead(_14); StorageDead(_13); StorageDead(_12); - StorageDead(_10); + StorageDead(_11); StorageDead(_9); StorageDead(_8); StorageDead(_7); @@ -146,13 +197,51 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC6 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC7 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC8 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC9 (size: 8, align: 4) { ++ 01 00 00 00 01 00 00 00 │ ........ ++ } ++ ++ ALLOC10 (size: 4, align: 4) { ++ 01 00 00 00 │ .... } - ALLOC1 (static: STAT, size: 4, align: 4) { + ALLOC5 (static: BIG_STAT, size: 4, align: 4) { ╾ALLOC0╼ │ ╾──╼ } - ALLOC0 (size: 16, align: 4) { - 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ + ALLOC0 (size: 20, align: 4) { + 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ 02 00 00 00 │ ....#...╾──╼.... + 0x10 │ 00 00 a4 42 │ ...B + } + + ALLOC1 (size: 16, align: 4) { + 00 00 00 00 00 80 46 40 00 00 00 00 00 00 52 40 │ ......F@......R@ + } + + ALLOC4 (static: SMALL_STAT, size: 4, align: 4) { + ╾ALLOC2╼ │ ╾──╼ + } + + ALLOC2 (size: 20, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ 01 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 10 41 │ ...A + } + + ALLOC3 (size: 4, align: 4) { + 00 00 50 41 │ ..PA } diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index fca94beb9ab5..c2c95657a2a3 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -7,17 +7,24 @@ let mut _3: i32; let mut _5: i32; let mut _6: i32; - let mut _11: BigStruct; - let mut _16: &&BigStruct; - let mut _18: S; - let mut _19: u8; - let mut _20: f32; - let mut _21: S; - let mut _22: &BigStruct; - let mut _23: &BigStruct; - let mut _24: &BigStruct; - let mut _25: &BigStruct; - let mut _26: &BigStruct; + let mut _10: SmallStruct; + let mut _14: &&SmallStruct; + let mut _16: f32; + let mut _17: std::option::Option; + let mut _18: &[f32]; + let mut _22: BigStruct; + let mut _26: &&BigStruct; + let mut _28: f32; + let mut _29: std::option::Option; + let mut _30: &[f64]; + let mut _31: &SmallStruct; + let mut _32: &SmallStruct; + let mut _33: &SmallStruct; + let mut _34: &SmallStruct; + let mut _35: &BigStruct; + let mut _36: &BigStruct; + let mut _37: &BigStruct; + let mut _38: &BigStruct; scope 1 { debug s => _1; let _2: i32; @@ -26,27 +33,43 @@ let _4: i32; scope 3 { debug b => _4; - let _7: S; - let _8: u8; - let _9: f32; - let _10: S; + let _7: f32; + let _8: std::option::Option; + let _9: &[f32]; scope 4 { debug a => _7; debug b => _8; debug c => _9; - debug d => _10; - let _12: S; - let _13: u8; - let _14: f32; - let _15: S; + let _11: f32; + let _12: std::option::Option; + let _13: &[f32]; scope 5 { - debug a => _12; - debug b => _13; - debug c => _14; - debug d => _15; - let _17: BigStruct; + debug a => _11; + debug b => _12; + debug c => _13; + let _15: SmallStruct; scope 6 { - debug bs => _17; + debug ss => _15; + let _19: f32; + let _20: std::option::Option; + let _21: &[f64]; + scope 7 { + debug a => _19; + debug b => _20; + debug c => _21; + let _23: f32; + let _24: std::option::Option; + let _25: &[f64]; + scope 8 { + debug a => _23; + debug b => _24; + debug c => _25; + let _27: BigStruct; + scope 9 { + debug bs => _27; + } + } + } } } } @@ -57,7 +80,7 @@ bb0: { StorageLive(_1); - _1 = S(const 1_i32); -+ _1 = const S(1); ++ _1 = const S(1_i32); StorageLive(_2); StorageLive(_3); - _3 = (_1.0: i32); @@ -77,67 +100,95 @@ + _4 = const 6_i32; StorageDead(_6); StorageDead(_5); - StorageLive(_11); - _11 = const _; - StorageLive(_7); -- _7 = (_11.0: S); -+ _7 = const S(1_i32); - StorageLive(_8); -- _8 = (_11.1: u8); -+ _8 = const 5_u8; - StorageLive(_9); -- _9 = (_11.2: f32); -+ _9 = const 7f32; StorageLive(_10); -- _10 = (_11.3: S); -+ _10 = const S(13_i32); - StorageDead(_11); - StorageLive(_16); - _16 = const {ALLOC1: &&BigStruct}; - _22 = deref_copy (*_16); - StorageLive(_12); - _23 = deref_copy (*_16); -- _12 = ((*_23).0: S); -+ _12 = const S(1_i32); - StorageLive(_13); - _24 = deref_copy (*_16); -- _13 = ((*_24).1: u8); -+ _13 = const 5_u8; + _10 = const _; + StorageLive(_7); +- _7 = (_10.0: f32); ++ _7 = const 4f32; + StorageLive(_8); +- _8 = (_10.1: std::option::Option); ++ _8 = const Option::::Some(S(1_i32)); + StorageLive(_9); + _9 = (_10.2: &[f32]); + StorageDead(_10); StorageLive(_14); - _25 = deref_copy (*_16); -- _14 = ((*_25).2: f32); -+ _14 = const 7f32; + _14 = const {ALLOC4: &&SmallStruct}; + _31 = deref_copy (*_14); + StorageLive(_11); + _32 = deref_copy (*_14); +- _11 = ((*_32).0: f32); ++ _11 = const 9f32; + StorageLive(_12); + _33 = deref_copy (*_14); + _12 = ((*_33).1: std::option::Option); + StorageLive(_13); + _34 = deref_copy (*_14); + _13 = ((*_34).2: &[f32]); + StorageDead(_14); StorageLive(_15); - _26 = deref_copy (*_16); -- _15 = ((*_26).3: S); -+ _15 = const S(13_i32); - StorageDead(_16); + StorageLive(_16); +- _16 = _11; ++ _16 = const 9f32; StorageLive(_17); + _17 = _12; StorageLive(_18); -- _18 = _12; -+ _18 = const S(1_i32); + _18 = _13; +- _15 = SmallStruct(move _16, move _17, move _18); ++ _15 = SmallStruct(const 9f32, move _17, move _18); + StorageDead(_18); + StorageDead(_17); + StorageDead(_16); + StorageLive(_22); + _22 = const _; StorageLive(_19); -- _19 = _13; -+ _19 = const 5_u8; +- _19 = (_22.0: f32); ++ _19 = const 25f32; StorageLive(_20); -- _20 = _14; -+ _20 = const 7f32; + _20 = (_22.1: std::option::Option); StorageLive(_21); -- _21 = _15; -- _17 = BigStruct(move _18, move _19, move _20, move _21); -+ _21 = const S(13_i32); -+ _17 = const BigStruct(S(1), 5, 7f32, S(13)); + _21 = (_22.2: &[f64]); + StorageDead(_22); + StorageLive(_26); + _26 = const {ALLOC5: &&BigStruct}; + _35 = deref_copy (*_26); + StorageLive(_23); + _36 = deref_copy (*_26); +- _23 = ((*_36).0: f32); ++ _23 = const 82f32; + StorageLive(_24); + _37 = deref_copy (*_26); +- _24 = ((*_37).1: std::option::Option); ++ _24 = const Option::::Some(S(35_i32)); + StorageLive(_25); + _38 = deref_copy (*_26); + _25 = ((*_38).2: &[f64]); + StorageDead(_26); + StorageLive(_27); + StorageLive(_28); +- _28 = _23; ++ _28 = const 82f32; + StorageLive(_29); +- _29 = _24; ++ _29 = const Option::::Some(S(35_i32)); + StorageLive(_30); + _30 = _25; +- _27 = BigStruct(move _28, move _29, move _30); ++ _27 = BigStruct(const 82f32, const Option::::Some(S(35_i32)), move _30); + StorageDead(_30); + StorageDead(_29); + StorageDead(_28); + _0 = const (); + StorageDead(_27); + StorageDead(_25); + StorageDead(_24); + StorageDead(_23); StorageDead(_21); StorageDead(_20); StorageDead(_19); - StorageDead(_18); - _0 = const (); - StorageDead(_17); StorageDead(_15); - StorageDead(_14); StorageDead(_13); StorageDead(_12); - StorageDead(_10); + StorageDead(_11); StorageDead(_9); StorageDead(_8); StorageDead(_7); @@ -146,13 +197,51 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC6 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC7 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC8 (size: 8, align: 4) { ++ 01 00 00 00 23 00 00 00 │ ....#... ++ } ++ ++ ALLOC9 (size: 8, align: 4) { ++ 01 00 00 00 01 00 00 00 │ ........ ++ } ++ ++ ALLOC10 (size: 4, align: 4) { ++ 01 00 00 00 │ .... } - ALLOC1 (static: STAT, size: 8, align: 8) { + ALLOC5 (static: BIG_STAT, size: 8, align: 8) { ╾ALLOC0╼ │ ╾──────╼ } - ALLOC0 (size: 16, align: 4) { - 01 00 00 00 00 00 e0 40 0d 00 00 00 05 __ __ __ │ .......@.....░░░ + ALLOC0 (size: 32, align: 8) { + 0x00 │ 01 00 00 00 23 00 00 00 ╾ALLOC1╼ │ ....#...╾──────╼ + 0x10 │ 02 00 00 00 00 00 00 00 00 00 a4 42 __ __ __ __ │ ...........B░░░░ + } + + ALLOC1 (size: 16, align: 8) { + 00 00 00 00 00 80 46 40 00 00 00 00 00 00 52 40 │ ......F@......R@ + } + + ALLOC4 (static: SMALL_STAT, size: 8, align: 8) { + ╾ALLOC2╼ │ ╾──────╼ + } + + ALLOC2 (size: 32, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾ALLOC3╼ │ ....░░░░╾──────╼ + 0x10 │ 01 00 00 00 00 00 00 00 00 00 10 41 __ __ __ __ │ ...........A░░░░ + } + + ALLOC3 (size: 4, align: 4) { + 00 00 50 41 │ ..PA } diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 5c6edeb3866e..030f3c0c4ded 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -6,7 +6,10 @@ struct S(i32); #[derive(Copy, Clone)] -struct BigStruct(S, u8, f32, S); +struct SmallStruct(f32, Option, &'static [f32]); + +#[derive(Copy, Clone)] +struct BigStruct(f32, Option, &'static [f64]); // EMIT_MIR struct.main.DataflowConstProp.diff fn main() { @@ -15,11 +18,21 @@ fn main() { s.0 = 3; let b = a + s.0; - const VAL: BigStruct = BigStruct(S(1), 5, 7., S(13)); - let BigStruct(a, b, c, d) = VAL; + const SMALL_VAL: SmallStruct = SmallStruct(4., Some(S(1)), &[]); + let SmallStruct(a, b, c) = SMALL_VAL; - static STAT: &BigStruct = &BigStruct(S(1), 5, 7., S(13)); - let BigStruct(a, b, c, d) = *STAT; + static SMALL_STAT: &SmallStruct = &SmallStruct(9., None, &[13.]); + let SmallStruct(a, b, c) = *SMALL_STAT; - let bs = BigStruct(a, b, c, d); + let ss = SmallStruct(a, b, c); + + const BIG_VAL: BigStruct = BigStruct(25., None, &[]); + let BigStruct(a, b, c) = BIG_VAL; + + static BIG_STAT: &BigStruct = &BigStruct(82., Some(S(35)), &[45., 72.]); + let BigStruct(a, b, c) = *BIG_STAT; + + // We arbitrarily limit the size of synthetized values to 4 pointers. + // `BigStruct` can be read, but we will keep a MIR aggregate for this. + let bs = BigStruct(a, b, c); } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.rs b/tests/mir-opt/dataflow-const-prop/transmute.rs index 02e4f1e50134..bb85e4586787 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.rs +++ b/tests/mir-opt/dataflow-const-prop/transmute.rs @@ -52,8 +52,8 @@ pub unsafe fn undef_union_as_integer() -> u32 { // EMIT_MIR transmute.unreachable_direct.DataflowConstProp.diff pub unsafe fn unreachable_direct() -> ! { // CHECK-LABEL: fn unreachable_direct( - // CHECK: [[unit:_.*]] = (); - // CHECK: move [[unit]] as Never (Transmute); + // CHECK: = const (); + // CHECK: = const ZeroSized: Never; let x: Never = unsafe { transmute(()) }; match x {} } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff index fc0634b1f8fc..fb28aa8f6d9c 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.32bit.diff @@ -11,8 +11,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = Union32 { value: move _2 }; +- _2 = (); +- _1 = Union32 { value: move _2 }; ++ _2 = const (); ++ _1 = Union32 { value: const () }; StorageDead(_2); _0 = move _1 as u32 (Transmute); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff index fc0634b1f8fc..fb28aa8f6d9c 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.undef_union_as_integer.DataflowConstProp.64bit.diff @@ -11,8 +11,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = Union32 { value: move _2 }; +- _2 = (); +- _1 = Union32 { value: move _2 }; ++ _2 = const (); ++ _1 = Union32 { value: const () }; StorageDead(_2); _0 = move _1 as u32 (Transmute); StorageDead(_1); diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff index acbb5cd1bc73..c8d4d6edba1e 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.32bit.diff @@ -14,8 +14,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = move _2 as Never (Transmute); +- _2 = (); +- _1 = move _2 as Never (Transmute); ++ _2 = const (); ++ _1 = const ZeroSized: Never; unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff index acbb5cd1bc73..c8d4d6edba1e 100644 --- a/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/transmute.unreachable_direct.DataflowConstProp.64bit.diff @@ -14,8 +14,10 @@ bb0: { StorageLive(_1); StorageLive(_2); - _2 = (); - _1 = move _2 as Never (Transmute); +- _2 = (); +- _1 = move _2 as Never (Transmute); ++ _2 = const (); ++ _1 = const ZeroSized: Never; unreachable; } } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff similarity index 80% rename from tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff rename to tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff index 21c9b9d1eb96..f5723cac7d9c 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.diff +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.32bit.diff @@ -33,7 +33,7 @@ bb0: { StorageLive(_1); - _1 = (const 1_i32, const 2_i32); -+ _1 = const (1, 2); ++ _1 = const (1_i32, 2_i32); StorageLive(_2); StorageLive(_3); StorageLive(_4); @@ -50,7 +50,7 @@ + _2 = const 6_i32; StorageDead(_3); - _1 = (const 2_i32, const 3_i32); -+ _1 = const (2, 3); ++ _1 = const (2_i32, 3_i32); StorageLive(_6); StorageLive(_7); StorageLive(_8); @@ -76,12 +76,12 @@ + _12 = const 6_i32; StorageLive(_13); - _13 = _1; -+ _13 = const (2, 3); ++ _13 = const (2_i32, 3_i32); StorageLive(_14); - _14 = _6; - _11 = (move _12, move _13, move _14); + _14 = const 11_i32; -+ _11 = const (6, (2, 3), 11); ++ _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32); StorageDead(_14); StorageDead(_13); StorageDead(_12); @@ -92,5 +92,21 @@ StorageDead(_1); return; } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC1 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC2 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC3 (size: 8, align: 4) { ++ 01 00 00 00 02 00 00 00 │ ........ } diff --git a/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff new file mode 100644 index 000000000000..f5723cac7d9c --- /dev/null +++ b/tests/mir-opt/dataflow-const-prop/tuple.main.DataflowConstProp.64bit.diff @@ -0,0 +1,112 @@ +- // MIR for `main` before DataflowConstProp ++ // MIR for `main` after DataflowConstProp + + fn main() -> () { + let mut _0: (); + let mut _1: (i32, i32); + let mut _3: i32; + let mut _4: i32; + let mut _5: i32; + let mut _7: i32; + let mut _8: i32; + let mut _9: i32; + let mut _10: i32; + let mut _12: i32; + let mut _13: (i32, i32); + let mut _14: i32; + scope 1 { + debug a => _1; + let _2: i32; + scope 2 { + debug b => _2; + let _6: i32; + scope 3 { + debug c => _6; + let _11: (i32, (i32, i32), i32); + scope 4 { + debug d => _11; + } + } + } + } + + bb0: { + StorageLive(_1); +- _1 = (const 1_i32, const 2_i32); ++ _1 = const (1_i32, 2_i32); + StorageLive(_2); + StorageLive(_3); + StorageLive(_4); +- _4 = (_1.0: i32); ++ _4 = const 1_i32; + StorageLive(_5); +- _5 = (_1.1: i32); +- _3 = Add(move _4, move _5); ++ _5 = const 2_i32; ++ _3 = const 3_i32; + StorageDead(_5); + StorageDead(_4); +- _2 = Add(move _3, const 3_i32); ++ _2 = const 6_i32; + StorageDead(_3); +- _1 = (const 2_i32, const 3_i32); ++ _1 = const (2_i32, 3_i32); + StorageLive(_6); + StorageLive(_7); + StorageLive(_8); +- _8 = (_1.0: i32); ++ _8 = const 2_i32; + StorageLive(_9); +- _9 = (_1.1: i32); +- _7 = Add(move _8, move _9); ++ _9 = const 3_i32; ++ _7 = const 5_i32; + StorageDead(_9); + StorageDead(_8); + StorageLive(_10); +- _10 = _2; +- _6 = Add(move _7, move _10); ++ _10 = const 6_i32; ++ _6 = const 11_i32; + StorageDead(_10); + StorageDead(_7); + StorageLive(_11); + StorageLive(_12); +- _12 = _2; ++ _12 = const 6_i32; + StorageLive(_13); +- _13 = _1; ++ _13 = const (2_i32, 3_i32); + StorageLive(_14); +- _14 = _6; +- _11 = (move _12, move _13, move _14); ++ _14 = const 11_i32; ++ _11 = (const 6_i32, const (2_i32, 3_i32), const 11_i32); + StorageDead(_14); + StorageDead(_13); + StorageDead(_12); + _0 = const (); + StorageDead(_11); + StorageDead(_6); + StorageDead(_2); + StorageDead(_1); + return; + } ++ } ++ ++ ALLOC0 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC1 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC2 (size: 8, align: 4) { ++ 02 00 00 00 03 00 00 00 │ ........ ++ } ++ ++ ALLOC3 (size: 8, align: 4) { ++ 01 00 00 00 02 00 00 00 │ ........ + } + diff --git a/tests/mir-opt/dataflow-const-prop/tuple.rs b/tests/mir-opt/dataflow-const-prop/tuple.rs index 7691bc8d7c50..bb706eafe888 100644 --- a/tests/mir-opt/dataflow-const-prop/tuple.rs +++ b/tests/mir-opt/dataflow-const-prop/tuple.rs @@ -1,5 +1,6 @@ // skip-filecheck // unit-test: DataflowConstProp +// EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR tuple.main.DataflowConstProp.diff fn main() { From e472b5573a04c7e41208199c09a5a501cf972cf8 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sat, 21 Oct 2023 19:54:51 +0000 Subject: [PATCH 13/51] Merge commit 'c07d1e2f88cb3b1a0604ae8f18b478c1aeb7a7fa' into sync_cg_clif-2023-10-21 --- .cirrus.yml | 2 +- .github/workflows/main.yml | 10 +- Cargo.lock | 52 +-- Cargo.toml | 12 +- build_system/build_sysroot.rs | 9 + build_system/prepare.rs | 1 + build_system/tests.rs | 6 +- build_system/utils.rs | 10 + patches/0002-rand-Disable-failing-test.patch | 24 -- ...003-rand-Disable-rand-tests-on-mingw.patch | 47 --- patches/portable-simd-lock.toml | 304 ------------------ patches/stdlib-lock.toml | 5 +- rust-toolchain | 2 +- scripts/setup_rust_fork.sh | 27 +- scripts/test_rustc_tests.sh | 21 +- src/debuginfo/mod.rs | 2 +- src/driver/aot.rs | 47 +-- src/global_asm.rs | 8 +- src/inline_asm.rs | 59 +++- src/lib.rs | 8 +- 20 files changed, 163 insertions(+), 493 deletions(-) delete mode 100644 patches/0002-rand-Disable-failing-test.patch delete mode 100644 patches/0003-rand-Disable-rand-tests-on-mingw.patch delete mode 100644 patches/portable-simd-lock.toml diff --git a/.cirrus.yml b/.cirrus.yml index 8b4efd4e3948..aa1a2bad2cf2 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -3,7 +3,7 @@ task: freebsd_instance: image: freebsd-13-2-release-amd64 setup_rust_script: - - pkg install -y git bash + - pkg install -y git bash binutils - curl https://sh.rustup.rs -sSf --output rustup.sh - sh rustup.sh --default-toolchain none -y --profile=minimal target_cache: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 652d6eca3f6e..47d9a3b93f72 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -50,10 +50,12 @@ jobs: - os: ubuntu-latest env: TARGET_TRIPLE: aarch64-unknown-linux-gnu - # s390x requires QEMU 6.1 or greater, we could build it from source, but ubuntu 22.04 comes with 6.2 by default - os: ubuntu-latest env: TARGET_TRIPLE: s390x-unknown-linux-gnu + - os: ubuntu-latest + env: + TARGET_TRIPLE: riscv64gc-unknown-linux-gnu - os: windows-latest env: TARGET_TRIPLE: x86_64-pc-windows-msvc @@ -92,6 +94,12 @@ jobs: sudo apt-get update sudo apt-get install -y gcc-s390x-linux-gnu qemu-user + - name: Install riscv64gc toolchain and qemu + if: matrix.env.TARGET_TRIPLE == 'riscv64gc-unknown-linux-gnu' + run: | + sudo apt-get update + sudo apt-get install -y gcc-riscv64-linux-gnu qemu-user + - name: Prepare dependencies run: ./y.sh prepare diff --git a/Cargo.lock b/Cargo.lock index 7c324421be9c..8079913cb0ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b9d1a9e776c27ad55d7792a380785d1fe8c2d7b099eed8dbd8f4af2b598192" +checksum = "8e5e1df0da8488dd03b34afc134ba84b754d61862cc465932a9e5d07952f661e" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5528483314c2dd5da438576cd8a9d0b3cedad66fb8a4727f90cd319a81950038" +checksum = "77a17ca4e699a0aaf49a0c88f6311a864f321048aa63f6b787cab20eb5f93f10" dependencies = [ "bumpalo", "cranelift-bforest", @@ -75,39 +75,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f46a8318163f7682e35b8730ba93c1b586a2da8ce12a0ed545efc1218550f70" +checksum = "022f2793cdade1d37a1f755ac42938a3f832f533eac6cafc8b26b209544c3c06" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37d1239cfd50eecfaed468d46943f8650e32969591868ad50111613704da6c70" +checksum = "a4d72dbb83c2ad788dec4ad0843070973cb48c35a3ca19b1e7437ac40834fd9c" [[package]] name = "cranelift-control" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc530560c8f16cc1d4dd7ea000c56f519c60d1a914977abe849ce555c35a61d" +checksum = "ae07cf26dcc90d546826d747ac63b6c40c916f34b03e92a6ae0422c28d771b8a" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f333fa641a9ad2bff0b107767dcb972c18c2bfab7969805a1d7e42449ccb0408" +checksum = "c2fe6b7e49820893691aea497f36257e9d6f52061d8c4758d61d802d5f101a3d" [[package]] name = "cranelift-frontend" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abf6563015a80f03f8bc4df307d0a81363f4eb73108df3a34f6e66fb6d5307" +checksum = "44f497576ca3674581581601b6a55ccc1b43447217648c880e5bce70db3cf659" dependencies = [ "cranelift-codegen", "log", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eb29d0edc8a5c029ed0f7ca77501f272738e3c410020b4a00f42ffe8ad2a8aa" +checksum = "b96aa02eac00fffee13b0cd37d17874ccdb3d5458983041accd825ef78ce6454" [[package]] name = "cranelift-jit" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16e8c5e212b1e63658aada17553497e7a259acab61f044d1f185527efa609fb" +checksum = "b1d6e0e308c873eefc185745a6b21daec2a10f7554c9fb67e334c2d7d756d979" dependencies = [ "anyhow", "cranelift-codegen", @@ -143,9 +143,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b5fd273e1a959e920c7a9d790b1646d31acc8782bb549bad5ab85dd2fc9aa7" +checksum = "c1aa8ebb06eced4e478c3f94f1d65d4e7c93493f4640057912b27a3e34b84841" dependencies = [ "anyhow", "cranelift-codegen", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "006056a7fa920870bad06bf8e1b3033d70cbb7ee625b035efa9d90882a931868" +checksum = "2870170ca44054b202c737626607b87be6e35655084bd94a6ff807a5812ba7df" dependencies = [ "cranelift-codegen", "libc", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.100.0" +version = "0.101.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8be1b0e7720f30fec31be0c0b0b23caef2a73fa751190c6a251c1362e8f8c9" +checksum = "20647761742d17dabac8205da958910ede78599550e06418a16711a3ee2fc897" dependencies = [ "anyhow", "cranelift-codegen", @@ -374,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "13.0.0" +version = "14.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6ff5f3707a5e3797deeeeac6ac26b2e1dd32dbc06693c0ab52e8ac4d18ec706" +checksum = "a3a5dda53ad6993f9b0a2d65fb49e0348a7232a27a8794064122870d6ee19eb2" dependencies = [ "cfg-if", "libc", diff --git a/Cargo.toml b/Cargo.toml index 28a37b7995b7..5ad5e0e8140c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.100", features = ["unwind", "all-arch"] } -cranelift-frontend = { version = "0.100" } -cranelift-module = { version = "0.100" } -cranelift-native = { version = "0.100" } -cranelift-jit = { version = "0.100", optional = true } -cranelift-object = { version = "0.100" } +cranelift-codegen = { version = "0.101", features = ["unwind", "all-arch"] } +cranelift-frontend = { version = "0.101" } +cranelift-module = { version = "0.101" } +cranelift-native = { version = "0.101" } +cranelift-jit = { version = "0.101", optional = true } +cranelift-object = { version = "0.101" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/build_system/build_sysroot.rs b/build_system/build_sysroot.rs index 31a4b209826f..1ed896c6bf0e 100644 --- a/build_system/build_sysroot.rs +++ b/build_system/build_sysroot.rs @@ -1,3 +1,4 @@ +use std::env; use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; @@ -259,6 +260,14 @@ fn build_clif_sysroot_for_triple( // inlining. rustflags.push("-Zinline-mir".to_owned()); } + if let Some(prefix) = env::var_os("CG_CLIF_STDLIB_REMAP_PATH_PREFIX") { + rustflags.push("--remap-path-prefix".to_owned()); + rustflags.push(format!( + "{}={}", + STDLIB_SRC.to_path(dirs).to_str().unwrap(), + prefix.to_str().unwrap() + )); + } compiler.rustflags.extend(rustflags); let mut build_cmd = STANDARD_LIBRARY.build(&compiler, dirs); maybe_incremental(&mut build_cmd); diff --git a/build_system/prepare.rs b/build_system/prepare.rs index 16e7a4bafaee..c68968b4fde2 100644 --- a/build_system/prepare.rs +++ b/build_system/prepare.rs @@ -143,6 +143,7 @@ impl GitRepo { RelPath::PATCHES.to_path(dirs).join(format!("{}-lock.toml", self.patch_name)); let target_lockfile = download_dir.join("Cargo.lock"); if source_lockfile.exists() { + assert!(!target_lockfile.exists()); fs::copy(source_lockfile, target_lockfile).unwrap(); } else { assert!(target_lockfile.exists()); diff --git a/build_system/tests.rs b/build_system/tests.rs index 95ff6b754220..1e24d1b113fe 100644 --- a/build_system/tests.rs +++ b/build_system/tests.rs @@ -104,8 +104,8 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ pub(crate) static RAND_REPO: GitRepo = GitRepo::github( "rust-random", "rand", - "f3dd0b885c4597b9617ca79987a0dd899ab29fcb", - "3f869e4fcd602b66", + "9a02c819cc1e4ec6959ae25eafbb5cf6acb68234", + "4934f0afb1d1c2ca", "rand", ); @@ -125,7 +125,7 @@ pub(crate) static PORTABLE_SIMD_REPO: GitRepo = GitRepo::github( "rust-lang", "portable-simd", "4825b2a64d765317066948867e8714674419359b", - "8b188cc41f5af835", + "9e67d07c00f5fb0b", "portable-simd", ); diff --git a/build_system/utils.rs b/build_system/utils.rs index 9f24c043a504..149f1618f5c0 100644 --- a/build_system/utils.rs +++ b/build_system/utils.rs @@ -42,6 +42,16 @@ impl Compiler { "/usr/s390x-linux-gnu".to_owned(), ]; } + "riscv64gc-unknown-linux-gnu" => { + // We are cross-compiling for riscv64. Use the correct linker and run tests in qemu. + self.rustflags.push("-Clinker=riscv64-linux-gnu-gcc".to_owned()); + self.rustdocflags.push("-Clinker=riscv64-linux-gnu-gcc".to_owned()); + self.runner = vec![ + "qemu-riscv64".to_owned(), + "-L".to_owned(), + "/usr/riscv64-linux-gnu".to_owned(), + ]; + } "x86_64-pc-windows-gnu" => { // We are cross-compiling for Windows. Run tests in wine. self.runner = vec!["wine".to_owned()]; diff --git a/patches/0002-rand-Disable-failing-test.patch b/patches/0002-rand-Disable-failing-test.patch deleted file mode 100644 index ae13ab3b0ca6..000000000000 --- a/patches/0002-rand-Disable-failing-test.patch +++ /dev/null @@ -1,24 +0,0 @@ -From a8fb97120d71252538b6b026695df40d02696bdb Mon Sep 17 00:00:00 2001 -From: bjorn3 -Date: Sat, 15 Aug 2020 20:04:38 +0200 -Subject: [PATCH] [rand] Disable failing test - ---- - src/distributions/uniform.rs | 1 + - 1 file changed, 1 insertion(+), 0 deletions(-) - -diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs -index 480b859..c80bb6f 100644 ---- a/src/distributions/uniform.rs -+++ b/src/distributions/uniform.rs -@@ -1314,6 +1314,7 @@ mod tests { - not(target_arch = "wasm32"), - not(target_arch = "asmjs") - ))] -+ #[ignore] // Requires unwinding - fn test_float_assertions() { - use super::SampleUniform; - use std::panic::catch_unwind; --- -2.20.1 - diff --git a/patches/0003-rand-Disable-rand-tests-on-mingw.patch b/patches/0003-rand-Disable-rand-tests-on-mingw.patch deleted file mode 100644 index eb452c5cd377..000000000000 --- a/patches/0003-rand-Disable-rand-tests-on-mingw.patch +++ /dev/null @@ -1,47 +0,0 @@ -From eec874c889b8d24e5ad50faded24288150f057b1 Mon Sep 17 00:00:00 2001 -From: Afonso Bordado -Date: Tue, 27 Sep 2022 08:13:58 +0100 -Subject: [PATCH] Disable rand tests on mingw - ---- - rand_distr/src/pareto.rs | 2 ++ - rand_distr/tests/value_stability.rs | 4 ++++ - 2 files changed, 6 insertions(+) - -diff --git a/rand_distr/src/pareto.rs b/rand_distr/src/pareto.rs -index 217899e..9cedeb7 100644 ---- a/rand_distr/src/pareto.rs -+++ b/rand_distr/src/pareto.rs -@@ -107,6 +107,8 @@ mod tests { - } - - #[test] -+ // This is broken on x86_64-pc-windows-gnu presumably due to a broken powf implementation -+ #[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)] - fn value_stability() { - fn test_samples>( - distr: D, thresh: F, expected: &[F], -diff --git a/rand_distr/tests/value_stability.rs b/rand_distr/tests/value_stability.rs -index 192ba74..0101ace 100644 ---- a/rand_distr/tests/value_stability.rs -+++ b/rand_distr/tests/value_stability.rs -@@ -72,6 +72,8 @@ fn unit_disc_stability() { - } - - #[test] -+// This is broken on x86_64-pc-windows-gnu -+#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)] - fn pareto_stability() { - test_samples(213, Pareto::new(1.0, 1.0).unwrap(), &[ - 1.0423688f32, 2.1235929, 4.132709, 1.4679428, -@@ -143,6 +145,8 @@ fn inverse_gaussian_stability() { - } - - #[test] -+// This is broken on x86_64-pc-windows-gnu -+#[cfg_attr(all(target_os = "windows", target_env = "gnu"), ignore)] - fn gamma_stability() { - // Gamma has 3 cases: shape == 1, shape < 1, shape > 1 - test_samples(223, Gamma::new(1.0, 5.0).unwrap(), &[ --- -2.25.1 diff --git a/patches/portable-simd-lock.toml b/patches/portable-simd-lock.toml deleted file mode 100644 index 5c9dc7b361f9..000000000000 --- a/patches/portable-simd-lock.toml +++ /dev/null @@ -1,304 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bumpalo" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "core_simd" -version = "0.1.0" -dependencies = [ - "proptest", - "std_float", - "test_helpers", - "wasm-bindgen", - "wasm-bindgen-test", -] - -[[package]] -name = "js-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "num-traits" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "proc-macro2" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12e6c80c1139113c28ee4670dc50cc42915228b51f56a9e407f0ec60f966646f" -dependencies = [ - "bitflags", - "byteorder", - "num-traits", - "rand", - "rand_chacha", - "rand_xorshift", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "rand_chacha", - "rand_core", - "rand_hc", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rand_xorshift" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77d416b86801d23dde1aa643023b775c3a462efc0ed96443add11546cdf1dca8" -dependencies = [ - "rand_core", -] - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "std_float" -version = "0.1.0" -dependencies = [ - "core_simd", -] - -[[package]] -name = "syn" -version = "2.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "test_helpers" -version = "0.1.0" -dependencies = [ - "proptest", -] - -[[package]] -name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "wasm-bindgen" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" - -[[package]] -name = "wasm-bindgen-test" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e6e302a7ea94f83a6d09e78e7dc7d9ca7b186bc2829c24a22d0753efd680671" -dependencies = [ - "console_error_panic_hook", - "js-sys", - "scoped-tls", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-bindgen-test-macro", -] - -[[package]] -name = "wasm-bindgen-test-macro" -version = "0.3.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecb993dd8c836930ed130e020e77d9b2e65dd0fbab1b67c790b0f5d80b11a575" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "web-sys" -version = "0.3.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" -dependencies = [ - "js-sys", - "wasm-bindgen", -] diff --git a/patches/stdlib-lock.toml b/patches/stdlib-lock.toml index de89c4f5eff8..f10b4d6b9d4f 100644 --- a/patches/stdlib-lock.toml +++ b/patches/stdlib-lock.toml @@ -174,9 +174,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.148" +version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" dependencies = [ "rustc-std-workspace-core", ] @@ -361,7 +361,6 @@ version = "0.0.0" dependencies = [ "addr2line", "alloc", - "cc", "cfg-if", "compiler_builtins", "core", diff --git a/rust-toolchain b/rust-toolchain index 86ef127badd4..3735ac1c17b1 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-10-09" +channel = "nightly-2023-10-21" components = ["rust-src", "rustc-dev", "llvm-tools"] diff --git a/scripts/setup_rust_fork.sh b/scripts/setup_rust_fork.sh index 60ac6bc9951e..3e48fb006dea 100644 --- a/scripts/setup_rust_fork.sh +++ b/scripts/setup_rust_fork.sh @@ -1,7 +1,10 @@ #!/usr/bin/env bash set -e -./y.sh build +# Compiletest expects all standard library paths to start with /rustc/FAKE_PREFIX. +# CG_CLIF_STDLIB_REMAP_PATH_PREFIX will cause cg_clif's build system to pass +# --remap-path-prefix to handle this. +CG_CLIF_STDLIB_REMAP_PATH_PREFIX=/rustc/FAKE_PREFIX ./y.sh build echo "[SETUP] Rust fork" git clone https://github.com/rust-lang/rust.git || true @@ -13,23 +16,6 @@ git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')" git -c user.name=Dummy -c user.email=dummy@example.com -c commit.gpgSign=false \ am ../patches/*-stdlib-*.patch -git apply - < config.toml < String { format!( - "cg_clif (rustc {}, cranelift {})", + "rustc version {} with cranelift {}", rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), cranelift_codegen::VERSION, ) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index 49f51f9f956b..d3a7decc5430 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -394,28 +394,31 @@ pub(crate) fn run_aot( let modules = tcx.sess.time("codegen mono items", || { cgus.iter() .enumerate() - .map(|(i, cgu)| match cgu_reuse[i] { - CguReuse::No => { - let dep_node = cgu.codegen_dep_node(tcx); - tcx.dep_graph - .with_task( - dep_node, - tcx, - ( - backend_config.clone(), - global_asm_config.clone(), - cgu.name(), - concurrency_limiter.acquire(tcx.sess.diagnostic()), - ), - module_codegen, - Some(rustc_middle::dep_graph::hash_result), - ) - .0 - } - CguReuse::PreLto => unreachable!("LTO not yet supported"), - CguReuse::PostLto => { - concurrency_limiter.job_already_done(); - OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu)) + .map(|(i, cgu)| { + let cgu_reuse = + if backend_config.disable_incr_cache { CguReuse::No } else { cgu_reuse[i] }; + match cgu_reuse { + CguReuse::No => { + let dep_node = cgu.codegen_dep_node(tcx); + tcx.dep_graph + .with_task( + dep_node, + tcx, + ( + backend_config.clone(), + global_asm_config.clone(), + cgu.name(), + concurrency_limiter.acquire(tcx.sess.diagnostic()), + ), + module_codegen, + Some(rustc_middle::dep_graph::hash_result), + ) + .0 + } + CguReuse::PreLto | CguReuse::PostLto => { + concurrency_limiter.job_already_done(); + OngoingModuleCodegen::Sync(reuse_workproduct_for_cgu(tcx, cgu)) + } } }) .collect::>() diff --git a/src/global_asm.rs b/src/global_asm.rs index ebd9b728d90b..6692d1b85eac 100644 --- a/src/global_asm.rs +++ b/src/global_asm.rs @@ -81,6 +81,10 @@ pub(crate) fn codegen_global_asm_item(tcx: TyCtxt<'_>, global_asm: &mut String, } } +pub(crate) fn asm_supported(tcx: TyCtxt<'_>) -> bool { + cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows +} + #[derive(Debug)] pub(crate) struct GlobalAsmConfig { asm_enabled: bool, @@ -90,10 +94,8 @@ pub(crate) struct GlobalAsmConfig { impl GlobalAsmConfig { pub(crate) fn new(tcx: TyCtxt<'_>) -> Self { - let asm_enabled = cfg!(feature = "inline_asm") && !tcx.sess.target.is_like_windows; - GlobalAsmConfig { - asm_enabled, + asm_enabled: asm_supported(tcx), assembler: crate::toolchain::get_toolchain_binary(tcx.sess, "as"), output_filenames: tcx.output_filenames(()).clone(), } diff --git a/src/inline_asm.rs b/src/inline_asm.rs index dd2127d554dd..ed0772342548 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -8,6 +8,7 @@ use rustc_span::sym; use rustc_target::asm::*; use target_lexicon::BinaryFormat; +use crate::global_asm::asm_supported; use crate::prelude::*; enum CInlineAsmOperand<'tcx> { @@ -44,9 +45,13 @@ pub(crate) fn codegen_inline_asm<'tcx>( ) { // FIXME add .eh_frame unwind info directives - if !template.is_empty() - && (cfg!(not(feature = "inline_asm")) || fx.tcx.sess.target.is_like_windows) - { + if !asm_supported(fx.tcx) { + if template.is_empty() { + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); + return; + } + // Used by panic_abort if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) { fx.bcx.ins().trap(TrapCode::User(1)); @@ -144,6 +149,16 @@ pub(crate) fn codegen_inline_asm<'tcx>( return; } + // Used by core::hint::spin_loop() + if template[0] + == InlineAsmTemplatePiece::String(".insn i 0x0F, 0, x0, x0, 0x010".to_string()) + && template.len() == 1 + { + let destination_block = fx.get_block(destination.unwrap()); + fx.bcx.ins().jump(destination_block, &[]); + return; + } + // Used by measureme if template[0] == InlineAsmTemplatePiece::String("xor %eax, %eax".to_string()) && template[1] == InlineAsmTemplatePiece::String("\n".to_string()) @@ -223,6 +238,16 @@ pub(crate) fn codegen_inline_asm<'tcx>( fx.bcx.ins().jump(destination_block, &[]); return; } + + if cfg!(not(feature = "inline_asm")) { + fx.tcx.sess.span_err( + span, + "asm! and global_asm! support is disabled while compiling rustc_codegen_cranelift", + ); + } else { + fx.tcx.sess.span_err(span, "asm! and global_asm! are not yet supported on Windows"); + } + return; } let operands = operands @@ -745,6 +770,13 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { // x19 is reserved by LLVM for the "base pointer", so rustc doesn't allow using it generated_asm.push_str(" mov x19, x0\n"); } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" addi sp, sp, -16\n"); + generated_asm.push_str(" sd ra, 8(sp)\n"); + generated_asm.push_str(" sd s1, 0(sp)\n"); // s1 is callee saved + // s1/x9 is reserved by LLVM for the "base pointer", so rustc doesn't allow using it + generated_asm.push_str(" mv s1, a0\n"); + } _ => unimplemented!("prologue for {:?}", arch), } } @@ -761,6 +793,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { generated_asm.push_str(" ldp fp, lr, [sp], #32\n"); generated_asm.push_str(" ret\n"); } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" ld s1, 0(sp)\n"); + generated_asm.push_str(" ld ra, 8(sp)\n"); + generated_asm.push_str(" addi sp, sp, 16\n"); + generated_asm.push_str(" ret\n"); + } _ => unimplemented!("epilogue for {:?}", arch), } } @@ -771,7 +809,10 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { generated_asm.push_str(" ud2\n"); } InlineAsmArch::AArch64 => { - generated_asm.push_str(" brk #0x1"); + generated_asm.push_str(" brk #0x1\n"); + } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" ebreak\n"); } _ => unimplemented!("epilogue_noreturn for {:?}", arch), } @@ -794,6 +835,11 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" sd "); + reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s1)", offset.bytes()).unwrap(); + } _ => unimplemented!("save_register for {:?}", arch), } } @@ -815,6 +861,11 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { reg.emit(generated_asm, InlineAsmArch::AArch64, None).unwrap(); writeln!(generated_asm, ", [x19, 0x{:x}]", offset.bytes()).unwrap(); } + InlineAsmArch::RiscV64 => { + generated_asm.push_str(" ld "); + reg.emit(generated_asm, InlineAsmArch::RiscV64, None).unwrap(); + writeln!(generated_asm, ", 0x{:x}(s1)", offset.bytes()).unwrap(); + } _ => unimplemented!("restore_register for {:?}", arch), } } diff --git a/src/lib.rs b/src/lib.rs index 8992de5a923f..148193b5a975 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ -#![cfg_attr(not(bootstrap), allow(internal_features))] -#![cfg_attr(not(bootstrap), feature(rustdoc_internals))] -#![cfg_attr(not(bootstrap), doc(rust_logo))] +#![cfg_attr(all(doc, not(bootstrap)), allow(internal_features))] +#![cfg_attr(all(doc, not(bootstrap)), feature(rustdoc_internals))] +#![cfg_attr(all(doc, not(bootstrap)), doc(rust_logo))] #![feature(rustc_private)] // Note: please avoid adding other feature gates where possible #![warn(rust_2018_idioms)] @@ -189,7 +189,7 @@ impl CodegenBackend for CraneliftCodegenBackend { } fn target_features(&self, _sess: &Session, _allow_unstable: bool) -> Vec { - vec![] + vec![] // FIXME necessary for #[cfg(target_feature] } fn print_version(&self) { From 38e8be9673c5a24a5f8282a0047499071598a370 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 22 Oct 2023 16:02:02 +0000 Subject: [PATCH 14/51] Add create_stack_slot helper to FunctionCx This will allow centrally handling a workaround for the lack of stack alignment specifier in cranelift. --- src/abi/mod.rs | 35 ++++++++++++++--------------------- src/abi/pass_mode.rs | 11 ++++------- src/cast.rs | 6 +----- src/common.rs | 10 ++++++++++ src/inline_asm.rs | 22 ++++++++++++---------- src/value_and_place.rs | 37 +++++++++++-------------------------- 6 files changed, 52 insertions(+), 69 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index c75ad852f82d..c4572e035258 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -120,32 +120,25 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { args: &[Value], ) -> Cow<'_, [Value]> { if self.tcx.sess.target.is_like_windows { - let (mut params, mut args): (Vec<_>, Vec<_>) = - params - .into_iter() - .zip(args) - .map(|(param, &arg)| { - if param.value_type == types::I128 { - let arg_ptr = Pointer::stack_slot(self.bcx.create_sized_stack_slot( - StackSlotData { kind: StackSlotKind::ExplicitSlot, size: 16 }, - )); - arg_ptr.store(self, arg, MemFlags::trusted()); - (AbiParam::new(self.pointer_type), arg_ptr.get_addr(self)) - } else { - (param, arg) - } - }) - .unzip(); + let (mut params, mut args): (Vec<_>, Vec<_>) = params + .into_iter() + .zip(args) + .map(|(param, &arg)| { + if param.value_type == types::I128 { + let arg_ptr = self.create_stack_slot(16, 16); + arg_ptr.store(self, arg, MemFlags::trusted()); + (AbiParam::new(self.pointer_type), arg_ptr.get_addr(self)) + } else { + (param, arg) + } + }) + .unzip(); let indirect_ret_val = returns.len() == 1 && returns[0].value_type == types::I128; if indirect_ret_val { params.insert(0, AbiParam::new(self.pointer_type)); - let ret_ptr = - Pointer::stack_slot(self.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - size: 16, - })); + let ret_ptr = self.create_stack_slot(16, 16); args.insert(0, ret_ptr.get_addr(self)); self.lib_call_unadjusted(name, params, vec![], &args); return Cow::Owned(vec![ret_ptr.load(self, types::I128, MemFlags::trusted())]); diff --git a/src/abi/pass_mode.rs b/src/abi/pass_mode.rs index 7c9f8c1051cb..065226700291 100644 --- a/src/abi/pass_mode.rs +++ b/src/abi/pass_mode.rs @@ -189,16 +189,13 @@ pub(super) fn from_casted_value<'tcx>( let abi_params = cast_target_to_abi_params(cast); let abi_param_size: u32 = abi_params.iter().map(|param| param.value_type.bytes()).sum(); let layout_size = u32::try_from(layout.size.bytes()).unwrap(); - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. + let ptr = fx.create_stack_slot( // Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`. // It may also be smaller for example when the type is a wrapper around an integer with a // larger alignment than the integer. - size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16, - }); - let ptr = Pointer::stack_slot(stack_slot); + std::cmp::max(abi_param_size, layout_size), + u32::try_from(layout.align.pref.bytes()).unwrap(), + ); let mut offset = 0; let mut block_params_iter = block_params.iter().copied(); for param in abi_params { diff --git a/src/cast.rs b/src/cast.rs index 7e027c5f1b30..0b5cb1547fc6 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -104,11 +104,7 @@ pub(crate) fn clif_int_or_float_cast( &[from], )[0]; // FIXME(bytecodealliance/wasmtime#6104) use bitcast instead of store to get from i64x2 to i128 - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - size: 16, - }); - let ret_ptr = Pointer::stack_slot(stack_slot); + let ret_ptr = fx.create_stack_slot(16, 16); ret_ptr.store(fx, ret, MemFlags::trusted()); ret_ptr.load(fx, types::I128, MemFlags::trusted()) } else { diff --git a/src/common.rs b/src/common.rs index 7a3ae6ebf52f..d306471e970b 100644 --- a/src/common.rs +++ b/src/common.rs @@ -383,6 +383,16 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { }) } + pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer { + let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to + // specify stack slot alignment. + size: (size + 15) / 16 * 16, + }); + Pointer::stack_slot(stack_slot) + } + pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) { if let Some(debug_context) = &mut self.cx.debug_context { let (file, line, column) = diff --git a/src/inline_asm.rs b/src/inline_asm.rs index ed0772342548..0517c609337b 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -878,13 +878,7 @@ fn call_inline_asm<'tcx>( inputs: Vec<(Size, Value)>, outputs: Vec<(Size, CPlace<'tcx>)>, ) { - let stack_slot = fx.bcx.func.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - size: u32::try_from(slot_size.bytes()).unwrap(), - }); - if fx.clif_comments.enabled() { - fx.add_comment(stack_slot, "inline asm scratch slot"); - } + let stack_slot = fx.create_stack_slot(u32::try_from(slot_size.bytes()).unwrap(), 16); let inline_asm_func = fx .module @@ -904,15 +898,23 @@ fn call_inline_asm<'tcx>( } for (offset, value) in inputs { - fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap()); + stack_slot.offset(fx, i32::try_from(offset.bytes()).unwrap().into()).store( + fx, + value, + MemFlags::trusted(), + ); } - let stack_slot_addr = fx.bcx.ins().stack_addr(fx.pointer_type, stack_slot, 0); + let stack_slot_addr = stack_slot.get_addr(fx); fx.bcx.ins().call(inline_asm_func, &[stack_slot_addr]); for (offset, place) in outputs { let ty = fx.clif_type(place.layout().ty).unwrap(); - let value = fx.bcx.ins().stack_load(ty, stack_slot, i32::try_from(offset.bytes()).unwrap()); + let value = stack_slot.offset(fx, i32::try_from(offset.bytes()).unwrap().into()).load( + fx, + ty, + MemFlags::trusted(), + ); place.write_cvalue(fx, CValue::by_val(value, place.layout())); } } diff --git a/src/value_and_place.rs b/src/value_and_place.rs index 3a6a6c9e3f50..5f0aa6c5581d 100644 --- a/src/value_and_place.rs +++ b/src/value_and_place.rs @@ -132,18 +132,11 @@ impl<'tcx> CValue<'tcx> { (ptr.get_addr(fx), vtable) } CValueInner::ByValPair(data, vtable) => { - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (u32::try_from(fx.target_config.pointer_type().bytes()).unwrap() + 15) - / 16 - * 16, - }); - let data_ptr = Pointer::stack_slot(stack_slot); - let mut flags = MemFlags::new(); - flags.set_notrap(); - data_ptr.store(fx, data, flags); + let data_ptr = fx.create_stack_slot( + u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(), + u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(), + ); + data_ptr.store(fx, data, MemFlags::trusted()); (data_ptr.get_addr(fx), vtable) } @@ -372,13 +365,11 @@ impl<'tcx> CPlace<'tcx> { .fatal(format!("values of type {} are too big to store on the stack", layout.ty)); } - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (u32::try_from(layout.size.bytes()).unwrap() + 15) / 16 * 16, - }); - CPlace { inner: CPlaceInner::Addr(Pointer::stack_slot(stack_slot), None), layout } + let stack_slot = fx.create_stack_slot( + u32::try_from(layout.size.bytes()).unwrap(), + u32::try_from(layout.align.pref.bytes()).unwrap(), + ); + CPlace { inner: CPlaceInner::Addr(stack_slot, None), layout } } pub(crate) fn new_var( @@ -543,13 +534,7 @@ impl<'tcx> CPlace<'tcx> { _ if src_ty.is_vector() && dst_ty.is_vector() => codegen_bitcast(fx, dst_ty, data), _ if src_ty.is_vector() || dst_ty.is_vector() => { // FIXME(bytecodealliance/wasmtime#6104) do something more efficient for transmutes between vectors and integers. - let stack_slot = fx.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (src_ty.bytes() + 15) / 16 * 16, - }); - let ptr = Pointer::stack_slot(stack_slot); + let ptr = fx.create_stack_slot(src_ty.bytes(), src_ty.bytes()); ptr.store(fx, data, MemFlags::trusted()); ptr.load(fx, dst_ty, MemFlags::trusted()) } From 55380a5ffd72bb2ab601e911409cdd092a2740d9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 22 Oct 2023 17:11:11 +0000 Subject: [PATCH 15/51] Dynamically realign local variables with large alignment This works around the lack of a way to specify the alignment of a stack slot in Cranelift. Fixes #1230 Fixes #1381 --- example/mini_core_hello_world.rs | 11 +++++++++++ src/common.rs | 29 ++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 58670b33c7bd..3e4edcf6f541 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -353,6 +353,17 @@ fn main() { let f = V([0.0, 1.0]); let _a = f.0[0]; + + stack_val_align(); +} + +#[inline(never)] +fn stack_val_align() { + #[repr(align(8192))] + struct Foo(u8); + + let a = Foo(0); + assert_eq!(&a as *const Foo as usize % 8192, 0); } #[cfg(all( diff --git a/src/common.rs b/src/common.rs index d306471e970b..7a0b04c09cc8 100644 --- a/src/common.rs +++ b/src/common.rs @@ -384,13 +384,28 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer { - let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to - // specify stack slot alignment. - size: (size + 15) / 16 * 16, - }); - Pointer::stack_slot(stack_slot) + if align <= 16 { + let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to + // specify stack slot alignment. + size: (size + 15) / 16 * 16, + }); + Pointer::stack_slot(stack_slot) + } else { + // Alignment is too big to handle using the above hack. Dynamically realign a stack slot + // instead. This wastes some space for the realignment. + let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { + kind: StackSlotKind::ExplicitSlot, + // FIXME is this calculation to ensure there is enough space to dyanmically realign + // as well as keep a 16 byte realignment for the other stack slots correct? + size: ((size + align - 1) + 16) / 16 * 16, + }); + let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0); + let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align)); + let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align)); + Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset)) + } } pub(crate) fn set_debug_loc(&mut self, source_info: mir::SourceInfo) { From 56c6c86661498c61a0f877e43c9e6aa928882fa1 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 22 Oct 2023 18:10:59 +0000 Subject: [PATCH 16/51] Simplify FunctionCx::create_stack_slot a bit --- src/common.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/common.rs b/src/common.rs index 7a0b04c09cc8..9771f44f62cf 100644 --- a/src/common.rs +++ b/src/common.rs @@ -395,13 +395,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { } else { // Alignment is too big to handle using the above hack. Dynamically realign a stack slot // instead. This wastes some space for the realignment. - let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData { - kind: StackSlotKind::ExplicitSlot, - // FIXME is this calculation to ensure there is enough space to dyanmically realign - // as well as keep a 16 byte realignment for the other stack slots correct? - size: ((size + align - 1) + 16) / 16 * 16, - }); - let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0); + let base_ptr = self.create_stack_slot(size + align, 16).get_addr(self); let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align)); let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align)); Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset)) From 7c4fcd41653e04e6b368830e84e234422c9c61ed Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 22 Oct 2023 22:45:03 +0200 Subject: [PATCH 17/51] Update readme for the move to the rust-lang org --- Readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 6f2027be96de..5664cbe7d4fa 100644 --- a/Readme.md +++ b/Readme.md @@ -8,7 +8,7 @@ If not please open an issue. ## Building and testing ```bash -$ git clone https://github.com/bjorn3/rustc_codegen_cranelift +$ git clone https://github.com/rust-lang/rustc_codegen_cranelift $ cd rustc_codegen_cranelift $ ./y.sh prepare $ ./y.sh build @@ -29,7 +29,7 @@ Extract the `dist` directory in the archive anywhere you want. If you want to use `cargo clif build` instead of having to specify the full path to the `cargo-clif` executable, you can add the `bin` subdirectory of the extracted `dist` directory to your `PATH`. (tutorial [for Windows](https://stackoverflow.com/a/44272417), and [for Linux/MacOS](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path/26059#26059)). -[releases]: https://github.com/bjorn3/rustc_codegen_cranelift/releases/tag/dev +[releases]: https://github.com/rust-lang/rustc_codegen_cranelift/releases/tag/dev ## Usage @@ -78,7 +78,7 @@ configuration options. * Inline assembly ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1041)) * On UNIX there is support for invoking an external assembler for `global_asm!` and `asm!`. -* SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported) +* SIMD ([tracked here](https://github.com/rust-lang/rustc_codegen_cranelift/issues/171), `std::simd` fully works, `std::arch` is partially supported) * Unwinding on panics ([no cranelift support](https://github.com/bytecodealliance/wasmtime/issues/1677), `-Cpanic=abort` is enabled by default) ## License From ed8c515cc43870497f5c11efa239a32dd89c9174 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 23 Oct 2023 09:32:55 +0000 Subject: [PATCH 18/51] Avoid collect_and_partition_mono_items call when not doing codegen Fixes #1401 --- src/driver/aot.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/driver/aot.rs b/src/driver/aot.rs index d3a7decc5430..11229dd421ec 100644 --- a/src/driver/aot.rs +++ b/src/driver/aot.rs @@ -361,12 +361,26 @@ pub(crate) fn run_aot( metadata: EncodedMetadata, need_metadata_module: bool, ) -> Box { + // FIXME handle `-Ctarget-cpu=native` + let target_cpu = match tcx.sess.opts.cg.target_cpu { + Some(ref name) => name, + None => tcx.sess.target.cpu.as_ref(), + } + .to_owned(); + let cgus = if tcx.sess.opts.output_types.should_codegen() { tcx.collect_and_partition_mono_items(()).1 } else { // If only `--emit metadata` is used, we shouldn't perform any codegen. // Also `tcx.collect_and_partition_mono_items` may panic in that case. - &[] + return Box::new(OngoingCodegen { + modules: vec![], + allocator_module: None, + metadata_module: None, + metadata, + crate_info: CrateInfo::new(tcx, target_cpu), + concurrency_limiter: ConcurrencyLimiter::new(tcx.sess, 0), + }); }; if tcx.dep_graph.is_fully_enabled() { @@ -481,13 +495,6 @@ pub(crate) fn run_aot( None }; - // FIXME handle `-Ctarget-cpu=native` - let target_cpu = match tcx.sess.opts.cg.target_cpu { - Some(ref name) => name, - None => tcx.sess.target.cpu.as_ref(), - } - .to_owned(); - Box::new(OngoingCodegen { modules, allocator_module, From e5ba1e84171899aa99b4ba6c1b5d4eef3873592a Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 23 Oct 2023 14:06:47 +0200 Subject: [PATCH 19/51] Implement llvm intrinsics necessary for rav1e Fixes #1399 --- src/intrinsics/llvm_x86.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index 0c9a94e1c231..ea790277863f 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -310,6 +310,40 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( let val = CValue::by_val_pair(cb_out, c, layout); ret.write_cvalue(fx, val); } + "llvm.x86.sse2.pavg.b" | "llvm.x86.sse2.pavg.w" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + // FIXME use vector instructions when possible + simd_pair_for_each_lane( + fx, + a, + b, + ret, + &|fx, _lane_ty, _res_lane_ty, a_lane, b_lane| { + // (a + b + 1) >> 1 + let lane_ty = fx.bcx.func.dfg.value_type(a_lane); + let a_lane = fx.bcx.ins().uextend(lane_ty.double_width().unwrap(), a_lane); + let b_lane = fx.bcx.ins().uextend(lane_ty.double_width().unwrap(), b_lane); + let sum = fx.bcx.ins().iadd(a_lane, b_lane); + let num_plus_one = fx.bcx.ins().iadd_imm(sum, 1); + let res = fx.bcx.ins().ushr_imm(num_plus_one, 1); + fx.bcx.ins().ireduce(lane_ty, res) + }, + ); + } + "llvm.x86.sse2.psra.w" => { + intrinsic_args!(fx, args => (a, count); intrinsic); + + let count_lane = count.force_stack(fx).0.load(fx, types::I64, MemFlags::trusted()); + let lane_ty = fx.clif_type(a.layout().ty.simd_size_and_type(fx.tcx).1).unwrap(); + let max_count = fx.bcx.ins().iconst(types::I64, i64::from(lane_ty.bits() - 1)); + let saturated_count = fx.bcx.ins().umin(count_lane, max_count); + + // FIXME use vector instructions when possible + simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, a_lane| { + fx.bcx.ins().sshr(a_lane, saturated_count) + }); + } _ => { fx.tcx .sess From 0d780b108b007c6232ab3cbba8c47822edbbbddd Mon Sep 17 00:00:00 2001 From: GoodDaisy <90915921+GoodDaisy@users.noreply.github.com> Date: Mon, 23 Oct 2023 20:29:24 +0800 Subject: [PATCH 20/51] fix typos in comments --- compiler/rustc_const_eval/src/interpret/eval_context.rs | 2 +- library/core/src/num/mod.rs | 2 +- src/doc/unstable-book/src/compiler-flags/check-cfg.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 791370660fe9..3e764daa6626 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1010,7 +1010,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Just make this an efficient immediate. // Note that not calling `layout_of` here does have one real consequence: // if the type is too big, we'll only notice this when the local is actually initialized, - // which is a bit too late -- we should ideally notice this alreayd here, when the memory + // which is a bit too late -- we should ideally notice this already here, when the memory // is conceptually allocated. But given how rare that error is and that this is a hot function, // we accept this downside for now. Operand::Immediate(Immediate::Uninit) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 8b127132c1ca..a6c1adfac655 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -114,7 +114,7 @@ macro_rules! midpoint_impl { without modifying the original"] #[inline] pub const fn midpoint(self, rhs: $SelfT) -> $SelfT { - // Use the well known branchless algorthim from Hacker's Delight to compute + // Use the well known branchless algorithm from Hacker's Delight to compute // `(a + b) / 2` without overflowing: `((a ^ b) >> 1) + (a & b)`. ((self ^ rhs) >> 1) + (self & rhs) } diff --git a/src/doc/unstable-book/src/compiler-flags/check-cfg.md b/src/doc/unstable-book/src/compiler-flags/check-cfg.md index ca18ec567a4f..7a3ef5e9e2be 100644 --- a/src/doc/unstable-book/src/compiler-flags/check-cfg.md +++ b/src/doc/unstable-book/src/compiler-flags/check-cfg.md @@ -123,7 +123,7 @@ rustc --check-cfg 'cfg(is_embedded, has_feathers, values(any()))' \ fn do_embedded() {} // and because names exhaustiveness was not disabled #[cfg(has_feathers)] // This is expected as "has_feathers" was provided in cfg() -fn do_features() {} // and because names exhaustiveness was not disbaled +fn do_features() {} // and because names exhaustiveness was not disabled #[cfg(has_feathers = "zapping")] // This is expected as "has_feathers" was provided in cfg() // and because no value checking was enable for "has_feathers" From efd30810835ab0117d53f78534a63afc0ebed0e2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:24:46 +0000 Subject: [PATCH 21/51] Update rust-analyzer config --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 60cb51d56636..834a1362caf3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -33,7 +33,7 @@ ] }, { - "sysroot_src": "./download/sysroot/sysroot_src/library", + "sysroot_src": "./build/stdlib/library", "crates": [ { "root_module": "./example/std_example.rs", From a558968dbe962b1daa730426d001becebd102931 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 23 Oct 2023 14:10:22 +0000 Subject: [PATCH 22/51] Implement all llvm intrinsics necessary for the image crate Fixes #1379 --- src/intrinsics/llvm_x86.rs | 103 +++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/src/intrinsics/llvm_x86.rs b/src/intrinsics/llvm_x86.rs index ea790277863f..35f144d7dad4 100644 --- a/src/intrinsics/llvm_x86.rs +++ b/src/intrinsics/llvm_x86.rs @@ -344,6 +344,109 @@ pub(crate) fn codegen_x86_llvm_intrinsic_call<'tcx>( fx.bcx.ins().sshr(a_lane, saturated_count) }); } + "llvm.x86.sse2.psad.bw" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.u8); + assert_eq!(ret_lane_ty, fx.tcx.types.u64); + assert_eq!(lane_count, ret_lane_count * 8); + + let ret_lane_layout = fx.layout_of(fx.tcx.types.u64); + for out_lane_idx in 0..lane_count / 8 { + let mut lane_diff_acc = fx.bcx.ins().iconst(types::I64, 0); + + for lane_idx in out_lane_idx * 8..out_lane_idx * 8 + 1 { + let a_lane = a.value_lane(fx, lane_idx).load_scalar(fx); + let b_lane = b.value_lane(fx, lane_idx).load_scalar(fx); + + let lane_diff = fx.bcx.ins().isub(a_lane, b_lane); + let abs_lane_diff = fx.bcx.ins().iabs(lane_diff); + let abs_lane_diff = fx.bcx.ins().uextend(types::I64, abs_lane_diff); + lane_diff_acc = fx.bcx.ins().iadd(lane_diff_acc, abs_lane_diff); + } + + let res_lane = CValue::by_val(lane_diff_acc, ret_lane_layout); + + ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); + } + } + "llvm.x86.ssse3.pmadd.ub.sw.128" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + let (lane_count, lane_ty) = a.layout().ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.u8); + assert_eq!(ret_lane_ty, fx.tcx.types.i16); + assert_eq!(lane_count, ret_lane_count * 2); + + let ret_lane_layout = fx.layout_of(fx.tcx.types.i16); + for out_lane_idx in 0..lane_count / 2 { + let a_lane0 = a.value_lane(fx, out_lane_idx * 2).load_scalar(fx); + let a_lane0 = fx.bcx.ins().uextend(types::I16, a_lane0); + let b_lane0 = b.value_lane(fx, out_lane_idx * 2).load_scalar(fx); + let b_lane0 = fx.bcx.ins().sextend(types::I16, b_lane0); + + let a_lane1 = a.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); + let a_lane1 = fx.bcx.ins().uextend(types::I16, a_lane1); + let b_lane1 = b.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); + let b_lane1 = fx.bcx.ins().sextend(types::I16, b_lane1); + + let mul0: Value = fx.bcx.ins().imul(a_lane0, b_lane0); + let mul1 = fx.bcx.ins().imul(a_lane1, b_lane1); + + let (val, has_overflow) = fx.bcx.ins().sadd_overflow(mul0, mul1); + + let rhs_ge_zero = fx.bcx.ins().icmp_imm(IntCC::SignedGreaterThanOrEqual, mul1, 0); + + let min = fx.bcx.ins().iconst(types::I16, i64::from(i16::MIN as u16)); + let max = fx.bcx.ins().iconst(types::I16, i64::from(i16::MAX as u16)); + + let sat_val = fx.bcx.ins().select(rhs_ge_zero, max, min); + let res_lane = fx.bcx.ins().select(has_overflow, sat_val, val); + + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); + } + } + "llvm.x86.sse2.pmadd.wd" => { + intrinsic_args!(fx, args => (a, b); intrinsic); + + assert_eq!(a.layout(), b.layout()); + let layout = a.layout(); + + let (lane_count, lane_ty) = layout.ty.simd_size_and_type(fx.tcx); + let (ret_lane_count, ret_lane_ty) = ret.layout().ty.simd_size_and_type(fx.tcx); + assert_eq!(lane_ty, fx.tcx.types.i16); + assert_eq!(ret_lane_ty, fx.tcx.types.i32); + assert_eq!(lane_count, ret_lane_count * 2); + + let ret_lane_layout = fx.layout_of(fx.tcx.types.i32); + for out_lane_idx in 0..lane_count / 2 { + let a_lane0 = a.value_lane(fx, out_lane_idx * 2).load_scalar(fx); + let a_lane0 = fx.bcx.ins().uextend(types::I32, a_lane0); + let b_lane0 = b.value_lane(fx, out_lane_idx * 2).load_scalar(fx); + let b_lane0 = fx.bcx.ins().sextend(types::I32, b_lane0); + + let a_lane1 = a.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); + let a_lane1 = fx.bcx.ins().uextend(types::I32, a_lane1); + let b_lane1 = b.value_lane(fx, out_lane_idx * 2 + 1).load_scalar(fx); + let b_lane1 = fx.bcx.ins().sextend(types::I32, b_lane1); + + let mul0: Value = fx.bcx.ins().imul(a_lane0, b_lane0); + let mul1 = fx.bcx.ins().imul(a_lane1, b_lane1); + + let res_lane = fx.bcx.ins().iadd(mul0, mul1); + let res_lane = CValue::by_val(res_lane, ret_lane_layout); + + ret.place_lane(fx, out_lane_idx).write_cvalue(fx, res_lane); + } + } _ => { fx.tcx .sess From c1fb05cdf2442da42a1f28ba9fb5bc4adfac3875 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 23 Oct 2023 13:00:51 -0400 Subject: [PATCH 23/51] Update books --- src/doc/book | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/book b/src/doc/book index 72187f5cd0be..3dca2fc50b92 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 72187f5cd0beaaa9c6f584156bcd88f921871e83 +Subproject commit 3dca2fc50b922a8efb94903b9fee8bb42ab48f38 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index eac173690b8c..22bca3d0f6e9 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit eac173690b8cc99094e1d88bd49dd61127fbd285 +Subproject commit 22bca3d0f6e9b9b556689b54ce96f25b46ecd1b3 diff --git a/src/doc/nomicon b/src/doc/nomicon index ddfa42144876..184225781491 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit ddfa4214487686e91b21aa29afb972c08a8f0d5b +Subproject commit 1842257814919fa62e81bdecd5e8f95be2839dbb diff --git a/src/doc/reference b/src/doc/reference index 142b2ed77d33..16fd3c06d9e5 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 142b2ed77d33f37a9973772bd95e6144ed9dce43 +Subproject commit 16fd3c06d9e558dae2d52000818274ae70c9e90a diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 8eb3a01ab74c..6709beeb7d0f 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 8eb3a01ab74c567b7174784892fb807f2c632d6b +Subproject commit 6709beeb7d0fbc5ffc91ac4893a24434123b9bfa diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index b98af7d661e4..b0ee9ec8fa59 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit b98af7d661e4744baab81fb8dc7a049e44a4a998 +Subproject commit b0ee9ec8fa59a6c7620165e061f4747202377a62 From 66a554b04539a1319c68b3d52c7c3e027208dfec Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Fri, 20 Oct 2023 23:05:38 -0700 Subject: [PATCH 24/51] Add method to convert internal to stable constructs --- Cargo.lock | 1 + compiler/rustc_smir/Cargo.toml | 1 + compiler/rustc_smir/src/rustc_internal/mod.rs | 58 ++++- compiler/rustc_smir/src/rustc_smir/mod.rs | 206 +++++++++++------- compiler/stable_mir/src/lib.rs | 52 ++--- 5 files changed, 197 insertions(+), 121 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f8d566c2d15..d0422340c525 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4524,6 +4524,7 @@ dependencies = [ "rustc_middle", "rustc_span", "rustc_target", + "scoped-tls", "stable_mir", "tracing", ] diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 41c7d3a85943..47dd7372f3d1 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -9,6 +9,7 @@ rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } +scoped-tls = "1.0" stable_mir = {path = "../stable_mir" } tracing = "0.1" diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index f7e519570fa5..7bec946788b3 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -3,7 +3,7 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until stable MIR is complete. -use crate::rustc_smir::Tables; +use crate::rustc_smir::{Stable, Tables, TablesWrapper}; use rustc_data_structures::fx; use rustc_data_structures::fx::FxIndexMap; use rustc_middle::mir::interpret::AllocId; @@ -11,13 +11,21 @@ use rustc_middle::ty; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::Span; +use scoped_tls::scoped_thread_local; use stable_mir::ty::IndexedVal; +use std::cell::Cell; +use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::ops::Index; +use std::rc::Rc; mod internal; +pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { + with_tables(|tables| item.stable(tables)) +} + impl<'tcx> Index for Tables<'tcx> { type Output = DefId; @@ -125,18 +133,44 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { item.id.into() } +// A thread local variable that stores a pointer to the tables mapping between TyCtxt +// datastructures and stable MIR datastructures +scoped_thread_local! (static TLV: Cell<*const ()>); + +pub(crate) fn init<'tcx>(tables: TablesWrapper<'tcx>, f: impl FnOnce()) { + assert!(!TLV.is_set()); + fn g<'a, 'tcx>(context: &'a TablesWrapper<'tcx>, f: impl FnOnce()) { + let ptr: *const () = &context as *const &_ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); + } + g(&tables, f); +} + +/// Loads the current context and calls a function with it. +/// Do not nest these, as that will ICE. +pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R { + assert!(TLV.is_set()); + TLV.with(|tlv| { + let ptr = tlv.get(); + assert!(!ptr.is_null()); + let wrapper = unsafe { *(ptr as *const &TablesWrapper<'tcx>) }; + let mut tables = wrapper.0.borrow_mut(); + f(&mut *tables) + }) +} + pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { - stable_mir::run( - Tables { - tcx, - def_ids: IndexMap::default(), - alloc_ids: IndexMap::default(), - spans: IndexMap::default(), - types: vec![], - instances: IndexMap::default(), - }, - f, - ); + let tables = Rc::new(RefCell::new(Tables { + tcx, + def_ids: IndexMap::default(), + alloc_ids: IndexMap::default(), + spans: IndexMap::default(), + types: vec![], + instances: IndexMap::default(), + })); + stable_mir::run(TablesWrapper(Rc::clone(&tables)), || init(TablesWrapper(tables), f)); } #[macro_export] diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index d5379797f1c6..19ad9898db16 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -23,27 +23,31 @@ use stable_mir::ty::{ FloatTy, GenericParamDef, IntTy, LineInfo, Movability, RigidTy, Span, TyKind, UintTy, }; use stable_mir::{self, opaque, Context, Filename}; +use std::cell::RefCell; use tracing::debug; mod alloc; mod builder; -impl<'tcx> Context for Tables<'tcx> { +impl<'tcx> Context for TablesWrapper<'tcx> { fn local_crate(&self) -> stable_mir::Crate { - smir_crate(self.tcx, LOCAL_CRATE) + let tables = self.0.borrow(); + smir_crate(tables.tcx, LOCAL_CRATE) } fn external_crates(&self) -> Vec { - self.tcx.crates(()).iter().map(|crate_num| smir_crate(self.tcx, *crate_num)).collect() + let tables = self.0.borrow(); + tables.tcx.crates(()).iter().map(|crate_num| smir_crate(tables.tcx, *crate_num)).collect() } fn find_crates(&self, name: &str) -> Vec { + let tables = self.0.borrow(); let crates: Vec = [LOCAL_CRATE] .iter() - .chain(self.tcx.crates(()).iter()) + .chain(tables.tcx.crates(()).iter()) .map(|crate_num| { - let crate_name = self.tcx.crate_name(*crate_num).to_string(); - (name == crate_name).then(|| smir_crate(self.tcx, *crate_num)) + let crate_name = tables.tcx.crate_name(*crate_num).to_string(); + (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num)) }) .into_iter() .filter_map(|c| c) @@ -52,163 +56,197 @@ impl<'tcx> Context for Tables<'tcx> { } fn name_of_def_id(&self, def_id: stable_mir::DefId) -> String { - self.tcx.def_path_str(self[def_id]) + let tables = self.0.borrow(); + tables.tcx.def_path_str(tables[def_id]) } fn span_to_string(&self, span: stable_mir::ty::Span) -> String { - self.tcx.sess.source_map().span_to_diagnostic_string(self[span]) + let tables = self.0.borrow(); + tables.tcx.sess.source_map().span_to_diagnostic_string(tables[span]) } fn get_filename(&self, span: &Span) -> Filename { + let tables = self.0.borrow(); opaque( - &self + &tables .tcx .sess .source_map() - .span_to_filename(self[*span]) + .span_to_filename(tables[*span]) .display(rustc_span::FileNameDisplayPreference::Local) .to_string(), ) } fn get_lines(&self, span: &Span) -> LineInfo { - let lines = &self.tcx.sess.source_map().span_to_location_info(self[*span]); + let tables = self.0.borrow(); + let lines = &tables.tcx.sess.source_map().span_to_location_info(tables[*span]); LineInfo { start_line: lines.1, start_col: lines.2, end_line: lines.3, end_col: lines.4 } } - fn def_kind(&mut self, def_id: stable_mir::DefId) -> stable_mir::DefKind { - self.tcx.def_kind(self[def_id]).stable(self) + fn def_kind(&self, def_id: stable_mir::DefId) -> stable_mir::DefKind { + let mut tables = self.0.borrow_mut(); + tables.tcx.def_kind(tables[def_id]).stable(&mut *tables) } - fn span_of_an_item(&mut self, def_id: stable_mir::DefId) -> Span { - self.tcx.def_span(self[def_id]).stable(self) + fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span { + let mut tables = self.0.borrow_mut(); + tables.tcx.def_span(tables[def_id]).stable(&mut *tables) } - fn all_local_items(&mut self) -> stable_mir::CrateItems { - self.tcx.mir_keys(()).iter().map(|item| self.crate_item(item.to_def_id())).collect() + fn all_local_items(&self) -> stable_mir::CrateItems { + let mut tables = self.0.borrow_mut(); + tables.tcx.mir_keys(()).iter().map(|item| tables.crate_item(item.to_def_id())).collect() } - fn entry_fn(&mut self) -> Option { - Some(self.crate_item(self.tcx.entry_fn(())?.0)) + fn entry_fn(&self) -> Option { + let mut tables = self.0.borrow_mut(); + let tcx = tables.tcx; + Some(tables.crate_item(tcx.entry_fn(())?.0)) } - fn all_trait_decls(&mut self) -> stable_mir::TraitDecls { - self.tcx + fn all_trait_decls(&self) -> stable_mir::TraitDecls { + let mut tables = self.0.borrow_mut(); + tables + .tcx .traits(LOCAL_CRATE) .iter() - .map(|trait_def_id| self.trait_def(*trait_def_id)) + .map(|trait_def_id| tables.trait_def(*trait_def_id)) .collect() } - fn trait_decl(&mut self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl { - let def_id = self[trait_def.0]; - let trait_def = self.tcx.trait_def(def_id); - trait_def.stable(self) + fn trait_decl(&self, trait_def: &stable_mir::ty::TraitDef) -> stable_mir::ty::TraitDecl { + let mut tables = self.0.borrow_mut(); + let def_id = tables[trait_def.0]; + let trait_def = tables.tcx.trait_def(def_id); + trait_def.stable(&mut *tables) } - fn all_trait_impls(&mut self) -> stable_mir::ImplTraitDecls { - self.tcx + fn all_trait_impls(&self) -> stable_mir::ImplTraitDecls { + let mut tables = self.0.borrow_mut(); + tables + .tcx .trait_impls_in_crate(LOCAL_CRATE) .iter() - .map(|impl_def_id| self.impl_def(*impl_def_id)) + .map(|impl_def_id| tables.impl_def(*impl_def_id)) .collect() } - fn trait_impl(&mut self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait { - let def_id = self[impl_def.0]; - let impl_trait = self.tcx.impl_trait_ref(def_id).unwrap(); - impl_trait.stable(self) + fn trait_impl(&self, impl_def: &stable_mir::ty::ImplDef) -> stable_mir::ty::ImplTrait { + let mut tables = self.0.borrow_mut(); + let def_id = tables[impl_def.0]; + let impl_trait = tables.tcx.impl_trait_ref(def_id).unwrap(); + impl_trait.stable(&mut *tables) } - fn mir_body(&mut self, item: stable_mir::DefId) -> stable_mir::mir::Body { - let def_id = self[item]; - self.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(self) + fn mir_body(&self, item: stable_mir::DefId) -> stable_mir::mir::Body { + let mut tables = self.0.borrow_mut(); + let def_id = tables[item]; + tables.tcx.instance_mir(ty::InstanceDef::Item(def_id)).stable(&mut tables) } - fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind { - self.types[ty.0].clone().stable(self) + fn ty_kind(&self, ty: stable_mir::ty::Ty) -> TyKind { + let mut tables = self.0.borrow_mut(); + tables.types[ty.0].clone().stable(&mut *tables) } - fn mk_ty(&mut self, kind: TyKind) -> stable_mir::ty::Ty { - let n = self.types.len(); - self.types.push(MaybeStable::Stable(kind)); + fn mk_ty(&self, kind: TyKind) -> stable_mir::ty::Ty { + let mut tables = self.0.borrow_mut(); + let n = tables.types.len(); + tables.types.push(MaybeStable::Stable(kind)); stable_mir::ty::Ty(n) } - fn generics_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics { - let def_id = self[def_id]; - let generics = self.tcx.generics_of(def_id); - generics.stable(self) + fn generics_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::Generics { + let mut tables = self.0.borrow_mut(); + let def_id = tables[def_id]; + let generics = tables.tcx.generics_of(def_id); + generics.stable(&mut *tables) } - fn predicates_of(&mut self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates { - let def_id = self[def_id]; - let ty::GenericPredicates { parent, predicates } = self.tcx.predicates_of(def_id); + fn predicates_of(&self, def_id: stable_mir::DefId) -> stable_mir::ty::GenericPredicates { + let mut tables = self.0.borrow_mut(); + let def_id = tables[def_id]; + let ty::GenericPredicates { parent, predicates } = tables.tcx.predicates_of(def_id); stable_mir::ty::GenericPredicates { - parent: parent.map(|did| self.trait_def(did)), + parent: parent.map(|did| tables.trait_def(did)), predicates: predicates .iter() .map(|(clause, span)| { - (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self)) + ( + clause.as_predicate().kind().skip_binder().stable(&mut *tables), + span.stable(&mut *tables), + ) }) .collect(), } } fn explicit_predicates_of( - &mut self, + &self, def_id: stable_mir::DefId, ) -> stable_mir::ty::GenericPredicates { - let def_id = self[def_id]; - let ty::GenericPredicates { parent, predicates } = self.tcx.explicit_predicates_of(def_id); + let mut tables = self.0.borrow_mut(); + let def_id = tables[def_id]; + let ty::GenericPredicates { parent, predicates } = + tables.tcx.explicit_predicates_of(def_id); stable_mir::ty::GenericPredicates { - parent: parent.map(|did| self.trait_def(did)), + parent: parent.map(|did| tables.trait_def(did)), predicates: predicates .iter() .map(|(clause, span)| { - (clause.as_predicate().kind().skip_binder().stable(self), span.stable(self)) + ( + clause.as_predicate().kind().skip_binder().stable(&mut *tables), + span.stable(&mut *tables), + ) }) .collect(), } } - fn instance_body(&mut self, def: InstanceDef) -> Body { - let instance = self.instances[def]; - builder::BodyBuilder::new(self.tcx, instance).build(self) + fn instance_body(&self, def: InstanceDef) -> Body { + let mut tables = self.0.borrow_mut(); + let instance = tables.instances[def]; + builder::BodyBuilder::new(tables.tcx, instance).build(&mut *tables) } - fn instance_ty(&mut self, def: InstanceDef) -> stable_mir::ty::Ty { - let instance = self.instances[def]; - let ty = instance.ty(self.tcx, ParamEnv::empty()); - self.intern_ty(ty) + fn instance_ty(&self, def: InstanceDef) -> stable_mir::ty::Ty { + let mut tables = self.0.borrow_mut(); + let instance = tables.instances[def]; + let ty = instance.ty(tables.tcx, ParamEnv::empty()); + tables.intern_ty(ty) } - fn instance_def_id(&mut self, def: InstanceDef) -> stable_mir::DefId { - let def_id = self.instances[def].def_id(); - self.create_def_id(def_id) + fn instance_def_id(&self, def: InstanceDef) -> stable_mir::DefId { + let mut tables = self.0.borrow_mut(); + let def_id = tables.instances[def].def_id(); + tables.create_def_id(def_id) } - fn mono_instance(&mut self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance { - let def_id = self[item.0]; - Instance::mono(self.tcx, def_id).stable(self) + fn mono_instance(&self, item: stable_mir::CrateItem) -> stable_mir::mir::mono::Instance { + let mut tables = self.0.borrow_mut(); + let def_id = tables[item.0]; + Instance::mono(tables.tcx, def_id).stable(&mut *tables) } fn requires_monomorphization(&self, def_id: stable_mir::DefId) -> bool { - let def_id = self[def_id]; - let generics = self.tcx.generics_of(def_id); - let result = generics.requires_monomorphization(self.tcx); + let tables = self.0.borrow(); + let def_id = tables[def_id]; + let generics = tables.tcx.generics_of(def_id); + let result = generics.requires_monomorphization(tables.tcx); result } fn resolve_instance( - &mut self, + &self, def: stable_mir::ty::FnDef, args: &stable_mir::ty::GenericArgs, ) -> Option { - let def_id = def.0.internal(self); - let args_ref = args.internal(self); - match Instance::resolve(self.tcx, ParamEnv::reveal_all(), def_id, args_ref) { - Ok(Some(instance)) => Some(instance.stable(self)), + let mut tables = self.0.borrow_mut(); + let def_id = def.0.internal(&mut *tables); + let args_ref = args.internal(&mut *tables); + match Instance::resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) { + Ok(Some(instance)) => Some(instance.stable(&mut *tables)), Ok(None) | Err(_) => None, } } @@ -241,13 +279,15 @@ impl PartialEq for MaybeStable { } } +pub(crate) struct TablesWrapper<'tcx>(pub(crate) std::rc::Rc>>); + pub struct Tables<'tcx> { - pub tcx: TyCtxt<'tcx>, - pub def_ids: IndexMap, - pub alloc_ids: IndexMap, - pub spans: IndexMap, - pub types: Vec>>, - pub instances: IndexMap, InstanceDef>, + pub(crate) tcx: TyCtxt<'tcx>, + pub(crate) def_ids: IndexMap, + pub(crate) alloc_ids: IndexMap, + pub(crate) spans: IndexMap, + pub(crate) types: Vec>>, + pub(crate) instances: IndexMap, InstanceDef>, } impl<'tcx> Tables<'tcx> { @@ -270,7 +310,7 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { } /// Trait used to convert between an internal MIR type to a Stable MIR type. -pub(crate) trait Stable<'tcx> { +pub trait Stable<'tcx> { /// The stable representation of the type implementing Stable. type T; /// Converts an object to the equivalent Stable MIR representation. diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index be5ccac78c7c..512c3fc62964 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -175,17 +175,17 @@ pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait { } pub trait Context { - fn entry_fn(&mut self) -> Option; + fn entry_fn(&self) -> Option; /// Retrieve all items of the local crate that have a MIR associated with them. - fn all_local_items(&mut self) -> CrateItems; - fn mir_body(&mut self, item: DefId) -> mir::Body; - fn all_trait_decls(&mut self) -> TraitDecls; - fn trait_decl(&mut self, trait_def: &TraitDef) -> TraitDecl; - fn all_trait_impls(&mut self) -> ImplTraitDecls; - fn trait_impl(&mut self, trait_impl: &ImplDef) -> ImplTrait; - fn generics_of(&mut self, def_id: DefId) -> Generics; - fn predicates_of(&mut self, def_id: DefId) -> GenericPredicates; - fn explicit_predicates_of(&mut self, def_id: DefId) -> GenericPredicates; + fn all_local_items(&self) -> CrateItems; + fn mir_body(&self, item: DefId) -> mir::Body; + fn all_trait_decls(&self) -> TraitDecls; + fn trait_decl(&self, trait_def: &TraitDef) -> TraitDecl; + fn all_trait_impls(&self) -> ImplTraitDecls; + fn trait_impl(&self, trait_impl: &ImplDef) -> ImplTrait; + fn generics_of(&self, def_id: DefId) -> Generics; + fn predicates_of(&self, def_id: DefId) -> GenericPredicates; + fn explicit_predicates_of(&self, def_id: DefId) -> GenericPredicates; /// Get information about the local crate. fn local_crate(&self) -> Crate; /// Retrieve a list of all external crates. @@ -207,61 +207,61 @@ pub trait Context { fn get_lines(&self, span: &Span) -> LineInfo; /// Returns the `kind` of given `DefId` - fn def_kind(&mut self, def_id: DefId) -> DefKind; + fn def_kind(&self, def_id: DefId) -> DefKind; /// `Span` of an item - fn span_of_an_item(&mut self, def_id: DefId) -> Span; + fn span_of_an_item(&self, def_id: DefId) -> Span; /// Obtain the representation of a type. - fn ty_kind(&mut self, ty: Ty) -> TyKind; + fn ty_kind(&self, ty: Ty) -> TyKind; /// Create a new `Ty` from scratch without information from rustc. - fn mk_ty(&mut self, kind: TyKind) -> Ty; + fn mk_ty(&self, kind: TyKind) -> Ty; /// Get the body of an Instance. /// FIXME: Monomorphize the body. - fn instance_body(&mut self, instance: InstanceDef) -> Body; + fn instance_body(&self, instance: InstanceDef) -> Body; /// Get the instance type with generic substitutions applied and lifetimes erased. - fn instance_ty(&mut self, instance: InstanceDef) -> Ty; + fn instance_ty(&self, instance: InstanceDef) -> Ty; /// Get the instance. - fn instance_def_id(&mut self, instance: InstanceDef) -> DefId; + fn instance_def_id(&self, instance: InstanceDef) -> DefId; /// Convert a non-generic crate item into an instance. /// This function will panic if the item is generic. - fn mono_instance(&mut self, item: CrateItem) -> Instance; + fn mono_instance(&self, item: CrateItem) -> Instance; /// Item requires monomorphization. fn requires_monomorphization(&self, def_id: DefId) -> bool; /// Resolve an instance from the given function definition and generic arguments. - fn resolve_instance(&mut self, def: FnDef, args: &GenericArgs) -> Option; + fn resolve_instance(&self, def: FnDef, args: &GenericArgs) -> Option; } // A thread local variable that stores a pointer to the tables mapping between TyCtxt // datastructures and stable MIR datastructures -scoped_thread_local! (static TLV: Cell<*mut ()>); +scoped_thread_local! (static TLV: Cell<*const ()>); -pub fn run(mut context: impl Context, f: impl FnOnce()) { +pub fn run(context: impl Context, f: impl FnOnce()) { assert!(!TLV.is_set()); - fn g<'a>(mut context: &mut (dyn Context + 'a), f: impl FnOnce()) { - let ptr: *mut () = &mut context as *mut &mut _ as _; + fn g<'a>(context: &(dyn Context + 'a), f: impl FnOnce()) { + let ptr: *const () = &context as *const &_ as _; TLV.set(&Cell::new(ptr), || { f(); }); } - g(&mut context, f); + g(&context, f); } /// Loads the current context and calls a function with it. /// Do not nest these, as that will ICE. -pub fn with(f: impl FnOnce(&mut dyn Context) -> R) -> R { +pub fn with(f: impl FnOnce(&dyn Context) -> R) -> R { assert!(TLV.is_set()); TLV.with(|tlv| { let ptr = tlv.get(); assert!(!ptr.is_null()); - f(unsafe { *(ptr as *mut &mut dyn Context) }) + f(unsafe { *(ptr as *const &dyn Context) }) }) } From 93a5433f17ab5ed48cc88f1e69b0713b16183373 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 23 Oct 2023 19:06:04 +0000 Subject: [PATCH 25/51] Update Cranelift to 0.101.1 This patch release fixes an ABI incompatibility with LLVM. Fixes #1395 --- Cargo.lock | 52 +++++++++---------- Cargo.toml | 12 ++--- ...h-gets-miscompiled-with-llvm-sysroot.patch | 25 --------- 3 files changed, 32 insertions(+), 57 deletions(-) delete mode 100644 patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch diff --git a/Cargo.lock b/Cargo.lock index 8079913cb0ff..c716d5011731 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,18 +45,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cranelift-bforest" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5e1df0da8488dd03b34afc134ba84b754d61862cc465932a9e5d07952f661e" +checksum = "c1512c3bb6b13018e7109fc3ac964bc87b329eaf3a77825d337558d0c7f6f1be" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a17ca4e699a0aaf49a0c88f6311a864f321048aa63f6b787cab20eb5f93f10" +checksum = "16cb8fb9220a6ea7a226705a273ab905309ee546267bdf34948d57932d7f0396" dependencies = [ "bumpalo", "cranelift-bforest", @@ -75,39 +75,39 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "022f2793cdade1d37a1f755ac42938a3f832f533eac6cafc8b26b209544c3c06" +checksum = "ab3a8d3b0d4745b183da5ea0792b13d79f5c23d6e69ac04761728e2532b56649" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4d72dbb83c2ad788dec4ad0843070973cb48c35a3ca19b1e7437ac40834fd9c" +checksum = "524141c8e68f2abc2043de4c2b31f6d9dd42432738c246431d0572a1422a4a84" [[package]] name = "cranelift-control" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae07cf26dcc90d546826d747ac63b6c40c916f34b03e92a6ae0422c28d771b8a" +checksum = "97513b57c961c713789a03886a57b43e14ebcd204cbaa8ae50ca6c70a8e716b3" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2fe6b7e49820893691aea497f36257e9d6f52061d8c4758d61d802d5f101a3d" +checksum = "e3f23d3cf3afa7e45f239702612c76d87964f652a55e28d13ed6d7e20f3479dd" [[package]] name = "cranelift-frontend" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44f497576ca3674581581601b6a55ccc1b43447217648c880e5bce70db3cf659" +checksum = "554cd4947ec9209b58bf9ae5bf83581b5ddf9128bd967208e334b504a57db54e" dependencies = [ "cranelift-codegen", "log", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b96aa02eac00fffee13b0cd37d17874ccdb3d5458983041accd825ef78ce6454" +checksum = "6c1892a439696b6413cb54083806f5fd9fc431768b8de74864b3d9e8b93b124f" [[package]] name = "cranelift-jit" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1d6e0e308c873eefc185745a6b21daec2a10f7554c9fb67e334c2d7d756d979" +checksum = "32209252fb38acaf1662ccd0397907bbe0e92bdb13b6ddbfd2f74e437f83e685" dependencies = [ "anyhow", "cranelift-codegen", @@ -143,9 +143,9 @@ dependencies = [ [[package]] name = "cranelift-module" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1aa8ebb06eced4e478c3f94f1d65d4e7c93493f4640057912b27a3e34b84841" +checksum = "bf42656f5f6df7bfafc4dd7b63a1888b0627c07b43b2cb9aa54e13843fed39eb" dependencies = [ "anyhow", "cranelift-codegen", @@ -154,9 +154,9 @@ dependencies = [ [[package]] name = "cranelift-native" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2870170ca44054b202c737626607b87be6e35655084bd94a6ff807a5812ba7df" +checksum = "e0c2d3badd4b9690865f5bb68a71fa94de592fa2df3f3d11a5a062c60c0a107a" dependencies = [ "cranelift-codegen", "libc", @@ -165,9 +165,9 @@ dependencies = [ [[package]] name = "cranelift-object" -version = "0.101.0" +version = "0.101.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20647761742d17dabac8205da958910ede78599550e06418a16711a3ee2fc897" +checksum = "88eca54bbecea3170035168357306e9c779d4a63d8bf036c9e16bd21fdaa69b5" dependencies = [ "anyhow", "cranelift-codegen", @@ -374,9 +374,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasmtime-jit-icache-coherence" -version = "14.0.0" +version = "14.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a5dda53ad6993f9b0a2d65fb49e0348a7232a27a8794064122870d6ee19eb2" +checksum = "9aaf2fa8fd2d6b65abae9b92edfe69254cc5d6b166e342364036c3e347de8da9" dependencies = [ "cfg-if", "libc", diff --git a/Cargo.toml b/Cargo.toml index 5ad5e0e8140c..f2ce714e8ff1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,12 @@ crate-type = ["dylib"] [dependencies] # These have to be in sync with each other -cranelift-codegen = { version = "0.101", features = ["unwind", "all-arch"] } -cranelift-frontend = { version = "0.101" } -cranelift-module = { version = "0.101" } -cranelift-native = { version = "0.101" } -cranelift-jit = { version = "0.101", optional = true } -cranelift-object = { version = "0.101" } +cranelift-codegen = { version = "0.101.1", features = ["unwind", "all-arch"] } +cranelift-frontend = { version = "0.101.1" } +cranelift-module = { version = "0.101.1" } +cranelift-native = { version = "0.101.1" } +cranelift-jit = { version = "0.101.1", optional = true } +cranelift-object = { version = "0.101.1" } target-lexicon = "0.12.0" gimli = { version = "0.28", default-features = false, features = ["write"]} object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] } diff --git a/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch b/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch deleted file mode 100644 index e6ebdcec783a..000000000000 --- a/patches/0001-regex-Ignore-test-which-gets-miscompiled-with-llvm-sysroot.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 5d4afb8d807d181038b6a004d17ed055a8d191b2 Mon Sep 17 00:00:00 2001 -From: bjorn3 <17426603+bjorn3@users.noreply.github.com> -Date: Mon, 2 Oct 2023 13:59:00 +0000 -Subject: [PATCH] Ignore test which gets miscompiled with llvm sysroot - ---- - regex-automata/src/util/pool.rs | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/regex-automata/src/util/pool.rs b/regex-automata/src/util/pool.rs -index c03d7b0..28b233b 100644 ---- a/regex-automata/src/util/pool.rs -+++ b/regex-automata/src/util/pool.rs -@@ -1081,6 +1081,8 @@ mod tests { - // into the pool. This in turn resulted in this test producing a data race. - #[cfg(feature = "std")] - #[test] -+ // FIXME(rustc_codegen_cranelift#1395) miscompilation of thread::scope with LLVM sysroot -+ #[ignore] - fn thread_owner_sync() { - let pool = Pool::new(|| vec!['a']); - { --- -2.34.1 - From f613b26cfbfea5d7b1afbbad57be8e5774669775 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 23 Oct 2023 12:02:17 -0700 Subject: [PATCH 26/51] Add `internal()` method counterpart to `stable()` Note: We do not expect to provide internalizing methods for all StableMIR constructs. They exist only to help migrating efforts to allow users to mix StableMIR and internal constructs. --- compiler/rustc_smir/src/rustc_internal/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 7bec946788b3..58cdcd49087e 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -26,6 +26,10 @@ pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { with_tables(|tables| item.stable(tables)) } +pub unsafe fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { + with_tables(|tables| item.internal(tables)) +} + impl<'tcx> Index for Tables<'tcx> { type Output = DefId; @@ -285,7 +289,7 @@ impl Index { +pub trait RustcInternal<'tcx> { type T; fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T; } From 895134291192ca28d156131baa6340fbf48a16f2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 20 Oct 2023 21:30:52 -0700 Subject: [PATCH 27/51] Naming nits --- compiler/rustc_middle/src/ty/list.rs | 4 +- .../rustc_middle/src/ty/structural_impls.rs | 44 +++++++++---------- compiler/rustc_middle/src/ty/sty.rs | 4 +- compiler/rustc_type_ir/src/const_kind.rs | 6 +-- compiler/rustc_type_ir/src/debug.rs | 36 +++++++-------- compiler/rustc_type_ir/src/region_kind.rs | 6 +-- compiler/rustc_type_ir/src/ty_kind.rs | 10 ++--- 7 files changed, 55 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 7a32cfb10857..66463efd287d 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -121,8 +121,8 @@ impl fmt::Debug for List { } } impl<'tcx, T: super::DebugWithInfcx>> super::DebugWithInfcx> for List { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { fmt::Debug::fmt(&this.map(|this| this.as_slice()), f) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 012bb7494128..0fedc0e3cf8d 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -93,8 +93,8 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { } } impl<'tcx> DebugWithInfcx> for ty::FnSig<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { let sig = this.data; @@ -149,8 +149,8 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { } impl<'tcx> ty::DebugWithInfcx> for Ty<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { this.data.fmt(f) @@ -242,8 +242,8 @@ impl<'tcx> fmt::Debug for AliasTy<'tcx> { } } impl<'tcx> DebugWithInfcx> for AliasTy<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { f.debug_struct("AliasTy") @@ -263,8 +263,8 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> { } } impl<'tcx> DebugWithInfcx> for ty::InferConst<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { use ty::InferConst::*; @@ -287,8 +287,8 @@ impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> { } } impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { match this.data { @@ -320,8 +320,8 @@ impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> { } } impl<'tcx> DebugWithInfcx> for ty::UnevaluatedConst<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { f.debug_struct("UnevaluatedConst") @@ -337,8 +337,8 @@ impl<'tcx> fmt::Debug for ty::Const<'tcx> { } } impl<'tcx> DebugWithInfcx> for ty::Const<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { // If this is a value, we spend some effort to make it look nice. @@ -395,8 +395,8 @@ impl<'tcx> fmt::Debug for GenericArg<'tcx> { } } impl<'tcx> DebugWithInfcx> for GenericArg<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { match this.data.unpack() { @@ -413,8 +413,8 @@ impl<'tcx> fmt::Debug for Region<'tcx> { } } impl<'tcx> DebugWithInfcx> for Region<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { write!(f, "{:?}", &this.map(|data| data.kind())) @@ -422,8 +422,8 @@ impl<'tcx> DebugWithInfcx> for Region<'tcx> { } impl<'tcx> DebugWithInfcx> for ty::RegionVid { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { match this.infcx.and_then(|infcx| infcx.universe_of_lt(*this.data)) { @@ -434,8 +434,8 @@ impl<'tcx> DebugWithInfcx> for ty::RegionVid { } impl<'tcx, T: DebugWithInfcx>> DebugWithInfcx> for ty::Binder<'tcx, T> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { f.debug_tuple("Binder") diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 46aa5d950cb1..e76f256fdaac 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -683,8 +683,8 @@ pub enum ExistentialPredicate<'tcx> { } impl<'tcx> DebugWithInfcx> for ExistentialPredicate<'tcx> { - fn fmt>>( - this: rustc_type_ir::OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>, + fn fmt>>( + this: rustc_type_ir::OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { fmt::Debug::fmt(&this.data, f) diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index f84841c9f645..8139aacd8658 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -231,13 +231,13 @@ impl Clone for ConstKind { impl fmt::Debug for ConstKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - OptWithInfcx::new_no_ctx(self).fmt(f) + OptWithInfcx::with_no_infcx(self).fmt(f) } } impl DebugWithInfcx for ConstKind { - fn fmt>( - this: OptWithInfcx<'_, I, InfCtx, &Self>, + fn fmt>( + this: OptWithInfcx<'_, I, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { use ConstKind::*; diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index 7c6a78469007..556576eef00c 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -26,15 +26,15 @@ impl InferCtxtLike for core::convert::Infallible { } pub trait DebugWithInfcx: fmt::Debug { - fn fmt>( - this: OptWithInfcx<'_, I, InfCtx, &Self>, + fn fmt>( + this: OptWithInfcx<'_, I, Infcx, &Self>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result; } impl + ?Sized> DebugWithInfcx for &'_ T { - fn fmt>( - this: OptWithInfcx<'_, I, InfCtx, &Self>, + fn fmt>( + this: OptWithInfcx<'_, I, Infcx, &Self>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { >::fmt(this.map(|&data| data), f) @@ -42,8 +42,8 @@ impl + ?Sized> DebugWithInfcx for &'_ T { } impl> DebugWithInfcx for [T] { - fn fmt>( - this: OptWithInfcx<'_, I, InfCtx, &Self>, + fn fmt>( + this: OptWithInfcx<'_, I, Infcx, &Self>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { match f.alternate() { @@ -70,46 +70,46 @@ impl> DebugWithInfcx for [T] { } } -pub struct OptWithInfcx<'a, I: Interner, InfCtx: InferCtxtLike, T> { +pub struct OptWithInfcx<'a, I: Interner, Infcx: InferCtxtLike, T> { pub data: T, - pub infcx: Option<&'a InfCtx>, + pub infcx: Option<&'a Infcx>, _interner: PhantomData, } -impl, T: Copy> Copy for OptWithInfcx<'_, I, InfCtx, T> {} +impl, T: Copy> Copy for OptWithInfcx<'_, I, Infcx, T> {} -impl, T: Clone> Clone for OptWithInfcx<'_, I, InfCtx, T> { +impl, T: Clone> Clone for OptWithInfcx<'_, I, Infcx, T> { fn clone(&self) -> Self { Self { data: self.data.clone(), infcx: self.infcx, _interner: self._interner } } } impl<'a, I: Interner, T> OptWithInfcx<'a, I, core::convert::Infallible, T> { - pub fn new_no_ctx(data: T) -> Self { + pub fn with_no_infcx(data: T) -> Self { Self { data, infcx: None, _interner: PhantomData } } } -impl<'a, I: Interner, InfCtx: InferCtxtLike, T> OptWithInfcx<'a, I, InfCtx, T> { - pub fn new(data: T, infcx: &'a InfCtx) -> Self { +impl<'a, I: Interner, Infcx: InferCtxtLike, T> OptWithInfcx<'a, I, Infcx, T> { + pub fn new(data: T, infcx: &'a Infcx) -> Self { Self { data, infcx: Some(infcx), _interner: PhantomData } } - pub fn wrap(self, u: U) -> OptWithInfcx<'a, I, InfCtx, U> { + pub fn wrap(self, u: U) -> OptWithInfcx<'a, I, Infcx, U> { OptWithInfcx { data: u, infcx: self.infcx, _interner: PhantomData } } - pub fn map(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, InfCtx, U> { + pub fn map(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, Infcx, U> { OptWithInfcx { data: f(self.data), infcx: self.infcx, _interner: PhantomData } } - pub fn as_ref(&self) -> OptWithInfcx<'a, I, InfCtx, &T> { + pub fn as_ref(&self) -> OptWithInfcx<'a, I, Infcx, &T> { OptWithInfcx { data: &self.data, infcx: self.infcx, _interner: PhantomData } } } -impl, T: DebugWithInfcx> fmt::Debug - for OptWithInfcx<'_, I, InfCtx, T> +impl, T: DebugWithInfcx> fmt::Debug + for OptWithInfcx<'_, I, Infcx, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { DebugWithInfcx::fmt(self.as_ref(), f) diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 0006eec4d300..18b31949285d 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -274,8 +274,8 @@ impl hash::Hash for RegionKind { } impl DebugWithInfcx for RegionKind { - fn fmt>( - this: OptWithInfcx<'_, I, InfCtx, &Self>, + fn fmt>( + this: OptWithInfcx<'_, I, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { match this.data { @@ -301,7 +301,7 @@ impl DebugWithInfcx for RegionKind { } impl fmt::Debug for RegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - OptWithInfcx::new_no_ctx(self).fmt(f) + OptWithInfcx::with_no_infcx(self).fmt(f) } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 91bfce9a142f..3f7171a816b0 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -534,8 +534,8 @@ impl hash::Hash for TyKind { } impl DebugWithInfcx for TyKind { - fn fmt>( - this: OptWithInfcx<'_, I, InfCtx, &Self>, + fn fmt>( + this: OptWithInfcx<'_, I, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> fmt::Result { match this.data { @@ -617,7 +617,7 @@ impl DebugWithInfcx for TyKind { // This is manually implemented because a derive would require `I: Debug` impl fmt::Debug for TyKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - OptWithInfcx::new_no_ctx(self).fmt(f) + OptWithInfcx::with_no_infcx(self).fmt(f) } } @@ -1239,8 +1239,8 @@ impl fmt::Debug for InferTy { } impl> DebugWithInfcx for InferTy { - fn fmt>( - this: OptWithInfcx<'_, I, InfCtx, &Self>, + fn fmt>( + this: OptWithInfcx<'_, I, Infcx, &Self>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { use InferTy::*; From 269d5a322e35490513612ba1ed1afd80a982cfe7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 20 Oct 2023 22:10:58 -0700 Subject: [PATCH 28/51] Remove redundant type parameter --- compiler/rustc_infer/src/infer/mod.rs | 4 +- compiler/rustc_middle/src/ty/list.rs | 6 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- .../rustc_middle/src/ty/structural_impls.rs | 60 +++++++-------- compiler/rustc_middle/src/ty/sty.rs | 4 +- compiler/rustc_type_ir/src/const_kind.rs | 10 +-- compiler/rustc_type_ir/src/debug.rs | 73 +++++++++++-------- compiler/rustc_type_ir/src/lib.rs | 2 +- compiler/rustc_type_ir/src/region_kind.rs | 10 +-- compiler/rustc_type_ir/src/ty_kind.rs | 14 ++-- 10 files changed, 98 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 8ffcf1fce9cf..2198a15d99d4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -341,7 +341,9 @@ pub struct InferCtxt<'tcx> { next_trait_solver: bool, } -impl<'tcx> ty::InferCtxtLike> for InferCtxt<'tcx> { +impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { + type Interner = TyCtxt<'tcx>; + fn universe_of_ty(&self, ty: ty::InferTy) -> Option { use InferTy::*; match ty { diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 66463efd287d..4f9c9d85763a 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -1,7 +1,7 @@ use crate::arena::Arena; use rustc_data_structures::aligned::{align_of, Aligned}; use rustc_serialize::{Encodable, Encoder}; -use rustc_type_ir::{InferCtxtLike, OptWithInfcx}; +use rustc_type_ir::{InferCtxtLike, WithInfcx}; use std::alloc::Layout; use std::cmp::Ordering; use std::fmt; @@ -121,8 +121,8 @@ impl fmt::Debug for List { } } impl<'tcx, T: super::DebugWithInfcx>> super::DebugWithInfcx> for List { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { fmt::Debug::fmt(&this.map(|this| this.as_slice()), f) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9b0ceb23e3ea..91211a048a00 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -54,7 +54,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, ExpnKind, Span}; use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx}; pub use rustc_target::abi::{ReprFlags, ReprOptions}; -pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, OptWithInfcx}; +pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, WithInfcx}; pub use vtable::*; use std::fmt::Debug; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 0fedc0e3cf8d..101c6dd4f9a2 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -10,7 +10,7 @@ use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; use rustc_target::abi::TyAndLayout; -use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, OptWithInfcx}; +use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx}; use std::fmt::{self, Debug}; use std::ops::ControlFlow; @@ -89,12 +89,12 @@ impl fmt::Debug for ty::FreeRegion { impl<'tcx> fmt::Debug for ty::FnSig<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - OptWithInfcx::new_no_ctx(self).fmt(f) + WithInfcx::with_no_infcx(self).fmt(f) } } impl<'tcx> DebugWithInfcx> for ty::FnSig<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { let sig = this.data; @@ -149,8 +149,8 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { } impl<'tcx> ty::DebugWithInfcx> for Ty<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { this.data.fmt(f) @@ -238,12 +238,12 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> { impl<'tcx> fmt::Debug for AliasTy<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - OptWithInfcx::new_no_ctx(self).fmt(f) + WithInfcx::with_no_infcx(self).fmt(f) } } impl<'tcx> DebugWithInfcx> for AliasTy<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { f.debug_struct("AliasTy") @@ -263,12 +263,12 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> { } } impl<'tcx> DebugWithInfcx> for ty::InferConst<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { use ty::InferConst::*; - match this.infcx.and_then(|infcx| infcx.universe_of_ct(*this.data)) { + match this.infcx.universe_of_ct(*this.data) { None => write!(f, "{:?}", this.data), Some(universe) => match *this.data { Var(vid) => write!(f, "?{}_{}c", vid.index, universe.index()), @@ -283,12 +283,12 @@ impl<'tcx> DebugWithInfcx> for ty::InferConst<'tcx> { impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - OptWithInfcx::new_no_ctx(self).fmt(f) + WithInfcx::with_no_infcx(self).fmt(f) } } impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { match this.data { @@ -316,12 +316,12 @@ impl<'tcx> DebugWithInfcx> for ty::consts::Expr<'tcx> { impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - OptWithInfcx::new_no_ctx(self).fmt(f) + WithInfcx::with_no_infcx(self).fmt(f) } } impl<'tcx> DebugWithInfcx> for ty::UnevaluatedConst<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { f.debug_struct("UnevaluatedConst") @@ -333,12 +333,12 @@ impl<'tcx> DebugWithInfcx> for ty::UnevaluatedConst<'tcx> { impl<'tcx> fmt::Debug for ty::Const<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - OptWithInfcx::new_no_ctx(self).fmt(f) + WithInfcx::with_no_infcx(self).fmt(f) } } impl<'tcx> DebugWithInfcx> for ty::Const<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { // If this is a value, we spend some effort to make it look nice. @@ -395,8 +395,8 @@ impl<'tcx> fmt::Debug for GenericArg<'tcx> { } } impl<'tcx> DebugWithInfcx> for GenericArg<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { match this.data.unpack() { @@ -413,8 +413,8 @@ impl<'tcx> fmt::Debug for Region<'tcx> { } } impl<'tcx> DebugWithInfcx> for Region<'tcx> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { write!(f, "{:?}", &this.map(|data| data.kind())) @@ -422,11 +422,11 @@ impl<'tcx> DebugWithInfcx> for Region<'tcx> { } impl<'tcx> DebugWithInfcx> for ty::RegionVid { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { - match this.infcx.and_then(|infcx| infcx.universe_of_lt(*this.data)) { + match this.infcx.universe_of_lt(*this.data) { Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()), None => write!(f, "{:?}", this.data), } @@ -434,8 +434,8 @@ impl<'tcx> DebugWithInfcx> for ty::RegionVid { } impl<'tcx, T: DebugWithInfcx>> DebugWithInfcx> for ty::Binder<'tcx, T> { - fn fmt>>( - this: OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { f.debug_tuple("Binder") diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e76f256fdaac..f93a23158fb0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -683,8 +683,8 @@ pub enum ExistentialPredicate<'tcx> { } impl<'tcx> DebugWithInfcx> for ExistentialPredicate<'tcx> { - fn fmt>>( - this: rustc_type_ir::OptWithInfcx<'_, TyCtxt<'tcx>, Infcx, &Self>, + fn fmt>>( + this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { fmt::Debug::fmt(&this.data, f) diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 8139aacd8658..fbd403c82c6f 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -5,8 +5,8 @@ use std::fmt; use std::hash; use crate::{ - DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, OptWithInfcx, - TyDecoder, TyEncoder, + DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder, + TyEncoder, WithInfcx, }; use self::ConstKind::*; @@ -231,13 +231,13 @@ impl Clone for ConstKind { impl fmt::Debug for ConstKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - OptWithInfcx::with_no_infcx(self).fmt(f) + WithInfcx::with_no_infcx(self).fmt(f) } } impl DebugWithInfcx for ConstKind { - fn fmt>( - this: OptWithInfcx<'_, I, Infcx, &Self>, + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { use ConstKind::*; diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index 556576eef00c..4ea3eb3e84f4 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -3,38 +3,48 @@ use crate::{Interner, UniverseIndex}; use core::fmt; use std::marker::PhantomData; -pub trait InferCtxtLike { - fn universe_of_ty(&self, ty: I::InferTy) -> Option; +pub trait InferCtxtLike { + type Interner: Interner; - fn universe_of_lt(&self, lt: I::InferRegion) -> Option; + fn universe_of_ty(&self, ty: ::InferTy) -> Option; - fn universe_of_ct(&self, ct: I::InferConst) -> Option; + fn universe_of_lt( + &self, + lt: ::InferRegion, + ) -> Option; + + fn universe_of_ct(&self, ct: ::InferConst) + -> Option; } -impl InferCtxtLike for core::convert::Infallible { +pub struct NoInfcx(PhantomData); + +impl InferCtxtLike for NoInfcx { + type Interner = I; + fn universe_of_ty(&self, _ty: ::InferTy) -> Option { - match *self {} + None } fn universe_of_ct(&self, _ct: ::InferConst) -> Option { - match *self {} + None } fn universe_of_lt(&self, _lt: ::InferRegion) -> Option { - match *self {} + None } } pub trait DebugWithInfcx: fmt::Debug { - fn fmt>( - this: OptWithInfcx<'_, I, Infcx, &Self>, + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result; } impl + ?Sized> DebugWithInfcx for &'_ T { - fn fmt>( - this: OptWithInfcx<'_, I, Infcx, &Self>, + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { >::fmt(this.map(|&data| data), f) @@ -42,8 +52,8 @@ impl + ?Sized> DebugWithInfcx for &'_ T { } impl> DebugWithInfcx for [T] { - fn fmt>( - this: OptWithInfcx<'_, I, Infcx, &Self>, + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { match f.alternate() { @@ -70,46 +80,45 @@ impl> DebugWithInfcx for [T] { } } -pub struct OptWithInfcx<'a, I: Interner, Infcx: InferCtxtLike, T> { +pub struct WithInfcx<'a, Infcx: InferCtxtLike, T> { pub data: T, - pub infcx: Option<&'a Infcx>, - _interner: PhantomData, + pub infcx: &'a Infcx, } -impl, T: Copy> Copy for OptWithInfcx<'_, I, Infcx, T> {} +impl Copy for WithInfcx<'_, Infcx, T> {} -impl, T: Clone> Clone for OptWithInfcx<'_, I, Infcx, T> { +impl Clone for WithInfcx<'_, Infcx, T> { fn clone(&self) -> Self { - Self { data: self.data.clone(), infcx: self.infcx, _interner: self._interner } + Self { data: self.data.clone(), infcx: self.infcx } } } -impl<'a, I: Interner, T> OptWithInfcx<'a, I, core::convert::Infallible, T> { +impl<'a, I: Interner, T> WithInfcx<'a, NoInfcx, T> { pub fn with_no_infcx(data: T) -> Self { - Self { data, infcx: None, _interner: PhantomData } + Self { data, infcx: &NoInfcx(PhantomData) } } } -impl<'a, I: Interner, Infcx: InferCtxtLike, T> OptWithInfcx<'a, I, Infcx, T> { +impl<'a, Infcx: InferCtxtLike, T> WithInfcx<'a, Infcx, T> { pub fn new(data: T, infcx: &'a Infcx) -> Self { - Self { data, infcx: Some(infcx), _interner: PhantomData } + Self { data, infcx } } - pub fn wrap(self, u: U) -> OptWithInfcx<'a, I, Infcx, U> { - OptWithInfcx { data: u, infcx: self.infcx, _interner: PhantomData } + pub fn wrap(self, u: U) -> WithInfcx<'a, Infcx, U> { + WithInfcx { data: u, infcx: self.infcx } } - pub fn map(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, Infcx, U> { - OptWithInfcx { data: f(self.data), infcx: self.infcx, _interner: PhantomData } + pub fn map(self, f: impl FnOnce(T) -> U) -> WithInfcx<'a, Infcx, U> { + WithInfcx { data: f(self.data), infcx: self.infcx } } - pub fn as_ref(&self) -> OptWithInfcx<'a, I, Infcx, &T> { - OptWithInfcx { data: &self.data, infcx: self.infcx, _interner: PhantomData } + pub fn as_ref(&self) -> WithInfcx<'a, Infcx, &T> { + WithInfcx { data: &self.data, infcx: self.infcx } } } -impl, T: DebugWithInfcx> fmt::Debug - for OptWithInfcx<'_, I, Infcx, T> +impl> fmt::Debug + for WithInfcx<'_, Infcx, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { DebugWithInfcx::fmt(self.as_ref(), f) diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index d4ca9da96e4e..1ff220f3ed6b 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -34,7 +34,7 @@ mod region_kind; pub use codec::*; pub use const_kind::*; -pub use debug::{DebugWithInfcx, InferCtxtLike, OptWithInfcx}; +pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx}; pub use flags::*; pub use interner::*; pub use region_kind::*; diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index 18b31949285d..23e575cbc375 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -5,8 +5,8 @@ use std::fmt; use std::hash; use crate::{ - DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, OptWithInfcx, - TyDecoder, TyEncoder, + DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, TyDecoder, + TyEncoder, WithInfcx, }; use self::RegionKind::*; @@ -274,8 +274,8 @@ impl hash::Hash for RegionKind { } impl DebugWithInfcx for RegionKind { - fn fmt>( - this: OptWithInfcx<'_, I, Infcx, &Self>, + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { match this.data { @@ -301,7 +301,7 @@ impl DebugWithInfcx for RegionKind { } impl fmt::Debug for RegionKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - OptWithInfcx::with_no_infcx(self).fmt(f) + WithInfcx::with_no_infcx(self).fmt(f) } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 3f7171a816b0..9c719d2d9784 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -11,7 +11,7 @@ use crate::HashStableContext; use crate::Interner; use crate::TyDecoder; use crate::TyEncoder; -use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, OptWithInfcx}; +use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx}; use self::TyKind::*; @@ -534,8 +534,8 @@ impl hash::Hash for TyKind { } impl DebugWithInfcx for TyKind { - fn fmt>( - this: OptWithInfcx<'_, I, Infcx, &Self>, + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> fmt::Result { match this.data { @@ -617,7 +617,7 @@ impl DebugWithInfcx for TyKind { // This is manually implemented because a derive would require `I: Debug` impl fmt::Debug for TyKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - OptWithInfcx::with_no_infcx(self).fmt(f) + WithInfcx::with_no_infcx(self).fmt(f) } } @@ -1239,12 +1239,12 @@ impl fmt::Debug for InferTy { } impl> DebugWithInfcx for InferTy { - fn fmt>( - this: OptWithInfcx<'_, I, Infcx, &Self>, + fn fmt>( + this: WithInfcx<'_, Infcx, &Self>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { use InferTy::*; - match this.infcx.and_then(|infcx| infcx.universe_of_ty(*this.data)) { + match this.infcx.universe_of_ty(*this.data) { None => write!(f, "{:?}", this.data), Some(universe) => match *this.data { TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()), From 9853f6132f3908ec9d767ab13eb7d48943afb791 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 15 Oct 2023 12:06:14 -0700 Subject: [PATCH 29/51] =?UTF-8?q?Validate=20#[stable(feature=20=3D=20"?= =?UTF-8?q?=E2=80=A6")]=20identifier?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_attr/src/builtin.rs | 51 ++++++++++++++++-------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 60eacde1c723..50045cb1f0f2 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -3,6 +3,7 @@ use rustc_ast::{self as ast, attr}; use rustc_ast::{Attribute, LitKind, MetaItem, MetaItemKind, MetaItemLit, NestedMetaItem, NodeId}; use rustc_ast_pretty::pprust; +use rustc_errors::ErrorGuaranteed; use rustc_feature::{find_gated_cfg, is_builtin_attr_name, Features, GatedCfg}; use rustc_macros::HashStable_Generic; use rustc_session::config::ExpectedValues; @@ -367,19 +368,23 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit since = Some(rust_version_symbol()); } + let feature = match feature { + Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature), + Some(_bad_feature) => { + Err(sess.emit_err(session_diagnostics::NonIdentFeature { span: attr.span })) + } + None => Err(sess.emit_err(session_diagnostics::MissingFeature { span: attr.span })), + }; + + let since = + since.ok_or_else(|| sess.emit_err(session_diagnostics::MissingSince { span: attr.span })); + match (feature, since) { - (Some(feature), Some(since)) => { + (Ok(feature), Ok(since)) => { let level = StabilityLevel::Stable { since, allowed_through_unstable_modules: false }; Some((feature, level)) } - (None, _) => { - sess.emit_err(session_diagnostics::MissingFeature { span: attr.span }); - None - } - _ => { - sess.emit_err(session_diagnostics::MissingSince { span: attr.span }); - None - } + (Err(ErrorGuaranteed { .. }), _) | (_, Err(ErrorGuaranteed { .. })) => None, } } @@ -451,12 +456,19 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil } } - match (feature, reason, issue) { - (Some(feature), reason, Some(_)) => { - if !rustc_lexer::is_ident(feature.as_str()) { - sess.emit_err(session_diagnostics::NonIdentFeature { span: attr.span }); - return None; - } + let feature = match feature { + Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature), + Some(_bad_feature) => { + Err(sess.emit_err(session_diagnostics::NonIdentFeature { span: attr.span })) + } + None => Err(sess.emit_err(session_diagnostics::MissingFeature { span: attr.span })), + }; + + let issue = + issue.ok_or_else(|| sess.emit_err(session_diagnostics::MissingIssue { span: attr.span })); + + match (feature, issue) { + (Ok(feature), Ok(_)) => { let level = StabilityLevel::Unstable { reason: UnstableReason::from_opt_reason(reason), issue: issue_num, @@ -465,14 +477,7 @@ fn parse_unstability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabil }; Some((feature, level)) } - (None, _, _) => { - sess.emit_err(session_diagnostics::MissingFeature { span: attr.span }); - return None; - } - _ => { - sess.emit_err(session_diagnostics::MissingIssue { span: attr.span }); - return None; - } + (Err(ErrorGuaranteed { .. }), _) | (_, Err(ErrorGuaranteed { .. })) => None, } } From 67ea7986c78d66d0b9ca09e6b1131e4a6643e861 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 15 Oct 2023 12:20:12 -0700 Subject: [PATCH 30/51] Fix invalid stability attribute features in standard library --- library/core/src/ffi/mod.rs | 2 +- library/std/src/io/mod.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index b2c9a0800c91..6908c824f44b 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -6,7 +6,7 @@ //! match those defined by C, so that code that interacts with C will //! refer to the correct types. -#![stable(feature = "", since = "1.30.0")] +#![stable(feature = "core_ffi", since = "1.30.0")] #![allow(non_camel_case_types)] use crate::fmt; diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 063464046e0b..bca5d859b665 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1140,10 +1140,10 @@ pub fn read_to_string(mut reader: R) -> Result { #[repr(transparent)] pub struct IoSliceMut<'a>(sys::io::IoSliceMut<'a>); -#[stable(feature = "iovec-send-sync", since = "1.44.0")] +#[stable(feature = "iovec_send_sync", since = "1.44.0")] unsafe impl<'a> Send for IoSliceMut<'a> {} -#[stable(feature = "iovec-send-sync", since = "1.44.0")] +#[stable(feature = "iovec_send_sync", since = "1.44.0")] unsafe impl<'a> Sync for IoSliceMut<'a> {} #[stable(feature = "iovec", since = "1.36.0")] @@ -1283,10 +1283,10 @@ impl<'a> DerefMut for IoSliceMut<'a> { #[repr(transparent)] pub struct IoSlice<'a>(sys::io::IoSlice<'a>); -#[stable(feature = "iovec-send-sync", since = "1.44.0")] +#[stable(feature = "iovec_send_sync", since = "1.44.0")] unsafe impl<'a> Send for IoSlice<'a> {} -#[stable(feature = "iovec-send-sync", since = "1.44.0")] +#[stable(feature = "iovec_send_sync", since = "1.44.0")] unsafe impl<'a> Sync for IoSlice<'a> {} #[stable(feature = "iovec", since = "1.36.0")] From 01b909174bf44b72b927b524626b06738e5872a4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 15 Oct 2023 12:53:37 -0700 Subject: [PATCH 31/51] Fix stable feature names in tests --- .../tests/ui/missing_const_for_fn/auxiliary/helper.rs | 4 ++-- tests/rustdoc/deprecated-future-staged-api.rs | 6 +++--- tests/ui/deprecation/staged-deprecation-in-future.rs | 6 +++--- tests/ui/repr/16-bit-repr-c-enum.rs | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs index 7b9dc76b8f1d..775e071147cf 100644 --- a/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs +++ b/src/tools/clippy/tests/ui/missing_const_for_fn/auxiliary/helper.rs @@ -1,8 +1,8 @@ // This file provides a const function that is unstably const forever. #![feature(staged_api)] -#![stable(feature = "1", since = "1.0.0")] +#![stable(feature = "clippytest", since = "1.0.0")] -#[stable(feature = "1", since = "1.0.0")] +#[stable(feature = "clippytest", since = "1.0.0")] #[rustc_const_unstable(feature = "foo", issue = "none")] pub const fn unstably_const_fn() {} diff --git a/tests/rustdoc/deprecated-future-staged-api.rs b/tests/rustdoc/deprecated-future-staged-api.rs index 2670e7f5d046..09120b8d411a 100644 --- a/tests/rustdoc/deprecated-future-staged-api.rs +++ b/tests/rustdoc/deprecated-future-staged-api.rs @@ -1,12 +1,12 @@ #![feature(staged_api)] -#![stable(feature = "deprecated-future-staged-api", since = "1.0.0")] +#![stable(feature = "deprecated_future_staged_api", since = "1.0.0")] // @has deprecated_future_staged_api/index.html '//*[@class="stab deprecated"]' \ // 'Deprecation planned' // @has deprecated_future_staged_api/struct.S1.html '//*[@class="stab deprecated"]' \ // 'Deprecating in 99.99.99: effectively never' #[deprecated(since = "99.99.99", note = "effectively never")] -#[stable(feature = "deprecated-future-staged-api", since = "1.0.0")] +#[stable(feature = "deprecated_future_staged_api", since = "1.0.0")] pub struct S1; // @has deprecated_future_staged_api/index.html '//*[@class="stab deprecated"]' \ @@ -14,5 +14,5 @@ pub struct S1; // @has deprecated_future_staged_api/struct.S2.html '//*[@class="stab deprecated"]' \ // 'Deprecating in a future Rust version: literally never' #[deprecated(since = "TBD", note = "literally never")] -#[stable(feature = "deprecated-future-staged-api", since = "1.0.0")] +#[stable(feature = "deprecated_future_staged_api", since = "1.0.0")] pub struct S2; diff --git a/tests/ui/deprecation/staged-deprecation-in-future.rs b/tests/ui/deprecation/staged-deprecation-in-future.rs index 87b15ec303c3..49ee60b9bd02 100644 --- a/tests/ui/deprecation/staged-deprecation-in-future.rs +++ b/tests/ui/deprecation/staged-deprecation-in-future.rs @@ -2,14 +2,14 @@ #![feature(staged_api)] -#![stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")] +#![stable(feature = "rustc_deprecation_in_future_test", since = "1.0.0")] #[deprecated(since = "99.99.99", note = "effectively never")] -#[stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")] +#[stable(feature = "rustc_deprecation_in_future_test", since = "1.0.0")] pub struct S1; #[deprecated(since = "TBD", note = "literally never")] -#[stable(feature = "rustc_deprecation-in-future-test", since = "1.0.0")] +#[stable(feature = "rustc_deprecation_in_future_test", since = "1.0.0")] pub struct S2; fn main() { diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index d4fea2b192b4..c6d188d63e63 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs @@ -8,7 +8,7 @@ #![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)] #![no_core] #![crate_type = "lib"] -#![stable(feature = "", since = "")] +#![stable(feature = "intrinsics_for_test", since = "")] #![allow(dead_code)] // Test that the repr(C) attribute doesn't break compilation @@ -22,8 +22,8 @@ enum Foo { } extern "rust-intrinsic" { - #[stable(feature = "", since = "")] - #[rustc_const_stable(feature = "", since = "")] + #[stable(feature = "intrinsics_for_test", since = "")] + #[rustc_const_stable(feature = "intrinsics_for_test", since = "")] #[rustc_safe_intrinsic] fn size_of() -> usize; } From 82ed3f5e8b65291d4861f62f8c9c5bc8630e42b2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 16 Oct 2023 12:30:32 -0700 Subject: [PATCH 32/51] Validate `since` value in stable attribute --- compiler/rustc_attr/messages.ftl | 3 +++ compiler/rustc_attr/src/builtin.rs | 19 +++++++++++-------- .../rustc_attr/src/session_diagnostics.rs | 7 +++++++ 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_attr/messages.ftl b/compiler/rustc_attr/messages.ftl index e6cbbaf3704b..7281282fec37 100644 --- a/compiler/rustc_attr/messages.ftl +++ b/compiler/rustc_attr/messages.ftl @@ -58,6 +58,9 @@ attr_invalid_repr_hint_no_paren = attr_invalid_repr_hint_no_value = invalid representation hint: `{$name}` does not take a value +attr_invalid_since = + 'since' must be a Rust version number, such as "1.31.0" + attr_missing_feature = missing 'feature' diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 50045cb1f0f2..44ba495721d2 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -362,12 +362,6 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit } } - if let Some(s) = since - && s.as_str() == VERSION_PLACEHOLDER - { - since = Some(rust_version_symbol()); - } - let feature = match feature { Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature), Some(_bad_feature) => { @@ -376,8 +370,17 @@ fn parse_stability(sess: &Session, attr: &Attribute) -> Option<(Symbol, Stabilit None => Err(sess.emit_err(session_diagnostics::MissingFeature { span: attr.span })), }; - let since = - since.ok_or_else(|| sess.emit_err(session_diagnostics::MissingSince { span: attr.span })); + let since = if let Some(since) = since { + if since.as_str() == VERSION_PLACEHOLDER { + Ok(rust_version_symbol()) + } else if parse_version(since.as_str(), false).is_some() { + Ok(since) + } else { + Err(sess.emit_err(session_diagnostics::InvalidSince { span: attr.span })) + } + } else { + Err(sess.emit_err(session_diagnostics::MissingSince { span: attr.span })) + }; match (feature, since) { (Ok(feature), Ok(since)) => { diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs index 86f27254db25..ca9bbd28b955 100644 --- a/compiler/rustc_attr/src/session_diagnostics.rs +++ b/compiler/rustc_attr/src/session_diagnostics.rs @@ -370,6 +370,13 @@ pub(crate) struct ExpectsFeatures { pub name: String, } +#[derive(Diagnostic)] +#[diag(attr_invalid_since)] +pub(crate) struct InvalidSince { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(attr_soft_no_args)] pub(crate) struct SoftNoArgs { From 6a02e20fb5e80f1d05070af0cb2b0f85185a62d0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 16 Oct 2023 13:11:26 -0700 Subject: [PATCH 33/51] Update `since` stability attributes in tests --- tests/rustdoc/implementor-stable-version.rs | 16 +++--- .../ui/attributes/const-stability-on-macro.rs | 2 +- .../const-stability-on-macro.stderr | 4 +- .../defaults/default-annotation.rs | 6 +- .../feature-gates/feature-gate-staged_api.rs | 4 +- .../feature-gate-staged_api.stderr | 8 +-- .../reachable-unnameable-type-alias.rs | 4 +- tests/ui/repr/16-bit-repr-c-enum.rs | 6 +- ...lt-method-body-is-const-with-staged-api.rs | 2 +- .../stability-attribute-issue-43027.rs | 8 +-- .../stability-attribute-sanity-4.rs | 4 +- .../stability-attribute-sanity.rs | 23 ++++---- .../stability-attribute-sanity.stderr | 55 +++++++++++-------- .../stability-attribute-trait-impl.rs | 4 +- .../stability-attribute-trait-impl.stderr | 2 +- 15 files changed, 79 insertions(+), 69 deletions(-) diff --git a/tests/rustdoc/implementor-stable-version.rs b/tests/rustdoc/implementor-stable-version.rs index a1f3fd5a8c5a..9c5b9b7e3033 100644 --- a/tests/rustdoc/implementor-stable-version.rs +++ b/tests/rustdoc/implementor-stable-version.rs @@ -1,21 +1,21 @@ -#![stable(feature = "bar", since = "OLD 1.0")] +#![stable(feature = "bar", since = "3.3.3")] #![crate_name = "foo"] #![feature(staged_api)] -#[stable(feature = "bar", since = "OLD 1.0")] +#[stable(feature = "bar", since = "3.3.3")] pub trait Bar {} -#[stable(feature = "baz", since = "OLD 1.0")] +#[stable(feature = "baz", since = "3.3.3")] pub trait Baz {} -#[stable(feature = "baz", since = "OLD 1.0")] +#[stable(feature = "baz", since = "3.3.3")] pub struct Foo; -// @has foo/trait.Bar.html '//div[@id="implementors-list"]//span[@class="since"]' 'NEW 2.0' -#[stable(feature = "foobar", since = "NEW 2.0")] +// @has foo/trait.Bar.html '//div[@id="implementors-list"]//span[@class="since"]' '4.4.4' +#[stable(feature = "foobar", since = "4.4.4")] impl Bar for Foo {} -// @!has foo/trait.Baz.html '//div[@id="implementors-list"]//span[@class="since"]' 'OLD 1.0' -#[stable(feature = "foobaz", since = "OLD 1.0")] +// @!has foo/trait.Baz.html '//div[@id="implementors-list"]//span[@class="since"]' '3.3.3' +#[stable(feature = "foobaz", since = "3.3.3")] impl Baz for Foo {} diff --git a/tests/ui/attributes/const-stability-on-macro.rs b/tests/ui/attributes/const-stability-on-macro.rs index 412af195d7a1..af268ccd5366 100644 --- a/tests/ui/attributes/const-stability-on-macro.rs +++ b/tests/ui/attributes/const-stability-on-macro.rs @@ -1,7 +1,7 @@ #![feature(staged_api)] #![stable(feature = "rust1", since = "1.0.0")] -#[rustc_const_stable(feature = "foo", since = "0")] +#[rustc_const_stable(feature = "foo", since = "3.3.3")] //~^ ERROR macros cannot have const stability attributes macro_rules! foo { () => {}; diff --git a/tests/ui/attributes/const-stability-on-macro.stderr b/tests/ui/attributes/const-stability-on-macro.stderr index c3da02c79cb5..28f31e3d4f61 100644 --- a/tests/ui/attributes/const-stability-on-macro.stderr +++ b/tests/ui/attributes/const-stability-on-macro.stderr @@ -1,8 +1,8 @@ error: macros cannot have const stability attributes --> $DIR/const-stability-on-macro.rs:4:1 | -LL | #[rustc_const_stable(feature = "foo", since = "0")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute +LL | #[rustc_const_stable(feature = "foo", since = "3.3.3")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid const stability attribute LL | LL | macro_rules! foo { | ---------------- const stability attribute affects this macro diff --git a/tests/ui/const-generics/defaults/default-annotation.rs b/tests/ui/const-generics/defaults/default-annotation.rs index 7a9f5732f7fa..587ad78e2981 100644 --- a/tests/ui/const-generics/defaults/default-annotation.rs +++ b/tests/ui/const-generics/defaults/default-annotation.rs @@ -4,12 +4,12 @@ // FIXME(const_generics_defaults): It seems like we aren't testing the right thing here, // I would assume that we want the attributes to apply to the const parameter defaults // themselves. -#![stable(feature = "const_default_test", since="none")] +#![stable(feature = "const_default_test", since = "3.3.3")] -#[unstable(feature = "const_default_stable", issue="none")] +#[unstable(feature = "const_default_stable", issue = "none")] pub struct ConstDefaultUnstable; -#[stable(feature = "const_default_unstable", since="none")] +#[stable(feature = "const_default_unstable", since = "3.3.3")] pub struct ConstDefaultStable; diff --git a/tests/ui/feature-gates/feature-gate-staged_api.rs b/tests/ui/feature-gates/feature-gate-staged_api.rs index 2571ab5d1b4e..ce6b218dd7d2 100644 --- a/tests/ui/feature-gates/feature-gate-staged_api.rs +++ b/tests/ui/feature-gates/feature-gate-staged_api.rs @@ -1,11 +1,11 @@ -#![stable(feature = "a", since = "b")] +#![stable(feature = "a", since = "3.3.3")] //~^ ERROR stability attributes may not be used outside of the standard library mod inner_private_module { // UnnameableTypeAlias isn't marked as reachable, so no stability annotation is required here pub type UnnameableTypeAlias = u8; } -#[stable(feature = "a", since = "b")] +#[stable(feature = "a", since = "3.3.3")] //~^ ERROR stability attributes may not be used outside of the standard library pub fn f() -> inner_private_module::UnnameableTypeAlias { 0 diff --git a/tests/ui/feature-gates/feature-gate-staged_api.stderr b/tests/ui/feature-gates/feature-gate-staged_api.stderr index 951bb5a17400..1a9fcb02b0de 100644 --- a/tests/ui/feature-gates/feature-gate-staged_api.stderr +++ b/tests/ui/feature-gates/feature-gate-staged_api.stderr @@ -1,14 +1,14 @@ error[E0734]: stability attributes may not be used outside of the standard library --> $DIR/feature-gate-staged_api.rs:8:1 | -LL | #[stable(feature = "a", since = "b")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[stable(feature = "a", since = "3.3.3")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0734]: stability attributes may not be used outside of the standard library --> $DIR/feature-gate-staged_api.rs:1:1 | -LL | #![stable(feature = "a", since = "b")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #![stable(feature = "a", since = "3.3.3")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/reachable/reachable-unnameable-type-alias.rs b/tests/ui/reachable/reachable-unnameable-type-alias.rs index 461355f87cf1..ce830d2d4b4b 100644 --- a/tests/ui/reachable/reachable-unnameable-type-alias.rs +++ b/tests/ui/reachable/reachable-unnameable-type-alias.rs @@ -1,14 +1,14 @@ // run-pass #![feature(staged_api)] -#![stable(feature = "a", since = "b")] +#![stable(feature = "a", since = "3.3.3")] mod inner_private_module { // UnnameableTypeAlias isn't marked as reachable, so no stability annotation is required here pub type UnnameableTypeAlias = u8; } -#[stable(feature = "a", since = "b")] +#[stable(feature = "a", since = "3.3.3")] pub fn f() -> inner_private_module::UnnameableTypeAlias { 0 } diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index c6d188d63e63..987fd455fcc0 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs @@ -8,7 +8,7 @@ #![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)] #![no_core] #![crate_type = "lib"] -#![stable(feature = "intrinsics_for_test", since = "")] +#![stable(feature = "intrinsics_for_test", since = "3.3.3")] #![allow(dead_code)] // Test that the repr(C) attribute doesn't break compilation @@ -22,8 +22,8 @@ enum Foo { } extern "rust-intrinsic" { - #[stable(feature = "intrinsics_for_test", since = "")] - #[rustc_const_stable(feature = "intrinsics_for_test", since = "")] + #[stable(feature = "intrinsics_for_test", since = "3.3.3")] + #[rustc_const_stable(feature = "intrinsics_for_test", since = "3.3.3")] #[rustc_safe_intrinsic] fn size_of() -> usize; } diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs index 1b45cd9aab9d..13881e042a32 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-with-staged-api.rs @@ -7,7 +7,7 @@ #![feature(staged_api)] #![feature(const_trait_impl)] -#![stable(since = "1", feature = "foo")] +#![stable(feature = "foo", since = "3.3.3")] #[const_trait] trait Tr { diff --git a/tests/ui/stability-attribute/stability-attribute-issue-43027.rs b/tests/ui/stability-attribute/stability-attribute-issue-43027.rs index 3f4fdfd0180e..810fbef7b381 100644 --- a/tests/ui/stability-attribute/stability-attribute-issue-43027.rs +++ b/tests/ui/stability-attribute/stability-attribute-issue-43027.rs @@ -1,12 +1,12 @@ // check-pass #![feature(staged_api)] -#![stable(feature = "test", since = "0")] +#![stable(feature = "test", since = "3.3.3")] -#[stable(feature = "test", since = "0")] +#[stable(feature = "test", since = "3.3.3")] pub struct A(pub T); -#[stable(feature = "test", since = "0")] -pub struct B(#[stable(feature = "test", since = "0")] pub T); +#[stable(feature = "test", since = "3.3.3")] +pub struct B(#[stable(feature = "test", since = "3.3.3")] pub T); fn main() { // Make sure the field is used to fill the stability cache diff --git a/tests/ui/stability-attribute/stability-attribute-sanity-4.rs b/tests/ui/stability-attribute/stability-attribute-sanity-4.rs index 64f996352196..4fe8e45fd049 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity-4.rs +++ b/tests/ui/stability-attribute/stability-attribute-sanity-4.rs @@ -17,11 +17,11 @@ mod bogus_attribute_types_2 { #[stable = "a"] //~ ERROR malformed `stable` attribute fn f4() { } - #[stable(feature = "a", since = "b")] + #[stable(feature = "a", since = "3.3.3")] #[deprecated] //~ ERROR missing 'since' fn f5() { } - #[stable(feature = "a", since = "b")] + #[stable(feature = "a", since = "3.3.3")] #[deprecated = "a"] //~ ERROR missing 'since' fn f6() { } } diff --git a/tests/ui/stability-attribute/stability-attribute-sanity.rs b/tests/ui/stability-attribute/stability-attribute-sanity.rs index cc30e6ab9a9b..7b3a7b537c12 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity.rs +++ b/tests/ui/stability-attribute/stability-attribute-sanity.rs @@ -5,19 +5,19 @@ #![stable(feature = "rust1", since = "1.0.0")] mod bogus_attribute_types_1 { - #[stable(feature = "a", since = "b", reason)] //~ ERROR unknown meta item 'reason' [E0541] + #[stable(feature = "a", since = "4.4.4", reason)] //~ ERROR unknown meta item 'reason' [E0541] fn f1() { } #[stable(feature = "a", since)] //~ ERROR incorrect meta item [E0539] fn f2() { } - #[stable(feature, since = "a")] //~ ERROR incorrect meta item [E0539] + #[stable(feature, since = "3.3.3")] //~ ERROR incorrect meta item [E0539] fn f3() { } #[stable(feature = "a", since(b))] //~ ERROR incorrect meta item [E0539] fn f5() { } - #[stable(feature(b), since = "a")] //~ ERROR incorrect meta item [E0539] + #[stable(feature(b), since = "3.3.3")] //~ ERROR incorrect meta item [E0539] fn f6() { } } @@ -28,7 +28,7 @@ mod missing_feature_names { #[unstable(feature = "b")] //~ ERROR missing 'issue' [E0547] fn f2() { } - #[stable(since = "a")] //~ ERROR missing 'feature' [E0546] + #[stable(since = "3.3.3")] //~ ERROR missing 'feature' [E0546] fn f3() { } } @@ -36,33 +36,34 @@ mod missing_version { #[stable(feature = "a")] //~ ERROR missing 'since' [E0542] fn f1() { } - #[stable(feature = "a", since = "b")] + #[stable(feature = "a", since = "4.4.4")] #[deprecated(note = "a")] //~ ERROR missing 'since' [E0542] fn f2() { } - #[stable(feature = "a", since = "b")] + #[stable(feature = "a", since = "4.4.4")] #[deprecated(since = "a")] //~ ERROR missing 'note' [E0543] fn f3() { } } #[unstable(feature = "b", issue = "none")] -#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544] +#[stable(feature = "a", since = "4.4.4")] //~ ERROR multiple stability levels [E0544] fn multiple1() { } #[unstable(feature = "b", issue = "none")] #[unstable(feature = "b", issue = "none")] //~ ERROR multiple stability levels [E0544] fn multiple2() { } -#[stable(feature = "a", since = "b")] -#[stable(feature = "a", since = "b")] //~ ERROR multiple stability levels [E0544] +#[stable(feature = "a", since = "4.4.4")] +#[stable(feature = "a", since = "4.4.4")] //~ ERROR multiple stability levels [E0544] fn multiple3() { } -#[stable(feature = "a", since = "b")] //~ ERROR invalid stability version found +#[stable(feature = "e", since = "b")] //~ ERROR 'since' must be a Rust version number, such as "1.31.0" #[deprecated(since = "b", note = "text")] #[deprecated(since = "b", note = "text")] //~ ERROR multiple `deprecated` attributes +//~^ ERROR deprecated attribute must be paired with either stable or unstable attribute #[rustc_const_unstable(feature = "c", issue = "none")] #[rustc_const_unstable(feature = "d", issue = "none")] //~ ERROR multiple stability levels -pub const fn multiple4() { } +pub const fn multiple4() { } //~ ERROR function has missing stability attribute #[stable(feature = "a", since = "1.0.0")] //~ ERROR invalid deprecation version found //~^ ERROR feature `a` is declared stable since 1.0.0 diff --git a/tests/ui/stability-attribute/stability-attribute-sanity.stderr b/tests/ui/stability-attribute/stability-attribute-sanity.stderr index 89a8425f5e78..f9610c90f76e 100644 --- a/tests/ui/stability-attribute/stability-attribute-sanity.stderr +++ b/tests/ui/stability-attribute/stability-attribute-sanity.stderr @@ -11,10 +11,10 @@ LL | #[deprecated(since = "b", note = "text")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0541]: unknown meta item 'reason' - --> $DIR/stability-attribute-sanity.rs:8:42 + --> $DIR/stability-attribute-sanity.rs:8:46 | -LL | #[stable(feature = "a", since = "b", reason)] - | ^^^^^^ expected one of `feature`, `since` +LL | #[stable(feature = "a", since = "4.4.4", reason)] + | ^^^^^^ expected one of `feature`, `since` error[E0539]: incorrect meta item --> $DIR/stability-attribute-sanity.rs:11:29 @@ -25,7 +25,7 @@ LL | #[stable(feature = "a", since)] error[E0539]: incorrect meta item --> $DIR/stability-attribute-sanity.rs:14:14 | -LL | #[stable(feature, since = "a")] +LL | #[stable(feature, since = "3.3.3")] | ^^^^^^^ error[E0539]: incorrect meta item @@ -37,7 +37,7 @@ LL | #[stable(feature = "a", since(b))] error[E0539]: incorrect meta item --> $DIR/stability-attribute-sanity.rs:20:14 | -LL | #[stable(feature(b), since = "a")] +LL | #[stable(feature(b), since = "3.3.3")] | ^^^^^^^^^^ error[E0546]: missing 'feature' @@ -55,8 +55,8 @@ LL | #[unstable(feature = "b")] error[E0546]: missing 'feature' --> $DIR/stability-attribute-sanity.rs:31:5 | -LL | #[stable(since = "a")] - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | #[stable(since = "3.3.3")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0542]: missing 'since' --> $DIR/stability-attribute-sanity.rs:36:5 @@ -79,8 +79,8 @@ LL | #[deprecated(since = "a")] error[E0544]: multiple stability levels --> $DIR/stability-attribute-sanity.rs:49:1 | -LL | #[stable(feature = "a", since = "b")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[stable(feature = "a", since = "4.4.4")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0544]: multiple stability levels --> $DIR/stability-attribute-sanity.rs:53:1 @@ -91,26 +91,29 @@ LL | #[unstable(feature = "b", issue = "none")] error[E0544]: multiple stability levels --> $DIR/stability-attribute-sanity.rs:57:1 | -LL | #[stable(feature = "a", since = "b")] +LL | #[stable(feature = "a", since = "4.4.4")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: 'since' must be a Rust version number, such as "1.31.0" + --> $DIR/stability-attribute-sanity.rs:60:1 + | +LL | #[stable(feature = "e", since = "b")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0544]: multiple stability levels - --> $DIR/stability-attribute-sanity.rs:64:1 + --> $DIR/stability-attribute-sanity.rs:65:1 | LL | #[rustc_const_unstable(feature = "d", issue = "none")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: invalid stability version found - --> $DIR/stability-attribute-sanity.rs:60:1 +error[E0549]: deprecated attribute must be paired with either stable or unstable attribute + --> $DIR/stability-attribute-sanity.rs:62:1 | -LL | #[stable(feature = "a", since = "b")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid stability version -... -LL | pub const fn multiple4() { } - | ---------------------------- the stability attribute annotates this item +LL | #[deprecated(since = "b", note = "text")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: invalid deprecation version found - --> $DIR/stability-attribute-sanity.rs:67:1 + --> $DIR/stability-attribute-sanity.rs:68:1 | LL | #[stable(feature = "a", since = "1.0.0")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid deprecation version @@ -119,18 +122,24 @@ LL | fn invalid_deprecation_version() {} | ----------------------------------- the stability attribute annotates this item error[E0549]: deprecated attribute must be paired with either stable or unstable attribute - --> $DIR/stability-attribute-sanity.rs:72:1 + --> $DIR/stability-attribute-sanity.rs:73:1 | LL | #[deprecated(since = "a", note = "text")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0711]: feature `a` is declared stable since 1.0.0, but was previously declared stable since b - --> $DIR/stability-attribute-sanity.rs:67:1 +error: function has missing stability attribute + --> $DIR/stability-attribute-sanity.rs:66:1 + | +LL | pub const fn multiple4() { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0711]: feature `a` is declared stable since 1.0.0, but was previously declared stable since 4.4.4 + --> $DIR/stability-attribute-sanity.rs:68:1 | LL | #[stable(feature = "a", since = "1.0.0")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 20 previous errors +error: aborting due to 22 previous errors Some errors have detailed explanations: E0539, E0541, E0542, E0543, E0544, E0546, E0547, E0549, E0711. For more information about an error, try `rustc --explain E0539`. diff --git a/tests/ui/stability-attribute/stability-attribute-trait-impl.rs b/tests/ui/stability-attribute/stability-attribute-trait-impl.rs index 1d138e264086..880000ee7a43 100644 --- a/tests/ui/stability-attribute/stability-attribute-trait-impl.rs +++ b/tests/ui/stability-attribute/stability-attribute-trait-impl.rs @@ -1,13 +1,13 @@ #![feature(staged_api, never_type, rust_cold_cc)] //~^ ERROR module has missing stability attribute -#[stable(feature = "a", since = "1")] +#[stable(feature = "a", since = "3.3.3")] struct StableType; #[unstable(feature = "b", issue = "none")] struct UnstableType; -#[stable(feature = "c", since = "1")] +#[stable(feature = "c", since = "3.3.3")] trait StableTrait {} #[unstable(feature = "d", issue = "none")] diff --git a/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr b/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr index 96322c2c9450..018786dd26dc 100644 --- a/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr +++ b/tests/ui/stability-attribute/stability-attribute-trait-impl.stderr @@ -21,7 +21,7 @@ error: module has missing stability attribute LL | / #![feature(staged_api, never_type, rust_cold_cc)] LL | | LL | | -LL | | #[stable(feature = "a", since = "1")] +LL | | #[stable(feature = "a", since = "3.3.3")] ... | LL | | LL | | fn main() {} From fd92bc6021423f144b8d6204a5ec7ac0cceeecc9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Oct 2023 21:58:38 +0000 Subject: [PATCH 34/51] Handle ReErased in responses in new solver --- .../src/solve/canonicalize.rs | 12 ++++++++++-- .../ui/impl-trait/erased-regions-in-hidden-ty.rs | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 tests/ui/impl-trait/erased-regions-in-hidden-ty.rs diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs index 19f0c9fe826d..377ae1b4e85f 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs @@ -224,12 +224,20 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { let kind = match *r { ty::ReLateBound(..) => return r, - ty::ReStatic => match self.canonicalize_mode { + // We may encounter `ReStatic` in item signatures or the hidden type + // of an opaque. `ReErased` should only be encountered in the hidden + // type of an opaque for regions that are ignored for the purposes of + // captures. + // + // FIXME: We should investigate the perf implications of not uniquifying + // `ReErased`. We may be able to short-circuit registering region + // obligations if we encounter a `ReErased` on one side, for example. + ty::ReStatic | ty::ReErased => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => return r, }, - ty::ReErased | ty::ReFree(_) | ty::ReEarlyBound(_) => match self.canonicalize_mode { + ty::ReFree(_) | ty::ReEarlyBound(_) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"), }, diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs new file mode 100644 index 000000000000..794dabe08b86 --- /dev/null +++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs @@ -0,0 +1,15 @@ +// revisions: current next +//[next] compile-flags: -Ztrait-solver=next +// check-pass + +// Make sure that the compiler can handle `ReErased` in the hidden type of an opaque. + +fn foo<'a: 'a>(x: &'a Vec) -> impl Fn() + 'static { + || () +} + +fn bar() -> impl Fn() + 'static { + foo(&vec![]) +} + +fn main() {} From a387a3cf9d2a3f3f3b743ff3f2741a72708e1664 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 4 Oct 2023 23:08:05 +0000 Subject: [PATCH 35/51] Let's see what those opaque types actually are --- compiler/rustc_feature/src/builtin_attrs.rs | 1 + compiler/rustc_hir_analysis/messages.ftl | 2 ++ compiler/rustc_hir_analysis/src/collect.rs | 10 ++++++---- .../rustc_hir_analysis/src/collect/type_of.rs | 1 + .../src/collect/type_of/opaque.rs | 19 ++++++++++++++++--- compiler/rustc_hir_analysis/src/errors.rs | 8 ++++++++ compiler/rustc_hir_analysis/src/lib.rs | 4 ++++ compiler/rustc_span/src/symbol.rs | 1 + ...erased-regions-in-hidden-ty.current.stderr | 14 ++++++++++++++ .../erased-regions-in-hidden-ty.next.stderr | 14 ++++++++++++++ .../impl-trait/erased-regions-in-hidden-ty.rs | 10 +++++++++- 11 files changed, 76 insertions(+), 8 deletions(-) create mode 100644 tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr create mode 100644 tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 65e697c8f3b8..e808e4815fe0 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -825,6 +825,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_variance, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_variance_of_opaques, Normal, template!(Word), WarnFollowing), + rustc_attr!(TEST, rustc_hidden_type_of_opaques, Normal, template!(Word), WarnFollowing), rustc_attr!(TEST, rustc_layout, Normal, template!(List: "field1, field2, ..."), WarnFollowing), rustc_attr!(TEST, rustc_abi, Normal, template!(List: "field1, field2, ..."), WarnFollowing), rustc_attr!(TEST, rustc_regions, Normal, template!(Word), WarnFollowing), diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index ee475e3de7e9..6bf6650986a6 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -339,6 +339,8 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de .label = needs at most one field with non-trivial size or alignment, but has {$field_count} .labels = this field has non-zero size or requires alignment +hir_analysis_type_of = {$type_of} + hir_analysis_typeof_reserved_keyword_used = `typeof` is a reserved keyword but unimplemented .suggestion = consider replacing `typeof(...)` with an actual type diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 640138a3e5ef..9636c6144461 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -14,14 +14,11 @@ //! At present, however, we do run collection across all items in the //! crate as a kind of pass. This should eventually be factored away. -use crate::astconv::AstConv; -use crate::check::intrinsic::intrinsic_operation_unsafety; -use crate::errors; -use hir::def::DefKind; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed, StashKey}; use rustc_hir as hir; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{GenericParamKind, Node}; @@ -40,6 +37,11 @@ use rustc_trait_selection::traits::ObligationCtxt; use std::iter; use std::ops::Bound; +use crate::astconv::AstConv; +use crate::check::intrinsic::intrinsic_operation_unsafety; +use crate::errors; +pub use type_of::test_opaque_hidden_types; + mod generics_of; mod item_bounds; mod predicates_of; diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 47a412c21109..d7bd2a7b17fc 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -11,6 +11,7 @@ use rustc_span::{Span, DUMMY_SP}; use super::ItemCtxt; use super::{bad_placeholder, is_suggestable_infer_ty}; +pub use opaque::test_opaque_hidden_types; mod opaque; diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 0544c5ca8661..e8d5264c2b8f 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -1,12 +1,25 @@ use rustc_errors::StashKey; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def::DefKind; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; -use rustc_span::DUMMY_SP; +use rustc_span::{sym, DUMMY_SP}; -use crate::errors::{TaitForwardCompat, UnconstrainedOpaqueType}; +use crate::errors::{TaitForwardCompat, TypeOf, UnconstrainedOpaqueType}; + +pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) { + if tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) { + for id in tcx.hir().items() { + if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) { + let type_of = tcx.type_of(id.owner_id).instantiate_identity(); + + tcx.sess.emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of }); + } + } + } +} /// Checks "defining uses" of opaque `impl Trait` types to ensure that they meet the restrictions /// laid for "higher-order pattern unification". diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 1120585f1aa2..189564d4e339 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -467,6 +467,14 @@ pub(crate) struct VariancesOf { pub variances_of: String, } +#[derive(Diagnostic)] +#[diag(hir_analysis_type_of)] +pub(crate) struct TypeOf<'tcx> { + #[primary_span] + pub span: Span, + pub type_of: Ty<'tcx>, +} + #[derive(Diagnostic)] #[diag(hir_analysis_pass_to_variadic_function, code = "E0617")] pub(crate) struct PassToVariadicFunction<'tcx, 'a> { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 88f3db03a4ee..0622aa2ee80f 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -214,6 +214,10 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { tcx.hir().for_each_module(|module| tcx.ensure().check_mod_item_types(module)) }); + if tcx.features().rustc_attrs { + tcx.sess.track_errors(|| collect::test_opaque_hidden_types(tcx))?; + } + // Freeze definitions as we don't add new ones at this point. This improves performance by // allowing lock-free access to them. tcx.untracked().definitions.freeze(); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5b58cf8b6d62..38ae8f570e91 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1369,6 +1369,7 @@ symbols! { rustc_evaluate_where_clauses, rustc_expected_cgu_reuse, rustc_has_incoherent_inherent_impls, + rustc_hidden_type_of_opaques, rustc_host, rustc_if_this_changed, rustc_inherit_overflow_checks, diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr new file mode 100644 index 000000000000..84b61dc50448 --- /dev/null +++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr @@ -0,0 +1,14 @@ +error: {foo::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} + --> $DIR/erased-regions-in-hidden-ty.rs:11:36 + | +LL | fn foo<'a: 'a>(x: &'a Vec) -> impl Fn() + 'static { + | ^^^^^^^^^^^^^^^^^^^ + +error: Opaque(DefId(..), [ReErased]) + --> $DIR/erased-regions-in-hidden-ty.rs:17:13 + | +LL | fn bar() -> impl Fn() + 'static { + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr new file mode 100644 index 000000000000..84b61dc50448 --- /dev/null +++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr @@ -0,0 +1,14 @@ +error: {foo::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} + --> $DIR/erased-regions-in-hidden-ty.rs:11:36 + | +LL | fn foo<'a: 'a>(x: &'a Vec) -> impl Fn() + 'static { + | ^^^^^^^^^^^^^^^^^^^ + +error: Opaque(DefId(..), [ReErased]) + --> $DIR/erased-regions-in-hidden-ty.rs:17:13 + | +LL | fn bar() -> impl Fn() + 'static { + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs index 794dabe08b86..698123a932d0 100644 --- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs +++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs @@ -1,14 +1,22 @@ // revisions: current next +// compile-flags: -Zverbose //[next] compile-flags: -Ztrait-solver=next -// check-pass +// normalize-stderr-test "DefId\([^\)]+\)" -> "DefId(..)" + +#![feature(rustc_attrs)] +#![rustc_hidden_type_of_opaques] // Make sure that the compiler can handle `ReErased` in the hidden type of an opaque. fn foo<'a: 'a>(x: &'a Vec) -> impl Fn() + 'static { +//~^ ERROR 0, 'a)>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()} +// Can't write whole type because of lack of path sanitization || () } fn bar() -> impl Fn() + 'static { +//~^ ERROR , [ReErased]) +// Can't write whole type because of lack of path sanitization foo(&vec![]) } From 421631a3a1fb4fe5f12d3212c070f95ea501471e Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 23 Oct 2023 14:21:24 -0700 Subject: [PATCH 36/51] Remove unsafe and `Rc` --- compiler/rustc_smir/src/rustc_internal/mod.rs | 22 ++++++++----------- compiler/rustc_smir/src/rustc_smir/mod.rs | 2 +- compiler/stable_mir/src/lib.rs | 13 +++++------ 3 files changed, 15 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 58cdcd49087e..efbf9eba04c3 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -18,15 +18,14 @@ use std::cell::RefCell; use std::fmt::Debug; use std::hash::Hash; use std::ops::Index; -use std::rc::Rc; mod internal; -pub unsafe fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { +pub fn stable<'tcx, S: Stable<'tcx>>(item: &S) -> S::T { with_tables(|tables| item.stable(tables)) } -pub unsafe fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { +pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: &S) -> S::T { with_tables(|tables| item.internal(tables)) } @@ -141,15 +140,12 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { // datastructures and stable MIR datastructures scoped_thread_local! (static TLV: Cell<*const ()>); -pub(crate) fn init<'tcx>(tables: TablesWrapper<'tcx>, f: impl FnOnce()) { +pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) { assert!(!TLV.is_set()); - fn g<'a, 'tcx>(context: &'a TablesWrapper<'tcx>, f: impl FnOnce()) { - let ptr: *const () = &context as *const &_ as _; - TLV.set(&Cell::new(ptr), || { - f(); - }); - } - g(&tables, f); + let ptr: *const () = &tables as *const &_ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); } /// Loads the current context and calls a function with it. @@ -166,7 +162,7 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R } pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { - let tables = Rc::new(RefCell::new(Tables { + let tables = TablesWrapper(RefCell::new(Tables { tcx, def_ids: IndexMap::default(), alloc_ids: IndexMap::default(), @@ -174,7 +170,7 @@ pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { types: vec![], instances: IndexMap::default(), })); - stable_mir::run(TablesWrapper(Rc::clone(&tables)), || init(TablesWrapper(tables), f)); + stable_mir::run(&tables, || init(&tables, f)); } #[macro_export] diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 19ad9898db16..d5a5f800a40c 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -279,7 +279,7 @@ impl PartialEq for MaybeStable { } } -pub(crate) struct TablesWrapper<'tcx>(pub(crate) std::rc::Rc>>); +pub(crate) struct TablesWrapper<'tcx>(pub(crate) RefCell>); pub struct Tables<'tcx> { pub(crate) tcx: TyCtxt<'tcx>, diff --git a/compiler/stable_mir/src/lib.rs b/compiler/stable_mir/src/lib.rs index 512c3fc62964..8cacbdbda487 100644 --- a/compiler/stable_mir/src/lib.rs +++ b/compiler/stable_mir/src/lib.rs @@ -243,15 +243,12 @@ pub trait Context { // datastructures and stable MIR datastructures scoped_thread_local! (static TLV: Cell<*const ()>); -pub fn run(context: impl Context, f: impl FnOnce()) { +pub fn run(context: &dyn Context, f: impl FnOnce()) { assert!(!TLV.is_set()); - fn g<'a>(context: &(dyn Context + 'a), f: impl FnOnce()) { - let ptr: *const () = &context as *const &_ as _; - TLV.set(&Cell::new(ptr), || { - f(); - }); - } - g(&context, f); + let ptr: *const () = &context as *const &_ as _; + TLV.set(&Cell::new(ptr), || { + f(); + }); } /// Loads the current context and calls a function with it. From 090e9de5708388a21d66adbec91c871a48ac355e Mon Sep 17 00:00:00 2001 From: BlackHoleFox Date: Sun, 1 Oct 2023 10:55:24 -0500 Subject: [PATCH 37/51] Remove Apple RNG fallbacks and simplify implementation --- library/std/src/sys/unix/mod.rs | 1 - library/std/src/sys/unix/rand.rs | 107 +++++++++++++++---------------- 2 files changed, 51 insertions(+), 57 deletions(-) diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index da05620fd16e..4b28f6feba5a 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -415,7 +415,6 @@ cfg_if::cfg_if! { } else if #[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] { #[link(name = "System")] #[link(name = "objc")] - #[link(name = "Security", kind = "framework")] #[link(name = "Foundation", kind = "framework")] extern "C" {} } else if #[cfg(target_os = "fuchsia")] { diff --git a/library/std/src/sys/unix/rand.rs b/library/std/src/sys/unix/rand.rs index bdf725fbe5ac..2825d1677427 100644 --- a/library/std/src/sys/unix/rand.rs +++ b/library/std/src/sys/unix/rand.rs @@ -151,40 +151,65 @@ mod imp { } } -#[cfg(target_os = "macos")] +#[cfg(target_vendor = "apple")] mod imp { - use crate::fs::File; - use crate::io::Read; - use crate::sys::os::errno; - use crate::sys::weak::weak; + use crate::io; use libc::{c_int, c_void, size_t}; - fn getentropy_fill_bytes(v: &mut [u8]) -> bool { - weak!(fn getentropy(*mut c_void, size_t) -> c_int); + #[inline(always)] + fn random_failure() -> ! { + panic!("unexpected random generation error: {}", io::Error::last_os_error()); + } - getentropy - .get() - .map(|f| { - // getentropy(2) permits a maximum buffer size of 256 bytes - for s in v.chunks_mut(256) { - let ret = unsafe { f(s.as_mut_ptr() as *mut c_void, s.len()) }; - if ret == -1 { - panic!("unexpected getentropy error: {}", errno()); - } - } - true - }) - .unwrap_or(false) + #[cfg(target_os = "macos")] + fn getentropy_fill_bytes(v: &mut [u8]) { + extern "C" { + fn getentropy(bytes: *mut c_void, count: size_t) -> c_int; + } + + // getentropy(2) permits a maximum buffer size of 256 bytes + for s in v.chunks_mut(256) { + let ret = unsafe { getentropy(s.as_mut_ptr().cast(), s.len()) }; + if ret == -1 { + random_failure() + } + } + } + + #[cfg(not(target_os = "macos"))] + fn ccrandom_fill_bytes(v: &mut [u8]) { + extern "C" { + fn CCRandomGenerateBytes(bytes: *mut c_void, count: size_t) -> c_int; + } + + let ret = unsafe { CCRandomGenerateBytes(v.as_mut_ptr().cast(), v.len()) }; + if ret == -1 { + random_failure() + } } pub fn fill_bytes(v: &mut [u8]) { - if getentropy_fill_bytes(v) { - return; - } + // All supported versions of macOS (10.12+) support getentropy. + // + // `getentropy` is measurably faster (via Divan) then the other alternatives so its preferred + // when usable. + #[cfg(target_os = "macos")] + getentropy_fill_bytes(v); - // for older macos which doesn't support getentropy - let mut file = File::open("/dev/urandom").expect("failed to open /dev/urandom"); - file.read_exact(v).expect("failed to read /dev/urandom") + // On Apple platforms, `CCRandomGenerateBytes` and `SecRandomCopyBytes` simply + // call into `CCRandomCopyBytes` with `kCCRandomDefault`. `CCRandomCopyBytes` + // manages a CSPRNG which is seeded from the kernel's CSPRNG and which runs on + // its own thread accessed via GCD. This seems needlessly heavyweight for our purposes + // so we only use it on non-Mac OSes where the better entrypoints are blocked. + // + // `CCRandomGenerateBytes` is used instead of `SecRandomCopyBytes` because the former is accessible + // via `libSystem` (libc) while the other needs to link to `Security.framework`. + // + // Note that while `getentropy` has a available attribute in the macOS headers, the lack + // of a header in the iOS (and others) SDK means that its can cause app store rejections. + // Just use `CCRandomGenerateBytes` instead. + #[cfg(not(target_os = "macos"))] + ccrandom_fill_bytes(v); } } @@ -203,36 +228,6 @@ mod imp { } } -// On iOS and MacOS `SecRandomCopyBytes` calls `CCRandomCopyBytes` with -// `kCCRandomDefault`. `CCRandomCopyBytes` manages a CSPRNG which is seeded -// from `/dev/random` and which runs on its own thread accessed via GCD. -// This seems needlessly heavyweight for the purposes of generating two u64s -// once per thread in `hashmap_random_keys`. Therefore `SecRandomCopyBytes` is -// only used on iOS where direct access to `/dev/urandom` is blocked by the -// sandbox. -#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))] -mod imp { - use crate::io; - use crate::ptr; - use libc::{c_int, size_t}; - - enum SecRandom {} - - #[allow(non_upper_case_globals)] - const kSecRandomDefault: *const SecRandom = ptr::null(); - - extern "C" { - fn SecRandomCopyBytes(rnd: *const SecRandom, count: size_t, bytes: *mut u8) -> c_int; - } - - pub fn fill_bytes(v: &mut [u8]) { - let ret = unsafe { SecRandomCopyBytes(kSecRandomDefault, v.len(), v.as_mut_ptr()) }; - if ret == -1 { - panic!("couldn't generate random bytes: {}", io::Error::last_os_error()); - } - } -} - // FIXME: once the 10.x release becomes the minimum, this can be dropped for simplification. #[cfg(target_os = "netbsd")] mod imp { From cb618162b138be0e0472d0f5540e6fc0d5a11210 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Thu, 19 Oct 2023 21:12:19 +0800 Subject: [PATCH 38/51] compiler: Add target features for LoongArch --- .../rustc_codegen_ssa/src/target_features.rs | 16 ++++++++++++++++ compiler/rustc_feature/src/unstable.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + 3 files changed, 18 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index baf6b19d3f97..13a3f432b039 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -342,6 +342,19 @@ const CSKY_ALLOWED_FEATURES: &[(&str, Option)] = &[ ("hard-float-abi", Some(sym::csky_target_feature)), // tidy-alphabetical-end ]; + +const LOONGARCH_ALLOWED_FEATURES: &[(&str, Option)] = &[ + // tidy-alphabetical-start + ("d", Some(sym::loongarch_target_feature)), + ("f", Some(sym::loongarch_target_feature)), + ("lasx", Some(sym::loongarch_target_feature)), + ("lbt", Some(sym::loongarch_target_feature)), + ("lsx", Some(sym::loongarch_target_feature)), + ("lvz", Some(sym::loongarch_target_feature)), + ("ual", Some(sym::loongarch_target_feature)), + // tidy-alphabetical-end +]; + /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. /// @@ -358,6 +371,7 @@ pub fn all_known_features() -> impl Iterator &'static [(&'static str, Opt "wasm32" | "wasm64" => WASM_ALLOWED_FEATURES, "bpf" => BPF_ALLOWED_FEATURES, "csky" => CSKY_ALLOWED_FEATURES, + "loongarch64" => LOONGARCH_ALLOWED_FEATURES, _ => &[], } } @@ -445,6 +460,7 @@ pub fn from_target_feature( Some(sym::bpf_target_feature) => rust_features.bpf_target_feature, Some(sym::aarch64_ver_target_feature) => rust_features.aarch64_ver_target_feature, Some(sym::csky_target_feature) => rust_features.csky_target_feature, + Some(sym::loongarch_target_feature) => rust_features.loongarch_target_feature, Some(name) => bug!("unknown target feature gate {}", name), None => true, }; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8185a8a3e437..695de54eefa0 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -288,6 +288,7 @@ declare_features! ( (unstable, csky_target_feature, "1.73.0", Some(44839), None), (unstable, ermsb_target_feature, "1.49.0", Some(44839), None), (unstable, hexagon_target_feature, "1.27.0", Some(44839), None), + (unstable, loongarch_target_feature, "1.73.0", Some(44839), None), (unstable, mips_target_feature, "1.27.0", Some(44839), None), (unstable, powerpc_target_feature, "1.27.0", Some(44839), None), (unstable, riscv_target_feature, "1.45.0", Some(44839), None), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 5b58cf8b6d62..50d969890419 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -957,6 +957,7 @@ symbols! { log_syntax, logf32, logf64, + loongarch_target_feature, loop_break_value, lt, macro_at_most_once_rep, From 6cf9423770437bd6f7b4f8ab0fb81dc2ae722ac0 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Thu, 19 Oct 2023 21:13:52 +0800 Subject: [PATCH 39/51] tests: Add features-gate for LoongArch --- tests/ui/target-feature/gate.rs | 1 + tests/ui/target-feature/gate.stderr | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 782444417a8f..971a4654b4ce 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -18,6 +18,7 @@ // gate-test-bpf_target_feature // gate-test-aarch64_ver_target_feature // gate-test-csky_target_feature +// gate-test-loongarch_target_feature #[target_feature(enable = "avx512bw")] //~^ ERROR: currently unstable diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index f56efb3bb831..0ec7427c3c45 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `avx512bw` is currently unstable - --> $DIR/gate.rs:22:18 + --> $DIR/gate.rs:23:18 | LL | #[target_feature(enable = "avx512bw")] | ^^^^^^^^^^^^^^^^^^^ From 300d04dc70a28188bf34e4476eb85ecd96f6a99b Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Tue, 24 Oct 2023 11:43:46 +0800 Subject: [PATCH 40/51] tests/ui/abi/compatibility: Set min-llvm-version to 17 for LoongArch64 --- tests/ui/abi/compatibility.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index 1f049b1785a6..0cdf229711ad 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -30,6 +30,7 @@ // revisions: loongarch64 //[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //[loongarch64] needs-llvm-components: loongarch +//[loongarch64] min-llvm-version: 17 // revisions: wasm //[wasm] compile-flags: --target wasm32-unknown-unknown //[wasm] needs-llvm-components: webassembly From ae86f59cc9dd7d4be3c47d9ecbc3b98ca1f514a8 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Mon, 23 Oct 2023 21:35:30 -0700 Subject: [PATCH 41/51] Add test and remove double ref --- compiler/rustc_smir/src/rustc_internal/mod.rs | 6 +- .../ui-fulldeps/stable-mir/check_instance.rs | 33 +++++----- tests/ui-fulldeps/stable-mir/smir_internal.rs | 64 +++++++++++++++++++ 3 files changed, 85 insertions(+), 18 deletions(-) create mode 100644 tests/ui-fulldeps/stable-mir/smir_internal.rs diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index efbf9eba04c3..d3ea8cdc699a 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -142,7 +142,7 @@ scoped_thread_local! (static TLV: Cell<*const ()>); pub(crate) fn init<'tcx>(tables: &TablesWrapper<'tcx>, f: impl FnOnce()) { assert!(!TLV.is_set()); - let ptr: *const () = &tables as *const &_ as _; + let ptr = tables as *const _ as *const (); TLV.set(&Cell::new(ptr), || { f(); }); @@ -155,8 +155,8 @@ pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R TLV.with(|tlv| { let ptr = tlv.get(); assert!(!ptr.is_null()); - let wrapper = unsafe { *(ptr as *const &TablesWrapper<'tcx>) }; - let mut tables = wrapper.0.borrow_mut(); + let wrapper = ptr as *const TablesWrapper<'tcx>; + let mut tables = unsafe { (*wrapper).0.borrow_mut() }; f(&mut *tables) }) } diff --git a/tests/ui-fulldeps/stable-mir/check_instance.rs b/tests/ui-fulldeps/stable-mir/check_instance.rs index c6a9e08ed026..ee82bc77aeda 100644 --- a/tests/ui-fulldeps/stable-mir/check_instance.rs +++ b/tests/ui-fulldeps/stable-mir/check_instance.rs @@ -1,5 +1,5 @@ // run-pass -// Test that users are able to use stable mir APIs to retrieve monomorphized instances +//! Test that users are able to use stable mir APIs to retrieve monomorphized instances // ignore-stage1 // ignore-cross-compile @@ -14,15 +14,15 @@ extern crate rustc_middle; #[macro_use] extern crate rustc_smir; -extern crate stable_mir; extern crate rustc_driver; extern crate rustc_interface; +extern crate stable_mir; -use rustc_middle::ty::TyCtxt; use mir::{mono::Instance, TerminatorKind::*}; -use stable_mir::ty::{TyKind, RigidTy}; -use stable_mir::*; +use rustc_middle::ty::TyCtxt; use rustc_smir::rustc_internal; +use stable_mir::ty::{RigidTy, TyKind}; +use stable_mir::*; use std::io::Write; use std::ops::ControlFlow; @@ -33,16 +33,16 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { let items = stable_mir::all_local_items(); // Get all items and split generic vs monomorphic items. - let (generic, mono) : (Vec<_>, Vec<_>) = items.into_iter().partition(|item| { - item.requires_monomorphization() - }); + let (generic, mono): (Vec<_>, Vec<_>) = + items.into_iter().partition(|item| item.requires_monomorphization()); assert_eq!(mono.len(), 3, "Expected 2 mono functions and one constant"); assert_eq!(generic.len(), 2, "Expected 2 generic functions"); // For all monomorphic items, get the correspondent instances. - let instances = mono.iter().filter_map(|item| { - mir::mono::Instance::try_from(*item).ok() - }).collect::>(); + let instances = mono + .iter() + .filter_map(|item| mir::mono::Instance::try_from(*item).ok()) + .collect::>(); assert_eq!(instances.len(), mono.len()); // For all generic items, try_from should fail. @@ -58,19 +58,22 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { fn test_body(body: mir::Body) { for term in body.blocks.iter().map(|bb| &bb.terminator) { match &term.kind { - Call{ func, .. } => { + Call { func, .. } => { let TyKind::RigidTy(ty) = func.ty(&body.locals).kind() else { unreachable!() }; let RigidTy::FnDef(def, args) = ty else { unreachable!() }; let result = Instance::resolve(def, &args); assert!(result.is_ok()); } - Goto {..} | Assert{..} | SwitchInt{..} | Return | Drop {..} => { /* Do nothing */} - _ => { unreachable!("Unexpected terminator {term:?}") } + Goto { .. } | Assert { .. } | SwitchInt { .. } | Return | Drop { .. } => { + /* Do nothing */ + } + _ => { + unreachable!("Unexpected terminator {term:?}") + } } } } - /// This test will generate and analyze a dummy crate using the stable mir. /// For that, it will first write the dummy crate into a file. /// Then it will create a `StableMir` using custom arguments and then diff --git a/tests/ui-fulldeps/stable-mir/smir_internal.rs b/tests/ui-fulldeps/stable-mir/smir_internal.rs new file mode 100644 index 000000000000..5ad05559cb4b --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/smir_internal.rs @@ -0,0 +1,64 @@ +// run-pass +//! Test that users are able to use retrieve internal constructs from stable ones to help with +//! the migration. + +// ignore-stage1 +// ignore-cross-compile +// ignore-remote +// ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 +// edition: 2021 + +#![feature(rustc_private)] +#![feature(assert_matches)] +#![feature(control_flow_enum)] + +#[macro_use] +extern crate rustc_smir; +extern crate rustc_driver; +extern crate rustc_interface; +extern crate rustc_middle; +extern crate stable_mir; + +use rustc_middle::ty::TyCtxt; +use rustc_smir::rustc_internal; +use std::io::Write; +use std::ops::ControlFlow; + +const CRATE_NAME: &str = "input"; + +fn test_translation(_tcx: TyCtxt<'_>) -> ControlFlow<()> { + let main_fn = stable_mir::entry_fn().unwrap(); + let body = main_fn.body(); + let orig_ty = body.locals[0].ty; + let rustc_ty = rustc_internal::internal(&orig_ty); + assert!(rustc_ty.is_unit()); + ControlFlow::Continue(()) +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// Then it will create a `StableMir` using custom arguments and then +/// it will run the compiler. +fn main() { + let path = "internal_input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + run!(args, tcx, test_translation(tcx)).unwrap(); +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + pub fn main() {{ + }} + "# + )?; + Ok(()) +} From b99b93586fe949f87f20cc65b9f0f1ac738c529d Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 24 Oct 2023 09:46:34 +0300 Subject: [PATCH 42/51] remove change-id assertion in bootstrap test In the bootstrap test, the assertion of the change-id fails whenever we update the change-id next to a breaking change in build configurations. This commit removes the assertion, as it's not critical or useful to have. Signed-off-by: onur-ozkan --- src/bootstrap/bootstrap_test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootstrap/bootstrap_test.py b/src/bootstrap/bootstrap_test.py index 7f16cac78901..e6caabec4f64 100644 --- a/src/bootstrap/bootstrap_test.py +++ b/src/bootstrap/bootstrap_test.py @@ -103,7 +103,6 @@ class GenerateAndParseConfig(unittest.TestCase): """Test that we can serialize and deserialize a config.toml file""" def test_no_args(self): build = serialize_and_parse([]) - self.assertEqual(build.get_toml("change-id"), '116998') self.assertEqual(build.get_toml("profile"), 'dist') self.assertIsNone(build.get_toml("llvm.download-ci-llvm")) From 2b36547e9cf3ff0331953571201e9ce451782c44 Mon Sep 17 00:00:00 2001 From: Arpad Borsos Date: Mon, 21 Aug 2023 10:54:37 +0200 Subject: [PATCH 43/51] Introduce `-C instrument-coverage=branch` to gate branch coverage This flag has to be used in combination with `-Zunstable-options`, and is added in advance of adding branch coverage instrumentation. --- compiler/rustc_session/src/config.rs | 8 +++++++- compiler/rustc_session/src/options.rs | 5 ++++- compiler/rustc_session/src/session.rs | 4 ++++ tests/ui/instrument-coverage/bad-value.bad.stderr | 2 +- tests/ui/instrument-coverage/bad-value.blank.stderr | 2 +- .../ui/instrument-coverage/except-unused-functions.stderr | 2 +- .../ui/instrument-coverage/except-unused-generics.stderr | 2 +- 7 files changed, 19 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 462e7e85c65a..84933588f17f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -169,6 +169,9 @@ pub enum MirSpanview { pub enum InstrumentCoverage { /// Default `-C instrument-coverage` or `-C instrument-coverage=statement` All, + /// Additionally, instrument branches and output branch coverage. + /// `-Zunstable-options -C instrument-coverage=branch` + Branch, /// `-Zunstable-options -C instrument-coverage=except-unused-generics` ExceptUnusedGenerics, /// `-Zunstable-options -C instrument-coverage=except-unused-functions` @@ -2747,7 +2750,10 @@ pub fn build_session_options( } (Some(InstrumentCoverage::Off | InstrumentCoverage::All), _) => {} (Some(_), _) if !unstable_opts.unstable_options => { - handler.early_error("`-C instrument-coverage=except-*` requires `-Z unstable-options`"); + handler.early_error( + "`-C instrument-coverage=branch` and `-C instrument-coverage=except-*` \ + require `-Z unstable-options`", + ); } (None, None) => {} (None, ic) => { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c090bcaf9d8e..77aaf951f0db 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -389,7 +389,7 @@ mod desc { pub const parse_mir_spanview: &str = "`statement` (default), `terminator`, or `block`"; pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`"; pub const parse_instrument_coverage: &str = - "`all` (default), `except-unused-generics`, `except-unused-functions`, or `off`"; + "`all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off`"; pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`"; pub const parse_unpretty: &str = "`string` or `string=string`"; pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; @@ -931,6 +931,7 @@ mod parse { *slot = Some(match v { "all" => InstrumentCoverage::All, + "branch" => InstrumentCoverage::Branch, "except-unused-generics" | "except_unused_generics" => { InstrumentCoverage::ExceptUnusedGenerics } @@ -1356,6 +1357,7 @@ options! { reports (note, the compiler build config must include `profiler = true`); \ implies `-C symbol-mangling-version=v0`. Optional values are: `=all` (implicit value) + `=branch` `=except-unused-generics` `=except-unused-functions` `=off` (default)"), @@ -1597,6 +1599,7 @@ options! { reports (note, the compiler build config must include `profiler = true`); \ implies `-C symbol-mangling-version=v0`. Optional values are: `=all` (implicit value) + `=branch` `=except-unused-generics` `=except-unused-functions` `=off` (default)"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 793074981654..94fe38b72ad1 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -702,6 +702,10 @@ impl Session { self.opts.cg.instrument_coverage() != InstrumentCoverage::Off } + pub fn instrument_coverage_branch(&self) -> bool { + self.opts.cg.instrument_coverage() == InstrumentCoverage::Branch + } + pub fn instrument_coverage_except_unused_generics(&self) -> bool { self.opts.cg.instrument_coverage() == InstrumentCoverage::ExceptUnusedGenerics } diff --git a/tests/ui/instrument-coverage/bad-value.bad.stderr b/tests/ui/instrument-coverage/bad-value.bad.stderr index 246c4f31a4ba..b867d169dae5 100644 --- a/tests/ui/instrument-coverage/bad-value.bad.stderr +++ b/tests/ui/instrument-coverage/bad-value.bad.stderr @@ -1,2 +1,2 @@ -error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected +error: incorrect value `bad-value` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected diff --git a/tests/ui/instrument-coverage/bad-value.blank.stderr b/tests/ui/instrument-coverage/bad-value.blank.stderr index b539c558d9ba..e7122fb61cdf 100644 --- a/tests/ui/instrument-coverage/bad-value.blank.stderr +++ b/tests/ui/instrument-coverage/bad-value.blank.stderr @@ -1,2 +1,2 @@ -error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `except-unused-generics`, `except-unused-functions`, or `off` was expected +error: incorrect value `` for codegen option `instrument-coverage` - `all` (default), `branch`, `except-unused-generics`, `except-unused-functions`, or `off` was expected diff --git a/tests/ui/instrument-coverage/except-unused-functions.stderr b/tests/ui/instrument-coverage/except-unused-functions.stderr index 82c1c630cbf2..acc633a2a6d2 100644 --- a/tests/ui/instrument-coverage/except-unused-functions.stderr +++ b/tests/ui/instrument-coverage/except-unused-functions.stderr @@ -1,2 +1,2 @@ -error: `-C instrument-coverage=except-*` requires `-Z unstable-options` +error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` diff --git a/tests/ui/instrument-coverage/except-unused-generics.stderr b/tests/ui/instrument-coverage/except-unused-generics.stderr index 82c1c630cbf2..acc633a2a6d2 100644 --- a/tests/ui/instrument-coverage/except-unused-generics.stderr +++ b/tests/ui/instrument-coverage/except-unused-generics.stderr @@ -1,2 +1,2 @@ -error: `-C instrument-coverage=except-*` requires `-Z unstable-options` +error: `-C instrument-coverage=branch` and `-C instrument-coverage=except-*` require `-Z unstable-options` From 712106b1229f48e71a6365f5e5bf171403105750 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 23 Oct 2023 16:34:33 +0000 Subject: [PATCH 44/51] Add regression test for #117058 --- .../statement-attribute-validation.rs | 39 +++++++++++++ .../statement-attribute-validation.stderr | 56 +++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 tests/ui/attributes/statement-attribute-validation.rs create mode 100644 tests/ui/attributes/statement-attribute-validation.stderr diff --git a/tests/ui/attributes/statement-attribute-validation.rs b/tests/ui/attributes/statement-attribute-validation.rs new file mode 100644 index 000000000000..31407364acfe --- /dev/null +++ b/tests/ui/attributes/statement-attribute-validation.rs @@ -0,0 +1,39 @@ +// test for #117058 - check that attributes are validated on various kinds of statements. + +struct A; + +fn func() {} + +fn main() { + #[allow(two-words)] + //~^ ERROR expected one of `(`, `,`, `::`, or `=`, found `-` + if true { + } else { + } + #[allow(two-words)] + //~^ ERROR expected one of `(`, `,`, `::`, or `=`, found `-` + (1); + #[allow(two-words)] + //~^ ERROR expected one of `(`, `,`, `::`, or `=`, found `-` + match 1 { + _ => {} + } + #[allow(two-words)] + //~^ ERROR expected one of `(`, `,`, `::`, or `=`, found `-` + while false {} + #[allow(two-words)] + //~^ ERROR expected one of `(`, `,`, `::`, or `=`, found `-` + {} + #[allow(two-words)] + //~^ ERROR expected one of `(`, `,`, `::`, or `=`, found `-` + A {}; + #[allow(two-words)] + //~^ ERROR expected one of `(`, `,`, `::`, or `=`, found `-` + func(); + #[allow(two-words)] + //~^ ERROR expected one of `(`, `,`, `::`, or `=`, found `-` + A; + #[allow(two-words)] + //~^ ERROR expected one of `(`, `,`, `::`, or `=`, found `-` + loop {} +} diff --git a/tests/ui/attributes/statement-attribute-validation.stderr b/tests/ui/attributes/statement-attribute-validation.stderr new file mode 100644 index 000000000000..06f447be5626 --- /dev/null +++ b/tests/ui/attributes/statement-attribute-validation.stderr @@ -0,0 +1,56 @@ +error: expected one of `(`, `,`, `::`, or `=`, found `-` + --> $DIR/statement-attribute-validation.rs:8:16 + | +LL | #[allow(two-words)] + | ^ expected one of `(`, `,`, `::`, or `=` + +error: expected one of `(`, `,`, `::`, or `=`, found `-` + --> $DIR/statement-attribute-validation.rs:13:16 + | +LL | #[allow(two-words)] + | ^ expected one of `(`, `,`, `::`, or `=` + +error: expected one of `(`, `,`, `::`, or `=`, found `-` + --> $DIR/statement-attribute-validation.rs:16:16 + | +LL | #[allow(two-words)] + | ^ expected one of `(`, `,`, `::`, or `=` + +error: expected one of `(`, `,`, `::`, or `=`, found `-` + --> $DIR/statement-attribute-validation.rs:21:16 + | +LL | #[allow(two-words)] + | ^ expected one of `(`, `,`, `::`, or `=` + +error: expected one of `(`, `,`, `::`, or `=`, found `-` + --> $DIR/statement-attribute-validation.rs:24:16 + | +LL | #[allow(two-words)] + | ^ expected one of `(`, `,`, `::`, or `=` + +error: expected one of `(`, `,`, `::`, or `=`, found `-` + --> $DIR/statement-attribute-validation.rs:27:16 + | +LL | #[allow(two-words)] + | ^ expected one of `(`, `,`, `::`, or `=` + +error: expected one of `(`, `,`, `::`, or `=`, found `-` + --> $DIR/statement-attribute-validation.rs:30:16 + | +LL | #[allow(two-words)] + | ^ expected one of `(`, `,`, `::`, or `=` + +error: expected one of `(`, `,`, `::`, or `=`, found `-` + --> $DIR/statement-attribute-validation.rs:33:16 + | +LL | #[allow(two-words)] + | ^ expected one of `(`, `,`, `::`, or `=` + +error: expected one of `(`, `,`, `::`, or `=`, found `-` + --> $DIR/statement-attribute-validation.rs:36:16 + | +LL | #[allow(two-words)] + | ^ expected one of `(`, `,`, `::`, or `=` + +error: aborting due to 9 previous errors + From 68f5536667ca2d60ac8275fe3bf5b6549f96d2f2 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Tue, 3 Oct 2023 20:17:40 +0300 Subject: [PATCH 45/51] Migrate diagnostics in `rustc_hir_analysis/src/coherence/orphan.rs` --- compiler/rustc_hir_analysis/messages.ftl | 41 +++ .../src/coherence/orphan.rs | 291 ++++++++---------- compiler/rustc_hir_analysis/src/errors.rs | 172 ++++++++++- 3 files changed, 341 insertions(+), 163 deletions(-) diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 6bf6650986a6..e8d9918be22d 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -72,6 +72,12 @@ hir_analysis_copy_impl_on_type_with_dtor = the trait `Copy` cannot be implemented for this type; the type has a destructor .label = `Copy` not allowed on types with destructors +hir_analysis_cross_crate_traits = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type, not `{$self_ty}` + .label = can't implement cross-crate trait with a default impl for non-struct/enum type + +hir_analysis_cross_crate_traits_defined = cross-crate traits with a default impl, like `{$traits}`, can only be implemented for a struct/enum type defined in the current crate + .label = can't implement cross-crate trait for type in another crate + hir_analysis_dispatch_from_dyn_multi = implementing the `DispatchFromDyn` trait requires multiple coercions .note = the trait `DispatchFromDyn` may only be implemented for a coercion between structures with a single field being coerced .coercions_note = currently, {$number} fields need coercions: {$coercions} @@ -237,6 +243,28 @@ hir_analysis_must_implement_not_function_span_note = required by this annotation hir_analysis_must_implement_one_of_attribute = the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +hir_analysis_only_current_traits_arbitrary = only traits defined in the current crate can be implemented for arbitrary types + +hir_analysis_only_current_traits_foreign = this is not defined in the current crate because this is a foreign trait + +hir_analysis_only_current_traits_label = impl doesn't use only types from inside the current crate + +hir_analysis_only_current_traits_name = this is not defined in the current crate because {$name} are always foreign + +hir_analysis_only_current_traits_note = define and implement a trait or new type instead + +hir_analysis_only_current_traits_opaque = type alias impl trait is treated as if it were foreign, because its hidden type could be from a foreign crate + +hir_analysis_only_current_traits_outside = only traits defined in the current crate can be implemented for types defined outside of the crate + +hir_analysis_only_current_traits_pointer = `{$pointer}` is not defined in the current crate because raw pointers are always foreign + +hir_analysis_only_current_traits_pointer_sugg = consider introducing a new wrapper type + +hir_analysis_only_current_traits_primitive = only traits defined in the current crate can be implemented for primitive types + +hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate + hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it @@ -326,6 +354,9 @@ hir_analysis_trait_object_declared_with_no_traits = at least one trait is required for an object type .alias_span = this alias does not contain a trait +hir_analysis_traits_with_defualt_impl = traits with a default impl, like `{$traits}`, cannot be implemented for {$problematic_kind} `{$self_ty}` + .note = a trait object implements `{$traits}` if and only if `{$traits}` is one of the trait object's trait bounds + hir_analysis_transparent_enum_variant = transparent enum needs exactly one variant, but has {$number} .label = needs exactly one variant, but has {$number} .many_label = too many variants in `{$path}` @@ -339,6 +370,16 @@ hir_analysis_transparent_non_zero_sized_enum = the variant of a transparent {$de .label = needs at most one field with non-trivial size or alignment, but has {$field_count} .labels = this field has non-zero size or requires alignment +hir_analysis_ty_param_first_local = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`) + .label = type parameter `{$param_ty}` must be covered by another type when it appears before the first local type (`{$local_type}`) + .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type + .case_note = in this case, 'before' refers to the following order: `impl<..> ForeignTrait for T0`, where `T0` is the first and `Tn` is the last + +hir_analysis_ty_param_some = type parameter `{$param_ty}` must be used as the type parameter for some local type (e.g., `MyStruct<{$param_ty}>`) + .label = type parameter `{$param_ty}` must be used as the type parameter for some local type + .note = implementing a foreign trait is only possible if at least one of the types for which it is implemented is local + .only_note = only traits defined in the current crate can be implemented for a type parameter + hir_analysis_type_of = {$type_of} hir_analysis_typeof_reserved_keyword_used = diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index faddb0c38298..7eeb7837467f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -2,8 +2,7 @@ //! crate or pertains to a type defined in this crate. use rustc_data_structures::fx::FxHashSet; -use rustc_errors::{struct_span_err, DelayDm}; -use rustc_errors::{Diagnostic, ErrorGuaranteed}; +use rustc_errors::{DelayDm, ErrorGuaranteed}; use rustc_hir as hir; use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::GenericArgs; @@ -17,6 +16,8 @@ use rustc_span::Span; use rustc_trait_selection::traits; use std::ops::ControlFlow; +use crate::errors; + #[instrument(skip(tcx), level = "debug")] pub(crate) fn orphan_check_impl( tcx: TyCtxt<'_>, @@ -259,49 +260,30 @@ fn do_orphan_check_impl<'tcx>( match local_impl { LocalImpl::Allow => {} LocalImpl::Disallow { problematic_kind } => { - let msg = format!( - "traits with a default impl, like `{trait}`, \ - cannot be implemented for {problematic_kind} `{self_ty}`", - trait = tcx.def_path_str(trait_def_id), - ); - let label = format!( - "a trait object implements `{trait}` if and only if `{trait}` \ - is one of the trait object's trait bounds", - trait = tcx.def_path_str(trait_def_id), - ); - let sp = tcx.def_span(def_id); - let reported = - struct_span_err!(tcx.sess, sp, E0321, "{}", msg).note(label).emit(); - return Err(reported); + return Err(tcx.sess.emit_err(errors::TraitsWithDefaultImpl { + span: tcx.def_span(def_id), + traits: tcx.def_path_str(trait_def_id), + problematic_kind, + self_ty, + })); } } } else { - if let Some((msg, label)) = match nonlocal_impl { - NonlocalImpl::Allow => None, - NonlocalImpl::DisallowBecauseNonlocal => Some(( - format!( - "cross-crate traits with a default impl, like `{}`, \ - can only be implemented for a struct/enum type \ - defined in the current crate", - tcx.def_path_str(trait_def_id) - ), - "can't implement cross-crate trait for type in another crate", - )), - NonlocalImpl::DisallowOther => Some(( - format!( - "cross-crate traits with a default impl, like `{}`, can \ - only be implemented for a struct/enum type, not `{}`", - tcx.def_path_str(trait_def_id), - self_ty - ), - "can't implement cross-crate trait with a default impl for \ - non-struct/enum type", - )), - } { - let sp = tcx.def_span(def_id); - let reported = - struct_span_err!(tcx.sess, sp, E0321, "{}", msg).span_label(sp, label).emit(); - return Err(reported); + match nonlocal_impl { + NonlocalImpl::Allow => {} + NonlocalImpl::DisallowBecauseNonlocal => { + return Err(tcx.sess.emit_err(errors::CrossCrateTraitsDefined { + span: tcx.def_span(def_id), + traits: tcx.def_path_str(trait_def_id), + })); + } + NonlocalImpl::DisallowOther => { + return Err(tcx.sess.emit_err(errors::CrossCrateTraits { + span: tcx.def_span(def_id), + traits: tcx.def_path_str(trait_def_id), + self_ty, + })); + } } } } @@ -322,19 +304,18 @@ fn emit_orphan_check_error<'tcx>( let self_ty = trait_ref.self_ty(); Err(match err { traits::OrphanCheckErr::NonLocalInputType(tys) => { - let msg = match self_ty.kind() { - ty::Adt(..) => "can be implemented for types defined outside of the crate", - _ if self_ty.is_primitive() => "can be implemented for primitive types", - _ => "can be implemented for arbitrary types", - }; - let mut err = struct_span_err!( - tcx.sess, - sp, - E0117, - "only traits defined in the current crate {msg}" - ); - err.span_label(sp, "impl doesn't use only types from inside the current crate"); + let (mut opaque, mut foreign, mut name, mut pointer, mut ty_diag) = + (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new()); + let mut sugg = None; for &(mut ty, is_target_ty) in &tys { + let span = if is_target_ty { + // Point at `D` in `impl for C in D` + self_ty_span + } else { + // Point at `C` in `impl for C in D` + trait_span + }; + ty = tcx.erase_regions(ty); ty = match ty.kind() { // Remove the type arguments from the output, as they are not relevant. @@ -345,50 +326,103 @@ fn emit_orphan_check_error<'tcx>( ty::Adt(def, _) => Ty::new_adt(tcx, *def, ty::List::empty()), _ => ty, }; - let msg = |ty: &str, postfix: &str| { - format!("{ty} is not defined in the current crate{postfix}") - }; - let this = |name: &str| { - if !trait_ref.def_id.is_local() && !is_target_ty { - msg("this", " because this is a foreign trait") + fn push_to_foreign_or_name<'tcx>( + is_foreign: bool, + foreign: &mut Vec, + name: &mut Vec>, + span: Span, + sname: &'tcx str, + ) { + if is_foreign { + foreign.push(errors::OnlyCurrentTraitsForeign { span }) } else { - msg("this", &format!(" because {name} are always foreign")) + name.push(errors::OnlyCurrentTraitsName { span, name: sname }); + } + } + + let is_foreign = !trait_ref.def_id.is_local() && !is_target_ty; + + match &ty.kind() { + ty::Slice(_) => { + push_to_foreign_or_name( + is_foreign, + &mut foreign, + &mut name, + span, + "slices", + ); + } + ty::Array(..) => { + push_to_foreign_or_name( + is_foreign, + &mut foreign, + &mut name, + span, + "arrays", + ); + } + ty::Tuple(..) => { + push_to_foreign_or_name( + is_foreign, + &mut foreign, + &mut name, + span, + "tuples", + ); } - }; - let msg = match &ty.kind() { - ty::Slice(_) => this("slices"), - ty::Array(..) => this("arrays"), - ty::Tuple(..) => this("tuples"), ty::Alias(ty::Opaque, ..) => { - "type alias impl trait is treated as if it were foreign, \ - because its hidden type could be from a foreign crate" - .to_string() + opaque.push(errors::OnlyCurrentTraitsOpaque { span }) } ty::RawPtr(ptr_ty) => { - emit_newtype_suggestion_for_raw_ptr( - full_impl_span, - self_ty, - self_ty_span, - ptr_ty, - &mut err, - ); - - msg(&format!("`{ty}`"), " because raw pointers are always foreign") + if !self_ty.has_param() { + let mut_key = ptr_ty.mutbl.prefix_str(); + sugg = Some(errors::OnlyCurrentTraitsPointerSugg { + wrapper_span: self_ty_span, + struct_span: full_impl_span.shrink_to_lo(), + mut_key, + ptr_ty: ptr_ty.ty, + }); + } + pointer.push(errors::OnlyCurrentTraitsPointer { span, pointer: ty }); } - _ => msg(&format!("`{ty}`"), ""), - }; - - if is_target_ty { - // Point at `D` in `impl for C in D` - err.span_label(self_ty_span, msg); - } else { - // Point at `C` in `impl for C in D` - err.span_label(trait_span, msg); + _ => ty_diag.push(errors::OnlyCurrentTraitsTy { span, ty }), } } - err.note("define and implement a trait or new type instead"); - err.emit() + + let err_struct = match self_ty.kind() { + ty::Adt(..) => errors::OnlyCurrentTraits::Outside { + span: sp, + note: (), + opaque, + foreign, + name, + pointer, + ty: ty_diag, + sugg, + }, + _ if self_ty.is_primitive() => errors::OnlyCurrentTraits::Primitive { + span: sp, + note: (), + opaque, + foreign, + name, + pointer, + ty: ty_diag, + sugg, + }, + _ => errors::OnlyCurrentTraits::Arbitrary { + span: sp, + note: (), + opaque, + foreign, + name, + pointer, + ty: ty_diag, + sugg, + }, + }; + tcx.sess.emit_err(err_struct) } traits::OrphanCheckErr::UncoveredTy(param_ty, local_type) => { let mut sp = sp; @@ -399,85 +433,18 @@ fn emit_orphan_check_error<'tcx>( } match local_type { - Some(local_type) => struct_span_err!( - tcx.sess, - sp, - E0210, - "type parameter `{}` must be covered by another type \ - when it appears before the first local type (`{}`)", + Some(local_type) => tcx.sess.emit_err(errors::TyParamFirstLocal { + span: sp, + note: (), param_ty, - local_type - ) - .span_label( - sp, - format!( - "type parameter `{param_ty}` must be covered by another type \ - when it appears before the first local type (`{local_type}`)" - ), - ) - .note( - "implementing a foreign trait is only possible if at \ - least one of the types for which it is implemented is local, \ - and no uncovered type parameters appear before that first \ - local type", - ) - .note( - "in this case, 'before' refers to the following order: \ - `impl<..> ForeignTrait for T0`, \ - where `T0` is the first and `Tn` is the last", - ) - .emit(), - None => struct_span_err!( - tcx.sess, - sp, - E0210, - "type parameter `{}` must be used as the type parameter for some \ - local type (e.g., `MyStruct<{}>`)", - param_ty, - param_ty - ) - .span_label( - sp, - format!( - "type parameter `{param_ty}` must be used as the type parameter for some \ - local type", - ), - ) - .note( - "implementing a foreign trait is only possible if at \ - least one of the types for which it is implemented is local", - ) - .note( - "only traits defined in the current crate can be \ - implemented for a type parameter", - ) - .emit(), + local_type, + }), + None => tcx.sess.emit_err(errors::TyParamSome { span: sp, note: (), param_ty }), } } }) } -fn emit_newtype_suggestion_for_raw_ptr( - full_impl_span: Span, - self_ty: Ty<'_>, - self_ty_span: Span, - ptr_ty: &ty::TypeAndMut<'_>, - diag: &mut Diagnostic, -) { - if !self_ty.has_param() { - let mut_key = ptr_ty.mutbl.prefix_str(); - let msg_sugg = "consider introducing a new wrapper type".to_owned(); - let sugg = vec![ - ( - full_impl_span.shrink_to_lo(), - format!("struct WrapperType(*{}{});\n\n", mut_key, ptr_ty.ty), - ), - (self_ty_span, "WrapperType".to_owned()), - ]; - diag.multipart_suggestion(msg_sugg, sugg, rustc_errors::Applicability::MaybeIncorrect); - } -} - /// Lint impls of auto traits if they are likely to have /// unsound or surprising effects on auto impls. fn lint_auto_trait_impl<'tcx>( diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 189564d4e339..6a2db1d06276 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -683,7 +683,6 @@ pub(crate) struct SIMDFFIHighlyExperimental { } #[derive(Diagnostic)] - pub enum ImplNotMarkedDefault { #[diag(hir_analysis_impl_not_marked_default, code = "E0520")] #[note] @@ -1159,3 +1158,174 @@ pub struct ImplForTyRequires { pub trait_name: String, pub ty: String, } + +#[derive(Diagnostic)] +#[diag(hir_analysis_traits_with_defualt_impl, code = "E0321")] +#[note] +pub struct TraitsWithDefaultImpl<'a> { + #[primary_span] + pub span: Span, + pub traits: String, + pub problematic_kind: &'a str, + pub self_ty: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_cross_crate_traits, code = "E0321")] +pub struct CrossCrateTraits<'a> { + #[primary_span] + #[label] + pub span: Span, + pub traits: String, + pub self_ty: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_cross_crate_traits_defined, code = "E0321")] +pub struct CrossCrateTraitsDefined { + #[primary_span] + #[label] + pub span: Span, + pub traits: String, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_ty_param_first_local, code = "E0210")] +#[note] +pub struct TyParamFirstLocal<'a> { + #[primary_span] + #[label] + pub span: Span, + #[note(hir_analysis_case_note)] + pub note: (), + pub param_ty: Ty<'a>, + pub local_type: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag(hir_analysis_ty_param_some, code = "E0210")] +#[note] +pub struct TyParamSome<'a> { + #[primary_span] + #[label] + pub span: Span, + #[note(hir_analysis_only_note)] + pub note: (), + pub param_ty: Ty<'a>, +} + +#[derive(Diagnostic)] +pub enum OnlyCurrentTraits<'a> { + #[diag(hir_analysis_only_current_traits_outside, code = "E0117")] + Outside { + #[primary_span] + #[label(hir_analysis_only_current_traits_label)] + span: Span, + #[note(hir_analysis_only_current_traits_note)] + note: (), + #[subdiagnostic] + opaque: Vec, + #[subdiagnostic] + foreign: Vec, + #[subdiagnostic] + name: Vec>, + #[subdiagnostic] + pointer: Vec>, + #[subdiagnostic] + ty: Vec>, + #[subdiagnostic] + sugg: Option>, + }, + #[diag(hir_analysis_only_current_traits_primitive, code = "E0117")] + Primitive { + #[primary_span] + #[label(hir_analysis_only_current_traits_label)] + span: Span, + #[note(hir_analysis_only_current_traits_note)] + note: (), + #[subdiagnostic] + opaque: Vec, + #[subdiagnostic] + foreign: Vec, + #[subdiagnostic] + name: Vec>, + #[subdiagnostic] + pointer: Vec>, + #[subdiagnostic] + ty: Vec>, + #[subdiagnostic] + sugg: Option>, + }, + #[diag(hir_analysis_only_current_traits_arbitrary, code = "E0117")] + Arbitrary { + #[primary_span] + #[label(hir_analysis_only_current_traits_label)] + span: Span, + #[note(hir_analysis_only_current_traits_note)] + note: (), + #[subdiagnostic] + opaque: Vec, + #[subdiagnostic] + foreign: Vec, + #[subdiagnostic] + name: Vec>, + #[subdiagnostic] + pointer: Vec>, + #[subdiagnostic] + ty: Vec>, + #[subdiagnostic] + sugg: Option>, + }, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_opaque)] +pub struct OnlyCurrentTraitsOpaque { + #[primary_span] + pub span: Span, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_foreign)] +pub struct OnlyCurrentTraitsForeign { + #[primary_span] + pub span: Span, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_name)] +pub struct OnlyCurrentTraitsName<'a> { + #[primary_span] + pub span: Span, + pub name: &'a str, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_pointer)] +pub struct OnlyCurrentTraitsPointer<'a> { + #[primary_span] + pub span: Span, + pub pointer: Ty<'a>, +} + +#[derive(Subdiagnostic)] +#[label(hir_analysis_only_current_traits_ty)] +pub struct OnlyCurrentTraitsTy<'a> { + #[primary_span] + pub span: Span, + pub ty: Ty<'a>, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + hir_analysis_only_current_traits_pointer_sugg, + applicability = "maybe-incorrect" +)] +pub struct OnlyCurrentTraitsPointerSugg<'a> { + #[suggestion_part(code = "WrapperType")] + pub wrapper_span: Span, + #[suggestion_part(code = "struct WrapperType(*{mut_key}{ptr_ty});\n\n")] + pub struct_span: Span, + pub mut_key: &'a str, + pub ptr_ty: Ty<'a>, +} From 9c85dfa1d755004b5499f45e2fd921c298f90a2e Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 24 Oct 2023 15:16:51 +0000 Subject: [PATCH 46/51] Tweak test to avoid platform dependency. --- .../struct.main.DataflowConstProp.32bit.diff | 14 +++++++------- .../struct.main.DataflowConstProp.64bit.diff | 14 +++++++------- tests/mir-opt/dataflow-const-prop/struct.rs | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff index 944b061f9939..8499d0a89c37 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff @@ -16,7 +16,7 @@ let mut _26: &&BigStruct; let mut _28: f32; let mut _29: std::option::Option; - let mut _30: &[f64]; + let mut _30: &[f32]; let mut _31: &SmallStruct; let mut _32: &SmallStruct; let mut _33: &SmallStruct; @@ -52,14 +52,14 @@ debug ss => _15; let _19: f32; let _20: std::option::Option; - let _21: &[f64]; + let _21: &[f32]; scope 7 { debug a => _19; debug b => _20; debug c => _21; let _23: f32; let _24: std::option::Option; - let _25: &[f64]; + let _25: &[f32]; scope 8 { debug a => _23; debug b => _24; @@ -146,7 +146,7 @@ StorageLive(_20); _20 = (_22.1: std::option::Option); StorageLive(_21); - _21 = (_22.2: &[f64]); + _21 = (_22.2: &[f32]); StorageDead(_22); StorageLive(_26); _26 = const {ALLOC5: &&BigStruct}; @@ -161,7 +161,7 @@ + _24 = const Option::::Some(S(35_i32)); StorageLive(_25); _38 = deref_copy (*_26); - _25 = ((*_38).2: &[f64]); + _25 = ((*_38).2: &[f32]); StorageDead(_26); StorageLive(_27); StorageLive(_28); @@ -228,8 +228,8 @@ 0x10 │ 00 00 a4 42 │ ...B } - ALLOC1 (size: 16, align: 4) { - 00 00 00 00 00 80 46 40 00 00 00 00 00 00 52 40 │ ......F@......R@ + ALLOC1 (size: 8, align: 4) { + 00 00 34 42 00 00 90 42 │ ..4B...B } ALLOC4 (static: SMALL_STAT, size: 4, align: 4) { diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff index c2c95657a2a3..01ec3f623d1a 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff +++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff @@ -16,7 +16,7 @@ let mut _26: &&BigStruct; let mut _28: f32; let mut _29: std::option::Option; - let mut _30: &[f64]; + let mut _30: &[f32]; let mut _31: &SmallStruct; let mut _32: &SmallStruct; let mut _33: &SmallStruct; @@ -52,14 +52,14 @@ debug ss => _15; let _19: f32; let _20: std::option::Option; - let _21: &[f64]; + let _21: &[f32]; scope 7 { debug a => _19; debug b => _20; debug c => _21; let _23: f32; let _24: std::option::Option; - let _25: &[f64]; + let _25: &[f32]; scope 8 { debug a => _23; debug b => _24; @@ -146,7 +146,7 @@ StorageLive(_20); _20 = (_22.1: std::option::Option); StorageLive(_21); - _21 = (_22.2: &[f64]); + _21 = (_22.2: &[f32]); StorageDead(_22); StorageLive(_26); _26 = const {ALLOC5: &&BigStruct}; @@ -161,7 +161,7 @@ + _24 = const Option::::Some(S(35_i32)); StorageLive(_25); _38 = deref_copy (*_26); - _25 = ((*_38).2: &[f64]); + _25 = ((*_38).2: &[f32]); StorageDead(_26); StorageLive(_27); StorageLive(_28); @@ -228,8 +228,8 @@ 0x10 │ 02 00 00 00 00 00 00 00 00 00 a4 42 __ __ __ __ │ ...........B░░░░ } - ALLOC1 (size: 16, align: 8) { - 00 00 00 00 00 80 46 40 00 00 00 00 00 00 52 40 │ ......F@......R@ + ALLOC1 (size: 8, align: 4) { + 00 00 34 42 00 00 90 42 │ ..4B...B } ALLOC4 (static: SMALL_STAT, size: 8, align: 8) { diff --git a/tests/mir-opt/dataflow-const-prop/struct.rs b/tests/mir-opt/dataflow-const-prop/struct.rs index 030f3c0c4ded..043981a29548 100644 --- a/tests/mir-opt/dataflow-const-prop/struct.rs +++ b/tests/mir-opt/dataflow-const-prop/struct.rs @@ -9,7 +9,7 @@ struct S(i32); struct SmallStruct(f32, Option, &'static [f32]); #[derive(Copy, Clone)] -struct BigStruct(f32, Option, &'static [f64]); +struct BigStruct(f32, Option, &'static [f32]); // EMIT_MIR struct.main.DataflowConstProp.diff fn main() { From 90e3aaeca2b5c88a652d78389c2a927abfb66e4c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 24 Oct 2023 15:27:02 +0000 Subject: [PATCH 47/51] Remove incomplete features from RPITIT/AFIT tests --- .../async-example-desugared-boxed-in-trait.rs | 2 -- ...async-example-desugared-boxed-in-trait.stderr | 4 ++-- .../in-trait/async-example-desugared-boxed.rs | 2 -- .../async-example-desugared-boxed.stderr | 2 +- .../in-trait/async-example-desugared-extra.rs | 1 - .../in-trait/async-example-desugared-in-trait.rs | 2 -- .../in-trait/async-example-desugared-manual.rs | 2 -- .../async-example-desugared-manual.stderr | 2 +- .../in-trait/async-example-desugared.rs | 2 -- tests/ui/async-await/in-trait/async-example.rs | 2 -- .../in-trait/async-generics-and-bounds.rs | 2 -- .../in-trait/async-generics-and-bounds.stderr | 4 ++-- tests/ui/async-await/in-trait/async-generics.rs | 2 -- .../async-await/in-trait/async-generics.stderr | 4 ++-- .../in-trait/async-lifetimes-and-bounds.rs | 2 -- tests/ui/async-await/in-trait/async-lifetimes.rs | 2 -- .../in-trait/async-recursive-generic.rs | 2 -- .../in-trait/async-recursive-generic.stderr | 2 +- tests/ui/async-await/in-trait/async-recursive.rs | 2 -- .../async-await/in-trait/async-recursive.stderr | 2 +- tests/ui/async-await/in-trait/early-bound-1.rs | 2 -- tests/ui/impl-trait/in-trait/deep-match.rs | 2 -- tests/ui/impl-trait/in-trait/deep-match.stderr | 2 +- .../impl-trait/in-trait/default-body-type-err.rs | 2 -- .../in-trait/default-body-type-err.stderr | 2 +- tests/ui/impl-trait/in-trait/doesnt-satisfy.rs | 2 -- .../ui/impl-trait/in-trait/doesnt-satisfy.stderr | 4 ++-- .../ui/impl-trait/in-trait/generics-mismatch.rs | 2 -- .../impl-trait/in-trait/generics-mismatch.stderr | 2 +- tests/ui/impl-trait/in-trait/issue-102140.rs | 2 -- tests/ui/impl-trait/in-trait/issue-102140.stderr | 6 +++--- tests/ui/impl-trait/in-trait/issue-102571.rs | 2 -- tests/ui/impl-trait/in-trait/issue-102571.stderr | 2 +- tests/ui/impl-trait/in-trait/object-safety.rs | 2 -- .../ui/impl-trait/in-trait/object-safety.stderr | 16 ++++++++-------- .../in-trait/opaque-in-impl-is-opaque.rs | 2 -- .../in-trait/opaque-in-impl-is-opaque.stderr | 2 +- .../in-trait/trait-more-generics-than-impl.rs | 2 -- .../trait-more-generics-than-impl.stderr | 2 +- 39 files changed, 29 insertions(+), 74 deletions(-) diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs index 3cc11d241f70..c26f6625f009 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs @@ -1,7 +1,5 @@ // edition: 2021 -#![allow(incomplete_features)] - use std::future::Future; use std::pin::Pin; diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr index e6dd83b6b0a8..b70b36adb4a5 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr @@ -1,11 +1,11 @@ error[E0053]: method `foo` has an incompatible type for trait - --> $DIR/async-example-desugared-boxed-in-trait.rs:13:5 + --> $DIR/async-example-desugared-boxed-in-trait.rs:11:5 | LL | async fn foo(&self) -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Pin>>`, found future | note: type in trait - --> $DIR/async-example-desugared-boxed-in-trait.rs:9:22 + --> $DIR/async-example-desugared-boxed-in-trait.rs:7:22 | LL | fn foo(&self) -> Pin + '_>>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs index 81d25ce27ae0..c5a9841029e3 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs @@ -1,7 +1,5 @@ // edition: 2021 -#![allow(incomplete_features)] - use std::future::Future; use std::pin::Pin; diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr index cd18790fdfbb..6392ce86e4a0 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr @@ -1,5 +1,5 @@ error: method `foo` should be async because the method from the trait is async - --> $DIR/async-example-desugared-boxed.rs:13:5 + --> $DIR/async-example-desugared-boxed.rs:11:5 | LL | async fn foo(&self) -> i32; | --------------------------- required because the trait method is async diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs index f0c59180fb50..ce93bd626081 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs @@ -2,7 +2,6 @@ // edition: 2021 #![feature(lint_reasons)] -#![allow(incomplete_features)] use std::future::Future; use std::pin::Pin; diff --git a/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs index deca28af8535..f7a351efff56 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs @@ -1,8 +1,6 @@ // check-pass // edition: 2021 -#![allow(incomplete_features)] - use std::future::Future; trait MyTrait { diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs index fdba4d93c770..c287b9a5b847 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs @@ -1,7 +1,5 @@ // edition: 2021 -#![allow(incomplete_features)] - use std::future::Future; use std::task::Poll; diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr index 463892f21bf2..1eda6fe6532a 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr +++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr @@ -1,5 +1,5 @@ error: method `foo` should be async because the method from the trait is async - --> $DIR/async-example-desugared-manual.rs:21:5 + --> $DIR/async-example-desugared-manual.rs:19:5 | LL | async fn foo(&self) -> i32; | --------------------------- required because the trait method is async diff --git a/tests/ui/async-await/in-trait/async-example-desugared.rs b/tests/ui/async-await/in-trait/async-example-desugared.rs index 7fc78f7da6db..78904d87abcd 100644 --- a/tests/ui/async-await/in-trait/async-example-desugared.rs +++ b/tests/ui/async-await/in-trait/async-example-desugared.rs @@ -1,8 +1,6 @@ // check-pass // edition: 2021 -#![allow(incomplete_features)] - use std::future::Future; trait MyTrait { diff --git a/tests/ui/async-await/in-trait/async-example.rs b/tests/ui/async-await/in-trait/async-example.rs index 62ed490bf059..a32f979df6ba 100644 --- a/tests/ui/async-await/in-trait/async-example.rs +++ b/tests/ui/async-await/in-trait/async-example.rs @@ -1,8 +1,6 @@ // check-pass // edition: 2021 -#![allow(incomplete_features)] - trait MyTrait { #[allow(async_fn_in_trait)] async fn foo(&self) -> i32; diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs index 4e859fb27a91..8dc0574c757a 100644 --- a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs +++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs @@ -2,8 +2,6 @@ // known-bug: #102682 // edition: 2021 -#![allow(incomplete_features)] - use std::fmt::Debug; use std::hash::Hash; diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr index d7251a528633..3cc35b21409a 100644 --- a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr +++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr @@ -1,5 +1,5 @@ error[E0311]: the parameter type `U` may not live long enough - --> $DIR/async-generics-and-bounds.rs:11:5 + --> $DIR/async-generics-and-bounds.rs:9:5 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; | ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | async fn foo<'a>(&'a self) -> &'a (T, U) where T: Debug + Sized, U: Has | ++++ ++ ++ +++++++ error[E0311]: the parameter type `T` may not live long enough - --> $DIR/async-generics-and-bounds.rs:11:5 + --> $DIR/async-generics-and-bounds.rs:9:5 | LL | async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash; | ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/in-trait/async-generics.rs b/tests/ui/async-await/in-trait/async-generics.rs index 2d3425928482..6004916a4e50 100644 --- a/tests/ui/async-await/in-trait/async-generics.rs +++ b/tests/ui/async-await/in-trait/async-generics.rs @@ -2,8 +2,6 @@ // known-bug: #102682 // edition: 2021 -#![allow(incomplete_features)] - trait MyTrait { async fn foo(&self) -> &(T, U); } diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.stderr index aec62d122015..3b27f8fe2f09 100644 --- a/tests/ui/async-await/in-trait/async-generics.stderr +++ b/tests/ui/async-await/in-trait/async-generics.stderr @@ -1,5 +1,5 @@ error[E0311]: the parameter type `U` may not live long enough - --> $DIR/async-generics.rs:8:5 + --> $DIR/async-generics.rs:6:5 | LL | async fn foo(&self) -> &(T, U); | ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | async fn foo<'a>(&'a self) -> &'a (T, U) where U: 'a; | ++++ ++ ++ +++++++++++ error[E0311]: the parameter type `T` may not live long enough - --> $DIR/async-generics.rs:8:5 + --> $DIR/async-generics.rs:6:5 | LL | async fn foo(&self) -> &(T, U); | ^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs index ea8330a4b524..3721b01350d7 100644 --- a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs +++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs @@ -1,8 +1,6 @@ // check-pass // edition: 2021 -#![allow(incomplete_features)] - use std::fmt::Debug; trait MyTrait<'a, 'b, T> { diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs index 6e573b9cc8b6..cb4b871cbe15 100644 --- a/tests/ui/async-await/in-trait/async-lifetimes.rs +++ b/tests/ui/async-await/in-trait/async-lifetimes.rs @@ -1,8 +1,6 @@ // check-pass // edition: 2021 -#![allow(incomplete_features)] - trait MyTrait<'a, 'b, T> { #[allow(async_fn_in_trait)] async fn foo(&'a self, key: &'b T) -> (&'a Self, &'b T); diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.rs b/tests/ui/async-await/in-trait/async-recursive-generic.rs index 34f1b09756ed..c6031ce28d1d 100644 --- a/tests/ui/async-await/in-trait/async-recursive-generic.rs +++ b/tests/ui/async-await/in-trait/async-recursive-generic.rs @@ -1,7 +1,5 @@ // edition: 2021 -#![allow(incomplete_features)] - trait MyTrait { async fn foo_recursive(&self, n: usize) -> T; } diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr index 7c2df6683f02..cf0bcd741fc3 100644 --- a/tests/ui/async-await/in-trait/async-recursive-generic.stderr +++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr @@ -1,5 +1,5 @@ error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/async-recursive-generic.rs:10:5 + --> $DIR/async-recursive-generic.rs:8:5 | LL | async fn foo_recursive(&self, n: usize) -> T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn` diff --git a/tests/ui/async-await/in-trait/async-recursive.rs b/tests/ui/async-await/in-trait/async-recursive.rs index ddf119b252ff..09f1ffe499e3 100644 --- a/tests/ui/async-await/in-trait/async-recursive.rs +++ b/tests/ui/async-await/in-trait/async-recursive.rs @@ -1,7 +1,5 @@ // edition: 2021 -#![allow(incomplete_features)] - trait MyTrait { async fn foo_recursive(&self, n: usize) -> i32; } diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr index 1253252cc405..b959652ea167 100644 --- a/tests/ui/async-await/in-trait/async-recursive.stderr +++ b/tests/ui/async-await/in-trait/async-recursive.stderr @@ -1,5 +1,5 @@ error[E0733]: recursion in an `async fn` requires boxing - --> $DIR/async-recursive.rs:10:5 + --> $DIR/async-recursive.rs:8:5 | LL | async fn foo_recursive(&self, n: usize) -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn` diff --git a/tests/ui/async-await/in-trait/early-bound-1.rs b/tests/ui/async-await/in-trait/early-bound-1.rs index f79d6f23c933..ddcb477a1dc4 100644 --- a/tests/ui/async-await/in-trait/early-bound-1.rs +++ b/tests/ui/async-await/in-trait/early-bound-1.rs @@ -1,8 +1,6 @@ // check-pass // edition:2021 -#![allow(incomplete_features)] - pub trait Foo { #[allow(async_fn_in_trait)] async fn foo(&mut self); diff --git a/tests/ui/impl-trait/in-trait/deep-match.rs b/tests/ui/impl-trait/in-trait/deep-match.rs index 02889347ba43..82eac7760fcd 100644 --- a/tests/ui/impl-trait/in-trait/deep-match.rs +++ b/tests/ui/impl-trait/in-trait/deep-match.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - struct Wrapper(T); trait Foo { diff --git a/tests/ui/impl-trait/in-trait/deep-match.stderr b/tests/ui/impl-trait/in-trait/deep-match.stderr index 9cfc54f5094c..a658d8fa0781 100644 --- a/tests/ui/impl-trait/in-trait/deep-match.stderr +++ b/tests/ui/impl-trait/in-trait/deep-match.stderr @@ -1,5 +1,5 @@ error[E0053]: method `bar` has an incompatible return type for trait - --> $DIR/deep-match.rs:10:17 + --> $DIR/deep-match.rs:8:17 | LL | fn bar() -> i32 { | ^^^ diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.rs b/tests/ui/impl-trait/in-trait/default-body-type-err.rs index 977ff8111ddc..ac7a50a365ea 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err.rs +++ b/tests/ui/impl-trait/in-trait/default-body-type-err.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - use std::ops::Deref; pub trait Foo { diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr index 3d9ca62b0db0..596ff1011555 100644 --- a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr +++ b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String` - --> $DIR/default-body-type-err.rs:6:22 + --> $DIR/default-body-type-err.rs:4:22 | LL | fn lol(&self) -> impl Deref { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String` diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs index 5a53c9a19b58..0ac60918b67e 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - trait Foo { fn bar() -> impl std::fmt::Display; } diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr index cb9ecc7fa483..cd45c6a9c6d4 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -1,5 +1,5 @@ error[E0277]: `()` doesn't implement `std::fmt::Display` - --> $DIR/doesnt-satisfy.rs:8:17 + --> $DIR/doesnt-satisfy.rs:6:17 | LL | fn bar() -> () {} | ^^ `()` cannot be formatted with the default formatter @@ -7,7 +7,7 @@ LL | fn bar() -> () {} = help: the trait `std::fmt::Display` is not implemented for `()` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead note: required by a bound in `Foo::{opaque#0}` - --> $DIR/doesnt-satisfy.rs:4:22 + --> $DIR/doesnt-satisfy.rs:2:22 | LL | fn bar() -> impl std::fmt::Display; | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}` diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.rs b/tests/ui/impl-trait/in-trait/generics-mismatch.rs index 2e5373dbd5dc..3ea31cc93479 100644 --- a/tests/ui/impl-trait/in-trait/generics-mismatch.rs +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - struct U; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr index 3dbf2235c5e1..043dbc8db5d0 100644 --- a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr +++ b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr @@ -1,5 +1,5 @@ error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters - --> $DIR/generics-mismatch.rs:10:12 + --> $DIR/generics-mismatch.rs:8:12 | LL | fn bar(&self) -> impl Sized; | - expected 0 type parameters diff --git a/tests/ui/impl-trait/in-trait/issue-102140.rs b/tests/ui/impl-trait/in-trait/issue-102140.rs index 1132bd25f813..7960018482fc 100644 --- a/tests/ui/impl-trait/in-trait/issue-102140.rs +++ b/tests/ui/impl-trait/in-trait/issue-102140.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - trait Marker {} impl Marker for u32 {} diff --git a/tests/ui/impl-trait/in-trait/issue-102140.stderr b/tests/ui/impl-trait/in-trait/issue-102140.stderr index 6d50d2f3a24f..9cd2cdfd1a53 100644 --- a/tests/ui/impl-trait/in-trait/issue-102140.stderr +++ b/tests/ui/impl-trait/in-trait/issue-102140.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/issue-102140.rs:22:22 + --> $DIR/issue-102140.rs:20:22 | LL | MyTrait::foo(&self) | ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` @@ -13,7 +13,7 @@ LL + MyTrait::foo(self) | error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/issue-102140.rs:22:9 + --> $DIR/issue-102140.rs:20:9 | LL | MyTrait::foo(&self) | ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` @@ -21,7 +21,7 @@ LL | MyTrait::foo(&self) = help: the trait `MyTrait` is implemented for `Outer` error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied - --> $DIR/issue-102140.rs:22:9 + --> $DIR/issue-102140.rs:20:9 | LL | MyTrait::foo(&self) | ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait` diff --git a/tests/ui/impl-trait/in-trait/issue-102571.rs b/tests/ui/impl-trait/in-trait/issue-102571.rs index 4534753f0d20..4fa3fdd31b5f 100644 --- a/tests/ui/impl-trait/in-trait/issue-102571.rs +++ b/tests/ui/impl-trait/in-trait/issue-102571.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - use std::fmt::Display; use std::ops::Deref; diff --git a/tests/ui/impl-trait/in-trait/issue-102571.stderr b/tests/ui/impl-trait/in-trait/issue-102571.stderr index 4d1a0feb22bf..872988faf7ab 100644 --- a/tests/ui/impl-trait/in-trait/issue-102571.stderr +++ b/tests/ui/impl-trait/in-trait/issue-102571.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-102571.rs:11:9 + --> $DIR/issue-102571.rs:9:9 | LL | let () = t.bar(); | ^^ ------- this expression has type `impl Deref` diff --git a/tests/ui/impl-trait/in-trait/object-safety.rs b/tests/ui/impl-trait/in-trait/object-safety.rs index 15634537dae8..5cca4ad839c2 100644 --- a/tests/ui/impl-trait/in-trait/object-safety.rs +++ b/tests/ui/impl-trait/in-trait/object-safety.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - use std::fmt::Debug; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/object-safety.stderr index 8d8823912517..3271cb18d9fb 100644 --- a/tests/ui/impl-trait/in-trait/object-safety.stderr +++ b/tests/ui/impl-trait/in-trait/object-safety.stderr @@ -1,11 +1,11 @@ error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:16:33 + --> $DIR/object-safety.rs:14:33 | LL | let i = Box::new(42_u32) as Box; | ^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:6:22 + --> $DIR/object-safety.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -14,13 +14,13 @@ LL | fn baz(&self) -> impl Debug; = help: consider moving `baz` to another trait error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:19:15 + --> $DIR/object-safety.rs:17:15 | LL | let s = i.baz(); | ^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:6:22 + --> $DIR/object-safety.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -29,13 +29,13 @@ LL | fn baz(&self) -> impl Debug; = help: consider moving `baz` to another trait error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:19:13 + --> $DIR/object-safety.rs:17:13 | LL | let s = i.baz(); | ^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:6:22 + --> $DIR/object-safety.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... @@ -44,13 +44,13 @@ LL | fn baz(&self) -> impl Debug; = help: consider moving `baz` to another trait error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/object-safety.rs:16:13 + --> $DIR/object-safety.rs:14:13 | LL | let i = Box::new(42_u32) as Box; | ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/object-safety.rs:6:22 + --> $DIR/object-safety.rs:4:22 | LL | trait Foo { | --- this trait cannot be made into an object... diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs index fc708536b0f5..1f18bb3b774b 100644 --- a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - use std::fmt::Display; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr index 99b62e80acd2..e260762d89f5 100644 --- a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr +++ b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/opaque-in-impl-is-opaque.rs:16:19 + --> $DIR/opaque-in-impl-is-opaque.rs:14:19 | LL | fn bar(&self) -> impl Display { | ------------ the found opaque type diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs index c905bfce8527..d9fac0238e16 100644 --- a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs +++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs @@ -1,5 +1,3 @@ -#![allow(incomplete_features)] - struct S; trait Foo { diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr index e904548742da..2836e9c7821e 100644 --- a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr +++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr @@ -1,5 +1,5 @@ error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter - --> $DIR/trait-more-generics-than-impl.rs:10:11 + --> $DIR/trait-more-generics-than-impl.rs:8:11 | LL | fn bar() -> impl Sized; | - expected 1 type parameter From f3d20be42bba6672be4818781487a7904b47354b Mon Sep 17 00:00:00 2001 From: yukang Date: Tue, 17 Oct 2023 17:35:54 +0800 Subject: [PATCH 48/51] suggest unwrap/expect for let binding type mismatch --- compiler/rustc_hir_typeck/src/demand.rs | 3 +- .../src/fn_ctxt/suggestions.rs | 80 ++++++++++++++++ tests/ui/lifetimes/issue-26638.stderr | 4 + .../mismatch-ty-dont-suggest.rs | 23 +++++ .../mismatch-ty-dont-suggest.stderr | 55 +++++++++++ .../mismatch-ty-unwrap-expect.fixed | 31 +++++++ .../mismatch-ty-unwrap-expect.rs | 31 +++++++ .../mismatch-ty-unwrap-expect.stderr | 93 +++++++++++++++++++ tests/ui/noexporttypeexe.stderr | 4 + .../tag-that-dare-not-speak-its-name.stderr | 4 + 10 files changed, 327 insertions(+), 1 deletion(-) create mode 100644 tests/ui/mismatched_types/mismatch-ty-dont-suggest.rs create mode 100644 tests/ui/mismatched_types/mismatch-ty-dont-suggest.stderr create mode 100644 tests/ui/mismatched_types/mismatch-ty-unwrap-expect.fixed create mode 100644 tests/ui/mismatched_types/mismatch-ty-unwrap-expect.rs create mode 100644 tests/ui/mismatched_types/mismatch-ty-unwrap-expect.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 65ec2f232aed..f379e8477e38 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -58,7 +58,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { || self.suggest_into(err, expr, expr_ty, expected) || self.suggest_floating_point_literal(err, expr, expected) || self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected) - || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty); + || self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty) + || self.suggest_missing_unwrap_expect(err, expr, expected, expr_ty); if !suggested { self.note_source_of_type_mismatch_constraint( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 14d691413434..85fb56b30672 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -6,6 +6,7 @@ use crate::method::probe::{IsSuggestion, Mode, ProbeScope}; use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX}; use rustc_errors::{Applicability, Diagnostic, MultiSpan}; use rustc_hir as hir; +use rustc_hir::def::Res; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ @@ -1738,4 +1739,83 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the field is hygienic it must come from the same syntax context. && self.tcx.def_ident_span(field.did).unwrap().normalize_to_macros_2_0().eq_ctxt(span) } + + pub(crate) fn suggest_missing_unwrap_expect( + &self, + err: &mut Diagnostic, + expr: &hir::Expr<'tcx>, + expected: Ty<'tcx>, + found: Ty<'tcx>, + ) -> bool { + let ty::Adt(adt, args) = found.kind() else { return false }; + let ret_ty_matches = |diagnostic_item| { + if let Some(ret_ty) = self + .ret_coercion + .as_ref() + .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty())) + && let ty::Adt(kind, _) = ret_ty.kind() + && self.tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did()) + { + true + } else { + false + } + }; + + // don't suggest anything like `Ok(ok_val).unwrap()` , `Some(some_val).unwrap()`, + // `None.unwrap()` etc. + let is_ctor = matches!( + expr.kind, + hir::ExprKind::Call( + hir::Expr { + kind: hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: Res::Def(hir::def::DefKind::Ctor(_, _), _), .. }, + )), + .. + }, + .., + ) | hir::ExprKind::Path(hir::QPath::Resolved( + None, + hir::Path { res: Res::Def(hir::def::DefKind::Ctor(_, _), _), .. }, + )), + ); + + let (article, kind, variant, sugg_operator) = + if self.tcx.is_diagnostic_item(sym::Result, adt.did()) { + ("a", "Result", "Err", ret_ty_matches(sym::Result)) + } else if self.tcx.is_diagnostic_item(sym::Option, adt.did()) { + ("an", "Option", "None", ret_ty_matches(sym::Option)) + } else { + return false; + }; + if is_ctor || !self.can_coerce(args.type_at(0), expected) { + return false; + } + + let (msg, sugg) = if sugg_operator { + ( + format!( + "use the `?` operator to extract the `{found}` value, propagating \ + {article} `{kind}::{variant}` value to the caller" + ), + "?", + ) + } else { + ( + format!( + "consider using `{kind}::expect` to unwrap the `{found}` value, \ + panicking if the value is {article} `{kind}::{variant}`" + ), + ".expect(\"REASON\")", + ) + }; + err.span_suggestion_verbose( + expr.span.shrink_to_hi(), + msg, + sugg, + Applicability::HasPlaceholders, + ); + return true; + } } diff --git a/tests/ui/lifetimes/issue-26638.stderr b/tests/ui/lifetimes/issue-26638.stderr index 30afcecf827e..e61158a5d4d0 100644 --- a/tests/ui/lifetimes/issue-26638.stderr +++ b/tests/ui/lifetimes/issue-26638.stderr @@ -44,6 +44,10 @@ LL | fn parse_type(iter: Box+'static>) -> &str { iter.ne | = note: expected reference `&str` found enum `Option<&str>` +help: consider using `Option::expect` to unwrap the `Option<&str>` value, panicking if the value is an `Option::None` + | +LL | fn parse_type(iter: Box+'static>) -> &str { iter.next().expect("REASON") } + | +++++++++++++++++ error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/issue-26638.rs:5:47 diff --git a/tests/ui/mismatched_types/mismatch-ty-dont-suggest.rs b/tests/ui/mismatched_types/mismatch-ty-dont-suggest.rs new file mode 100644 index 000000000000..b288a9b05efe --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-ty-dont-suggest.rs @@ -0,0 +1,23 @@ +#![allow(unused, dead_code)] + +fn test_unwrap() -> Option { + let b: Result = Ok(1); + let v: i32 = b; // return type is not `Result`, we don't suggest ? here + //~^ ERROR mismatched types + Some(v) +} + +fn test_unwrap_option() -> Result { + let b = Some(1); + let v: i32 = b; // return type is not `Option`, we don't suggest ? here + //~^ ERROR mismatched types + Ok(v) +} + +fn main() { + let v: i32 = Some(0); //~ ERROR mismatched types + + let c = Ok(false); + let v: i32 = c; //~ ERROR mismatched types + +} diff --git a/tests/ui/mismatched_types/mismatch-ty-dont-suggest.stderr b/tests/ui/mismatched_types/mismatch-ty-dont-suggest.stderr new file mode 100644 index 000000000000..4f8f9b1a8a56 --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-ty-dont-suggest.stderr @@ -0,0 +1,55 @@ +error[E0308]: mismatched types + --> $DIR/mismatch-ty-dont-suggest.rs:5:18 + | +LL | let v: i32 = b; // return type is not `Result`, we don't suggest ? here + | --- ^ expected `i32`, found `Result` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Result` +help: consider using `Result::expect` to unwrap the `Result` value, panicking if the value is a `Result::Err` + | +LL | let v: i32 = b.expect("REASON"); // return type is not `Result`, we don't suggest ? here + | +++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-ty-dont-suggest.rs:12:18 + | +LL | let v: i32 = b; // return type is not `Option`, we don't suggest ? here + | --- ^ expected `i32`, found `Option<{integer}>` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option<{integer}>` +help: consider using `Option::expect` to unwrap the `Option<{integer}>` value, panicking if the value is an `Option::None` + | +LL | let v: i32 = b.expect("REASON"); // return type is not `Option`, we don't suggest ? here + | +++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-ty-dont-suggest.rs:18:18 + | +LL | let v: i32 = Some(0); + | --- ^^^^^^^ expected `i32`, found `Option<{integer}>` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option<{integer}>` + +error[E0308]: mismatched types + --> $DIR/mismatch-ty-dont-suggest.rs:21:18 + | +LL | let v: i32 = c; + | --- ^ expected `i32`, found `Result` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Result` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/mismatched_types/mismatch-ty-unwrap-expect.fixed b/tests/ui/mismatched_types/mismatch-ty-unwrap-expect.fixed new file mode 100644 index 000000000000..f3f560fe530a --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-ty-unwrap-expect.fixed @@ -0,0 +1,31 @@ +// run-rustfix +#![allow(unused, dead_code)] + +fn func() -> Option { + Some(1) +} + +fn test_unwrap() -> Result { + let b: Result = Ok(1); + let v: i32 = b?; //~ ERROR mismatched types + Ok(v) +} + +fn test_unwrap_option() -> Option { + let b = Some(1); + let v: i32 = b?; //~ ERROR mismatched types + Some(v) +} + +fn main() { + let a = Some(1); + let v: i32 = a.expect("REASON"); //~ ERROR mismatched types + + let b: Result = Ok(1); + let v: i32 = b.expect("REASON"); //~ ERROR mismatched types + + let v: i32 = func().expect("REASON"); //~ ERROR mismatched types + + let a = None; + let v: i32 = a.expect("REASON"); //~ ERROR mismatched types +} diff --git a/tests/ui/mismatched_types/mismatch-ty-unwrap-expect.rs b/tests/ui/mismatched_types/mismatch-ty-unwrap-expect.rs new file mode 100644 index 000000000000..14020e872ff0 --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-ty-unwrap-expect.rs @@ -0,0 +1,31 @@ +// run-rustfix +#![allow(unused, dead_code)] + +fn func() -> Option { + Some(1) +} + +fn test_unwrap() -> Result { + let b: Result = Ok(1); + let v: i32 = b; //~ ERROR mismatched types + Ok(v) +} + +fn test_unwrap_option() -> Option { + let b = Some(1); + let v: i32 = b; //~ ERROR mismatched types + Some(v) +} + +fn main() { + let a = Some(1); + let v: i32 = a; //~ ERROR mismatched types + + let b: Result = Ok(1); + let v: i32 = b; //~ ERROR mismatched types + + let v: i32 = func(); //~ ERROR mismatched types + + let a = None; + let v: i32 = a; //~ ERROR mismatched types +} diff --git a/tests/ui/mismatched_types/mismatch-ty-unwrap-expect.stderr b/tests/ui/mismatched_types/mismatch-ty-unwrap-expect.stderr new file mode 100644 index 000000000000..9de23447fed5 --- /dev/null +++ b/tests/ui/mismatched_types/mismatch-ty-unwrap-expect.stderr @@ -0,0 +1,93 @@ +error[E0308]: mismatched types + --> $DIR/mismatch-ty-unwrap-expect.rs:10:18 + | +LL | let v: i32 = b; + | --- ^ expected `i32`, found `Result` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Result` +help: use the `?` operator to extract the `Result` value, propagating a `Result::Err` value to the caller + | +LL | let v: i32 = b?; + | + + +error[E0308]: mismatched types + --> $DIR/mismatch-ty-unwrap-expect.rs:16:18 + | +LL | let v: i32 = b; + | --- ^ expected `i32`, found `Option<{integer}>` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option<{integer}>` +help: use the `?` operator to extract the `Option<{integer}>` value, propagating an `Option::None` value to the caller + | +LL | let v: i32 = b?; + | + + +error[E0308]: mismatched types + --> $DIR/mismatch-ty-unwrap-expect.rs:22:18 + | +LL | let v: i32 = a; + | --- ^ expected `i32`, found `Option<{integer}>` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option<{integer}>` +help: consider using `Option::expect` to unwrap the `Option<{integer}>` value, panicking if the value is an `Option::None` + | +LL | let v: i32 = a.expect("REASON"); + | +++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-ty-unwrap-expect.rs:25:18 + | +LL | let v: i32 = b; + | --- ^ expected `i32`, found `Result` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Result` +help: consider using `Result::expect` to unwrap the `Result` value, panicking if the value is a `Result::Err` + | +LL | let v: i32 = b.expect("REASON"); + | +++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-ty-unwrap-expect.rs:27:18 + | +LL | let v: i32 = func(); + | --- ^^^^^^ expected `i32`, found `Option` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option` +help: consider using `Option::expect` to unwrap the `Option` value, panicking if the value is an `Option::None` + | +LL | let v: i32 = func().expect("REASON"); + | +++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/mismatch-ty-unwrap-expect.rs:30:18 + | +LL | let v: i32 = a; + | --- ^ expected `i32`, found `Option<_>` + | | + | expected due to this + | + = note: expected type `i32` + found enum `Option<_>` +help: consider using `Option::expect` to unwrap the `Option<_>` value, panicking if the value is an `Option::None` + | +LL | let v: i32 = a.expect("REASON"); + | +++++++++++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/noexporttypeexe.stderr b/tests/ui/noexporttypeexe.stderr index 26bafd31d011..bf88ceaa5d2a 100644 --- a/tests/ui/noexporttypeexe.stderr +++ b/tests/ui/noexporttypeexe.stderr @@ -8,6 +8,10 @@ LL | let x: isize = noexporttypelib::foo(); | = note: expected type `isize` found enum `Option` +help: consider using `Option::expect` to unwrap the `Option` value, panicking if the value is an `Option::None` + | +LL | let x: isize = noexporttypelib::foo().expect("REASON"); + | +++++++++++++++++ error: aborting due to previous error diff --git a/tests/ui/typeck/tag-that-dare-not-speak-its-name.stderr b/tests/ui/typeck/tag-that-dare-not-speak-its-name.stderr index f53abe53bf13..c4f164295634 100644 --- a/tests/ui/typeck/tag-that-dare-not-speak-its-name.stderr +++ b/tests/ui/typeck/tag-that-dare-not-speak-its-name.stderr @@ -8,6 +8,10 @@ LL | let x : char = last(y); | = note: expected type `char` found enum `Option<_>` +help: consider using `Option::expect` to unwrap the `Option<_>` value, panicking if the value is an `Option::None` + | +LL | let x : char = last(y).expect("REASON"); + | +++++++++++++++++ error: aborting due to previous error From a986ab4d4d72d2cfb7b8d38dd4648ffb4d636c4c Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 24 Oct 2023 20:13:36 +0000 Subject: [PATCH 49/51] Get rid of 'tcx on ConstVid, EffectVid --- .../rustc_infer/src/infer/canonical/mod.rs | 2 +- compiler/rustc_infer/src/infer/combine.rs | 4 +- compiler/rustc_infer/src/infer/freshen.rs | 6 +- compiler/rustc_infer/src/infer/fudge.rs | 15 ++-- compiler/rustc_infer/src/infer/generalize.rs | 20 +++-- compiler/rustc_infer/src/infer/mod.rs | 83 ++++++++++--------- compiler/rustc_infer/src/infer/resolve.rs | 4 +- compiler/rustc_infer/src/infer/undo_log.rs | 10 +-- compiler/rustc_middle/src/infer/unify_key.rs | 40 +++++++-- compiler/rustc_middle/src/ty/consts.rs | 4 +- compiler/rustc_middle/src/ty/consts/kind.rs | 8 +- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 10 +-- compiler/rustc_middle/src/ty/print/pretty.rs | 6 +- .../rustc_middle/src/ty/structural_impls.rs | 24 ++---- compiler/rustc_middle/src/ty/sty.rs | 33 ++++---- .../src/traits/fulfill.rs | 9 +- 17 files changed, 150 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 41787ee29420..280dcae34515 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -152,7 +152,7 @@ impl<'tcx> InferCtxt<'tcx> { ) .into(), CanonicalVarKind::Effect => { - let vid = self.inner.borrow_mut().effect_unification_table().new_key(None); + let vid = self.inner.borrow_mut().effect_unification_table().new_key(None).vid; ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid), self.tcx.types.bool) .into() } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index ee13eb0271e7..2a9e20b9f8f1 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -320,7 +320,7 @@ impl<'tcx> InferCtxt<'tcx> { #[instrument(level = "debug", skip(self))] fn unify_const_variable( &self, - target_vid: ty::ConstVid<'tcx>, + target_vid: ty::ConstVid, ct: ty::Const<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { @@ -381,7 +381,7 @@ impl<'tcx> InferCtxt<'tcx> { fn unify_effect_variable( &self, vid_is_expected: bool, - vid: ty::EffectVid<'tcx>, + vid: ty::EffectVid, val: EffectVarValue<'tcx>, ) -> RelateResult<'tcx, ty::Const<'tcx>> { self.inner diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 0596ce373cf5..35204478c54d 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -42,7 +42,7 @@ pub struct TypeFreshener<'a, 'tcx> { ty_freshen_count: u32, const_freshen_count: u32, ty_freshen_map: FxHashMap>, - const_freshen_map: FxHashMap, ty::Const<'tcx>>, + const_freshen_map: FxHashMap>, } impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { @@ -79,12 +79,12 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { fn freshen_const( &mut self, opt_ct: Option>, - key: ty::InferConst<'tcx>, + key: ty::InferConst, freshener: F, ty: Ty<'tcx>, ) -> ty::Const<'tcx> where - F: FnOnce(u32) -> ty::InferConst<'tcx>, + F: FnOnce(u32) -> ty::InferConst, { if let Some(ct) = opt_ct { return ct.fold_with(self); diff --git a/compiler/rustc_infer/src/infer/fudge.rs b/compiler/rustc_infer/src/infer/fudge.rs index 2f371c4fe31c..7e878ac06c7f 100644 --- a/compiler/rustc_infer/src/infer/fudge.rs +++ b/compiler/rustc_infer/src/infer/fudge.rs @@ -1,3 +1,4 @@ +use rustc_middle::infer::unify_key::ConstVidKey; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; @@ -23,14 +24,14 @@ where } fn const_vars_since_snapshot<'tcx>( - table: &mut UnificationTable<'_, 'tcx, ConstVid<'tcx>>, + table: &mut UnificationTable<'_, 'tcx, ConstVidKey<'tcx>>, snapshot_var_len: usize, -) -> (Range>, Vec) { +) -> (Range, Vec) { let range = vars_since_snapshot(table, snapshot_var_len); ( - range.start..range.end, - (range.start.index..range.end.index) - .map(|index| table.probe_value(ConstVid::from_index(index)).origin) + range.start.vid..range.end.vid, + (range.start.index()..range.end.index()) + .map(|index| table.probe_value(ConstVid::from_u32(index)).origin) .collect(), ) } @@ -172,7 +173,7 @@ pub struct InferenceFudger<'a, 'tcx> { int_vars: Range, float_vars: Range, region_vars: (Range, Vec), - const_vars: (Range>, Vec), + const_vars: (Range, Vec), } impl<'a, 'tcx> TypeFolder> for InferenceFudger<'a, 'tcx> { @@ -235,7 +236,7 @@ impl<'a, 'tcx> TypeFolder> for InferenceFudger<'a, 'tcx> { if self.const_vars.0.contains(&vid) { // This variable was created during the fudging. // Recreate it with a fresh variable here. - let idx = (vid.index - self.const_vars.0.start.index) as usize; + let idx = (vid.index() - self.const_vars.0.start.index()) as usize; let origin = self.const_vars.1[idx]; self.infcx.next_const_var(ct.ty(), origin) } else { diff --git a/compiler/rustc_infer/src/infer/generalize.rs b/compiler/rustc_infer/src/infer/generalize.rs index c1e65ffe0a65..17fe3aa7b44c 100644 --- a/compiler/rustc_infer/src/infer/generalize.rs +++ b/compiler/rustc_infer/src/infer/generalize.rs @@ -17,7 +17,7 @@ pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into> infcx: &InferCtxt<'tcx>, delegate: &mut D, term: T, - for_vid: impl Into>, + for_vid: impl Into, ambient_variance: ty::Variance, ) -> RelateResult<'tcx, Generalization> { let (for_universe, root_vid) = match for_vid.into() { @@ -27,7 +27,7 @@ pub(super) fn generalize<'tcx, D: GeneralizerDelegate<'tcx>, T: Into> ), ty::TermVid::Const(ct_vid) => ( infcx.probe_const_var(ct_vid).unwrap_err(), - ty::TermVid::Const(infcx.inner.borrow_mut().const_unification_table().find(ct_vid)), + ty::TermVid::Const(infcx.inner.borrow_mut().const_unification_table().find(ct_vid).vid), ), }; @@ -127,7 +127,7 @@ struct Generalizer<'me, 'tcx, D> { /// The vid of the type variable that is in the process of being /// instantiated. If we find this within the value we are folding, /// that means we would have created a cyclic value. - root_vid: ty::TermVid<'tcx>, + root_vid: ty::TermVid, /// The universe of the type variable that is in the process of being /// instantiated. If we find anything that this universe cannot name, @@ -376,7 +376,7 @@ where // `vid` are related and we'd be inferring an infinitely // deep const. if ty::TermVid::Const( - self.infcx.inner.borrow_mut().const_unification_table().find(vid), + self.infcx.inner.borrow_mut().const_unification_table().find(vid).vid, ) == self.root_vid { return Err(self.cyclic_term_error()); @@ -394,10 +394,14 @@ where if self.for_universe.can_name(universe) { Ok(c) } else { - let new_var_id = variable_table.new_key(ConstVarValue { - origin: var_value.origin, - val: ConstVariableValue::Unknown { universe: self.for_universe }, - }); + let new_var_id = variable_table + .new_key(ConstVarValue { + origin: var_value.origin, + val: ConstVariableValue::Unknown { + universe: self.for_universe, + }, + }) + .vid; Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty())) } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2198a15d99d4..4ee897ffe984 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -6,7 +6,9 @@ pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; pub use combine::ObligationEmittingRelation; +use rustc_data_structures::captures::Captures; use rustc_data_structures::undo_log::UndoLogs; +use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey}; use self::opaque_types::OpaqueTypeStorage; pub(crate) use self::undo_log::{InferCtxtUndoLogs, Snapshot, UndoLog}; @@ -40,7 +42,6 @@ use rustc_span::{Span, DUMMY_SP}; use std::cell::{Cell, RefCell}; use std::fmt; -use std::marker::PhantomData; use self::combine::CombineFields; use self::error_reporting::TypeErrCtxt; @@ -85,7 +86,7 @@ pub struct InferOk<'tcx, T> { pub type InferResult<'tcx, T> = Result, TypeError<'tcx>>; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" -pub type FixupResult<'tcx, T> = Result>; // "fixup result" +pub type FixupResult = Result; // "fixup result" pub(crate) type UnificationTable<'a, 'tcx, T> = ut::UnificationTable< ut::InPlace, &'a mut InferCtxtUndoLogs<'tcx>>, @@ -108,7 +109,7 @@ pub struct InferCtxtInner<'tcx> { type_variable_storage: type_variable::TypeVariableStorage<'tcx>, /// Map from const parameter variable to the kind of const it represents. - const_unification_storage: ut::UnificationTableStorage>, + const_unification_storage: ut::UnificationTableStorage>, /// Map from integral variable to the kind of integer it represents. int_unification_storage: ut::UnificationTableStorage, @@ -117,7 +118,7 @@ pub struct InferCtxtInner<'tcx> { float_unification_storage: ut::UnificationTableStorage, /// Map from effect variable to the effect param it represents. - effect_unification_storage: ut::UnificationTableStorage>, + effect_unification_storage: ut::UnificationTableStorage>, /// Tracks the set of region variables and the constraints between them. /// @@ -224,11 +225,11 @@ impl<'tcx> InferCtxtInner<'tcx> { } #[inline] - fn const_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::ConstVid<'tcx>> { + fn const_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ConstVidKey<'tcx>> { self.const_unification_storage.with_log(&mut self.undo_log) } - fn effect_unification_table(&mut self) -> UnificationTable<'_, 'tcx, ty::EffectVid<'tcx>> { + fn effect_unification_table(&mut self) -> UnificationTable<'_, 'tcx, EffectVidKey<'tcx>> { self.effect_unification_storage.with_log(&mut self.undo_log) } @@ -359,7 +360,7 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { } } - fn universe_of_ct(&self, ct: ty::InferConst<'tcx>) -> Option { + fn universe_of_ct(&self, ct: ty::InferConst) -> Option { use ty::InferConst::*; match ct { // Same issue as with `universe_of_ty` @@ -548,11 +549,11 @@ pub enum NllRegionVariableOrigin { // FIXME(eddyb) investigate overlap between this and `TyOrConstInferVar`. #[derive(Copy, Clone, Debug)] -pub enum FixupError<'tcx> { +pub enum FixupError { UnresolvedIntTy(IntVid), UnresolvedFloatTy(FloatVid), UnresolvedTy(TyVid), - UnresolvedConst(ConstVid<'tcx>), + UnresolvedConst(ConstVid), } /// See the `region_obligations` field for more information. @@ -563,7 +564,7 @@ pub struct RegionObligation<'tcx> { pub origin: SubregionOrigin<'tcx>, } -impl<'tcx> fmt::Display for FixupError<'tcx> { +impl fmt::Display for FixupError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use self::FixupError::*; @@ -794,7 +795,7 @@ impl<'tcx> InferCtxt<'tcx> { let mut table = inner.effect_unification_table(); (0..table.len()) - .map(|i| ty::EffectVid { index: i as u32, phantom: PhantomData }) + .map(|i| ty::EffectVid::from_usize(i)) .filter(|&vid| table.probe_value(vid).is_none()) .map(|v| { ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v), self.tcx.types.bool) @@ -1072,15 +1073,20 @@ impl<'tcx> InferCtxt<'tcx> { .inner .borrow_mut() .const_unification_table() - .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } }); + .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe } }) + .vid; ty::Const::new_var(self.tcx, vid, ty) } - pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid<'tcx> { - self.inner.borrow_mut().const_unification_table().new_key(ConstVarValue { - origin, - val: ConstVariableValue::Unknown { universe: self.universe() }, - }) + pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid { + self.inner + .borrow_mut() + .const_unification_table() + .new_key(ConstVarValue { + origin, + val: ConstVariableValue::Unknown { universe: self.universe() }, + }) + .vid } fn next_int_var_id(&self) -> IntVid { @@ -1194,11 +1200,15 @@ impl<'tcx> InferCtxt<'tcx> { ), span, }; - let const_var_id = - self.inner.borrow_mut().const_unification_table().new_key(ConstVarValue { + let const_var_id = self + .inner + .borrow_mut() + .const_unification_table() + .new_key(ConstVarValue { origin, val: ConstVariableValue::Unknown { universe: self.universe() }, - }); + }) + .vid; ty::Const::new_var( self.tcx, const_var_id, @@ -1213,7 +1223,7 @@ impl<'tcx> InferCtxt<'tcx> { } pub fn var_for_effect(&self, param: &ty::GenericParamDef) -> GenericArg<'tcx> { - let effect_vid = self.inner.borrow_mut().effect_unification_table().new_key(None); + let effect_vid = self.inner.borrow_mut().effect_unification_table().new_key(None).vid; let ty = self .tcx .type_of(param.def_id) @@ -1333,12 +1343,12 @@ impl<'tcx> InferCtxt<'tcx> { self.inner.borrow_mut().type_variables().root_var(var) } - pub fn root_const_var(&self, var: ty::ConstVid<'tcx>) -> ty::ConstVid<'tcx> { - self.inner.borrow_mut().const_unification_table().find(var) + pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid { + self.inner.borrow_mut().const_unification_table().find(var).vid } - pub fn root_effect_var(&self, var: ty::EffectVid<'tcx>) -> ty::EffectVid<'tcx> { - self.inner.borrow_mut().effect_unification_table().find(var) + pub fn root_effect_var(&self, var: ty::EffectVid) -> ty::EffectVid { + self.inner.borrow_mut().effect_unification_table().find(var).vid } /// Resolves an int var to a rigid int type, if it was constrained to one, @@ -1402,17 +1412,14 @@ impl<'tcx> InferCtxt<'tcx> { value.visit_with(&mut resolve::UnresolvedTypeOrConstFinder::new(self)).break_value() } - pub fn probe_const_var( - &self, - vid: ty::ConstVid<'tcx>, - ) -> Result, ty::UniverseIndex> { + pub fn probe_const_var(&self, vid: ty::ConstVid) -> Result, ty::UniverseIndex> { match self.inner.borrow_mut().const_unification_table().probe_value(vid).val { ConstVariableValue::Known { value } => Ok(value), ConstVariableValue::Unknown { universe } => Err(universe), } } - pub fn probe_effect_var(&self, vid: EffectVid<'tcx>) -> Option> { + pub fn probe_effect_var(&self, vid: EffectVid) -> Option> { self.inner.borrow_mut().effect_unification_table().probe_value(vid) } @@ -1423,7 +1430,7 @@ impl<'tcx> InferCtxt<'tcx> { /// /// This method is idempotent, but it not typically not invoked /// except during the writeback phase. - pub fn fully_resolve>>(&self, value: T) -> FixupResult<'tcx, T> { + pub fn fully_resolve>>(&self, value: T) -> FixupResult { match resolve::fully_resolve(self, value) { Ok(value) => { if value.has_non_region_infer() { @@ -1647,11 +1654,11 @@ impl<'tcx> InferCtxt<'tcx> { #[inline] pub fn is_ty_infer_var_definitely_unchanged<'a>( &'a self, - ) -> (impl Fn(TyOrConstInferVar<'tcx>) -> bool + 'a) { + ) -> (impl Fn(TyOrConstInferVar) -> bool + Captures<'tcx> + 'a) { // This hoists the borrow/release out of the loop body. let inner = self.inner.try_borrow(); - return move |infer_var: TyOrConstInferVar<'tcx>| match (infer_var, &inner) { + return move |infer_var: TyOrConstInferVar| match (infer_var, &inner) { (TyOrConstInferVar::Ty(ty_var), Ok(inner)) => { use self::type_variable::TypeVariableValue; @@ -1674,7 +1681,7 @@ impl<'tcx> InferCtxt<'tcx> { /// inference variables), and it handles both `Ty` and `ty::Const` without /// having to resort to storing full `GenericArg`s in `stalled_on`. #[inline(always)] - pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar<'tcx>) -> bool { + pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar) -> bool { match infer_var { TyOrConstInferVar::Ty(v) => { use self::type_variable::TypeVariableValue; @@ -1781,7 +1788,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { /// Helper for [InferCtxt::ty_or_const_infer_var_changed] (see comment on that), currently /// used only for `traits::fulfill`'s list of `stalled_on` inference variables. #[derive(Copy, Clone, Debug)] -pub enum TyOrConstInferVar<'tcx> { +pub enum TyOrConstInferVar { /// Equivalent to `ty::Infer(ty::TyVar(_))`. Ty(TyVid), /// Equivalent to `ty::Infer(ty::IntVar(_))`. @@ -1790,12 +1797,12 @@ pub enum TyOrConstInferVar<'tcx> { TyFloat(FloatVid), /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`. - Const(ConstVid<'tcx>), + Const(ConstVid), /// Equivalent to `ty::ConstKind::Infer(ty::InferConst::EffectVar(_))`. - Effect(EffectVid<'tcx>), + Effect(EffectVid), } -impl<'tcx> TyOrConstInferVar<'tcx> { +impl<'tcx> TyOrConstInferVar { /// Tries to extract an inference variable from a type or a constant, returns `None` /// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). diff --git a/compiler/rustc_infer/src/infer/resolve.rs b/compiler/rustc_infer/src/infer/resolve.rs index 3c41e8b37838..18a9cb6b44b7 100644 --- a/compiler/rustc_infer/src/infer/resolve.rs +++ b/compiler/rustc_infer/src/infer/resolve.rs @@ -192,7 +192,7 @@ impl<'a, 'tcx> TypeVisitor> for UnresolvedTypeOrConstFinder<'a, 'tc /// Full type resolution replaces all type and region variables with /// their concrete results. If any variable cannot be replaced (never unified, etc) /// then an `Err` result is returned. -pub fn fully_resolve<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> FixupResult<'tcx, T> +pub fn fully_resolve<'tcx, T>(infcx: &InferCtxt<'tcx>, value: T) -> FixupResult where T: TypeFoldable>, { @@ -206,7 +206,7 @@ struct FullTypeResolver<'a, 'tcx> { } impl<'a, 'tcx> FallibleTypeFolder> for FullTypeResolver<'a, 'tcx> { - type Error = FixupError<'tcx>; + type Error = FixupError; fn interner(&self) -> TyCtxt<'tcx> { self.infcx.tcx diff --git a/compiler/rustc_infer/src/infer/undo_log.rs b/compiler/rustc_infer/src/infer/undo_log.rs index 79144b3e643b..5655730518e5 100644 --- a/compiler/rustc_infer/src/infer/undo_log.rs +++ b/compiler/rustc_infer/src/infer/undo_log.rs @@ -3,7 +3,7 @@ use std::marker::PhantomData; use rustc_data_structures::snapshot_vec as sv; use rustc_data_structures::undo_log::{Rollback, UndoLogs}; use rustc_data_structures::unify as ut; -use rustc_middle::infer::unify_key::RegionVidKey; +use rustc_middle::infer::unify_key::{ConstVidKey, EffectVidKey, RegionVidKey}; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey}; use crate::{ @@ -21,10 +21,10 @@ pub struct Snapshot<'tcx> { pub(crate) enum UndoLog<'tcx> { OpaqueTypes(OpaqueTypeKey<'tcx>, Option>), TypeVariables(type_variable::UndoLog<'tcx>), - ConstUnificationTable(sv::UndoLog>>), + ConstUnificationTable(sv::UndoLog>>), IntUnificationTable(sv::UndoLog>), FloatUnificationTable(sv::UndoLog>), - EffectUnificationTable(sv::UndoLog>>), + EffectUnificationTable(sv::UndoLog>>), RegionConstraintCollector(region_constraints::UndoLog<'tcx>), RegionUnificationTable(sv::UndoLog>>), ProjectionCache(traits::UndoLog<'tcx>), @@ -56,9 +56,9 @@ impl_from! { IntUnificationTable(sv::UndoLog>), FloatUnificationTable(sv::UndoLog>), - EffectUnificationTable(sv::UndoLog>>), + EffectUnificationTable(sv::UndoLog>>), - ConstUnificationTable(sv::UndoLog>>), + ConstUnificationTable(sv::UndoLog>>), RegionUnificationTable(sv::UndoLog>>), ProjectionCache(traits::UndoLog<'tcx>), diff --git a/compiler/rustc_middle/src/infer/unify_key.rs b/compiler/rustc_middle/src/infer/unify_key.rs index 7ca9647590a2..041a63776d11 100644 --- a/compiler/rustc_middle/src/infer/unify_key.rs +++ b/compiler/rustc_middle/src/infer/unify_key.rs @@ -141,18 +141,30 @@ pub struct ConstVarValue<'tcx> { pub val: ConstVariableValue<'tcx>, } -impl<'tcx> UnifyKey for ty::ConstVid<'tcx> { +#[derive(PartialEq, Copy, Clone, Debug)] +pub struct ConstVidKey<'tcx> { + pub vid: ty::ConstVid, + pub phantom: PhantomData>, +} + +impl<'tcx> From for ConstVidKey<'tcx> { + fn from(vid: ty::ConstVid) -> Self { + ConstVidKey { vid, phantom: PhantomData } + } +} + +impl<'tcx> UnifyKey for ConstVidKey<'tcx> { type Value = ConstVarValue<'tcx>; #[inline] fn index(&self) -> u32 { - self.index + self.vid.as_u32() } #[inline] fn from_index(i: u32) -> Self { - ty::ConstVid { index: i, phantom: PhantomData } + ConstVidKey::from(ty::ConstVid::from_u32(i)) } fn tag() -> &'static str { - "ConstVid" + "ConstVidKey" } } @@ -224,17 +236,29 @@ impl<'tcx> UnifyValue for EffectVarValue<'tcx> { } } -impl<'tcx> UnifyKey for ty::EffectVid<'tcx> { +#[derive(PartialEq, Copy, Clone, Debug)] +pub struct EffectVidKey<'tcx> { + pub vid: ty::EffectVid, + pub phantom: PhantomData>, +} + +impl<'tcx> From for EffectVidKey<'tcx> { + fn from(vid: ty::EffectVid) -> Self { + EffectVidKey { vid, phantom: PhantomData } + } +} + +impl<'tcx> UnifyKey for EffectVidKey<'tcx> { type Value = Option>; #[inline] fn index(&self) -> u32 { - self.index + self.vid.as_u32() } #[inline] fn from_index(i: u32) -> Self { - ty::EffectVid { index: i, phantom: PhantomData } + EffectVidKey::from(ty::EffectVid::from_u32(i)) } fn tag() -> &'static str { - "EffectVid" + "EffectVidKey" } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 2518f0cf2e9c..cfacccd26799 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -57,7 +57,7 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid, ty: Ty<'tcx>) -> Const<'tcx> { Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer)), ty) } @@ -67,7 +67,7 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Const<'tcx> { Const::new(tcx, ty::ConstKind::Infer(infer), ty) } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 749b54ca0bef..4af841fcf9a5 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -80,19 +80,19 @@ static_assert_size!(super::ConstKind<'_>, 32); /// An inference variable for a const, for use in const generics. #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] -pub enum InferConst<'tcx> { +pub enum InferConst { /// Infer the value of the const. - Var(ty::ConstVid<'tcx>), + Var(ty::ConstVid), /// Infer the value of the effect. /// /// For why this is separate from the `Var` variant above, see the /// documentation on `EffectVid`. - EffectVar(ty::EffectVid<'tcx>), + EffectVar(ty::EffectVid), /// A fresh const variable. See `infer::freshen` for more details. Fresh(u32), } -impl HashStable for InferConst<'_> { +impl HashStable for InferConst { fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) { match self { InferConst::Var(_) | InferConst::EffectVar(_) => { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 561699d31708..3c8bac2a9d3d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -100,7 +100,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PolyFnSig = PolyFnSig<'tcx>; type AllocId = crate::mir::interpret::AllocId; type Const = ty::Const<'tcx>; - type InferConst = ty::InferConst<'tcx>; + type InferConst = ty::InferConst; type AliasConst = ty::UnevaluatedConst<'tcx>; type PlaceholderConst = ty::PlaceholderConst<'tcx>; type ParamConst = ty::ParamConst; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 91211a048a00..769b374c793a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1084,19 +1084,19 @@ impl ParamTerm { } #[derive(Copy, Clone, Eq, PartialEq, Debug)] -pub enum TermVid<'tcx> { +pub enum TermVid { Ty(ty::TyVid), - Const(ty::ConstVid<'tcx>), + Const(ty::ConstVid), } -impl From for TermVid<'_> { +impl From for TermVid { fn from(value: ty::TyVid) -> Self { TermVid::Ty(value) } } -impl<'tcx> From> for TermVid<'tcx> { - fn from(value: ty::ConstVid<'tcx>) -> Self { +impl From for TermVid { + fn from(value: ty::ConstVid) -> Self { TermVid::Const(value) } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 316370977a42..22648d853f4e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1194,7 +1194,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { None } - fn const_infer_name(&self, _: ty::ConstVid<'tcx>) -> Option { + fn const_infer_name(&self, _: ty::ConstVid) -> Option { None } @@ -1742,7 +1742,7 @@ pub struct FmtPrinterData<'a, 'tcx> { pub region_highlight_mode: RegionHighlightMode<'tcx>, pub ty_infer_name_resolver: Option Option + 'a>>, - pub const_infer_name_resolver: Option) -> Option + 'a>>, + pub const_infer_name_resolver: Option Option + 'a>>, } impl<'a, 'tcx> Deref for FmtPrinter<'a, 'tcx> { @@ -2082,7 +2082,7 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> { self.printed_type_count = 0; } - fn const_infer_name(&self, id: ty::ConstVid<'tcx>) -> Option { + fn const_infer_name(&self, id: ty::ConstVid) -> Option { self.0.const_infer_name_resolver.as_ref().and_then(|func| func(id)) } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 92fac6fdab40..967f62cdbca5 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -128,18 +128,6 @@ impl<'tcx> DebugWithInfcx> for ty::FnSig<'tcx> { } } -impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "?{}c", self.index) - } -} - -impl fmt::Debug for ty::EffectVid<'_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "?{}e", self.index) - } -} - impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { with_no_trimmed_paths!(fmt::Display::fmt(self, f)) @@ -251,7 +239,7 @@ impl<'tcx> DebugWithInfcx> for AliasTy<'tcx> { } } -impl<'tcx> fmt::Debug for ty::InferConst<'tcx> { +impl fmt::Debug for ty::InferConst { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { InferConst::Var(var) => write!(f, "{var:?}"), @@ -260,7 +248,7 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> { } } } -impl<'tcx> DebugWithInfcx> for ty::InferConst<'tcx> { +impl<'tcx> DebugWithInfcx> for ty::InferConst { fn fmt>>( this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, @@ -269,8 +257,8 @@ impl<'tcx> DebugWithInfcx> for ty::InferConst<'tcx> { match this.infcx.universe_of_ct(*this.data) { None => write!(f, "{:?}", this.data), Some(universe) => match *this.data { - Var(vid) => write!(f, "?{}_{}c", vid.index, universe.index()), - EffectVar(vid) => write!(f, "?{}_{}e", vid.index, universe.index()), + Var(vid) => write!(f, "?{}_{}c", vid.index(), universe.index()), + EffectVar(vid) => write!(f, "?{}_{}e", vid.index(), universe.index()), Fresh(_) => { unreachable!() } @@ -862,7 +850,7 @@ impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { } } -impl<'tcx> TypeFoldable> for InferConst<'tcx> { +impl<'tcx> TypeFoldable> for InferConst { fn try_fold_with>>( self, _folder: &mut F, @@ -871,7 +859,7 @@ impl<'tcx> TypeFoldable> for InferConst<'tcx> { } } -impl<'tcx> TypeVisitable> for InferConst<'tcx> { +impl<'tcx> TypeVisitable> for InferConst { fn visit_with>>( &self, _visitor: &mut V, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f93a23158fb0..53260a3996cf 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -29,7 +29,6 @@ use std::assert_matches::debug_assert_matches; use std::borrow::Cow; use std::cmp::Ordering; use std::fmt; -use std::marker::PhantomData; use std::ops::{ControlFlow, Deref, Range}; use ty::util::IntTypeExt; @@ -1583,26 +1582,22 @@ impl fmt::Debug for EarlyBoundRegion { } } -/// A **`const`** **v**ariable **ID**. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(HashStable, TyEncodable, TyDecodable)] -pub struct ConstVid<'tcx> { - pub index: u32, - pub phantom: PhantomData<&'tcx ()>, +rustc_index::newtype_index! { + /// A **`const`** **v**ariable **ID**. + #[debug_format = "?{}c"] + pub struct ConstVid {} } -/// An **effect** **v**ariable **ID**. -/// -/// Handling effect infer variables happens separately from const infer variables -/// because we do not want to reuse any of the const infer machinery. If we try to -/// relate an effect variable with a normal one, we would ICE, which can catch bugs -/// where we are not correctly using the effect var for an effect param. Fallback -/// is also implemented on top of having separate effect and normal const variables. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(TyEncodable, TyDecodable)] -pub struct EffectVid<'tcx> { - pub index: u32, - pub phantom: PhantomData<&'tcx ()>, +rustc_index::newtype_index! { + /// An **effect** **v**ariable **ID**. + /// + /// Handling effect infer variables happens separately from const infer variables + /// because we do not want to reuse any of the const infer machinery. If we try to + /// relate an effect variable with a normal one, we would ICE, which can catch bugs + /// where we are not correctly using the effect var for an effect param. Fallback + /// is also implemented on top of having separate effect and normal const variables. + #[debug_format = "?{}e"] + pub struct EffectVid {} } rustc_index::newtype_index! { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 55b5604b16b5..fb9cf51b513b 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -1,4 +1,5 @@ use crate::infer::{InferCtxt, TyOrConstInferVar}; +use rustc_data_structures::captures::Captures; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{Error, ForestObligation, Outcome}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; @@ -68,7 +69,7 @@ pub struct PendingPredicateObligation<'tcx> { // should mostly optimize for reading speed, while modifying is not as relevant. // // For whatever reason using a boxed slice is slower than using a `Vec` here. - pub stalled_on: Vec>, + pub stalled_on: Vec, } // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. @@ -669,7 +670,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { &mut self, obligation: &PredicateObligation<'tcx>, trait_obligation: PolyTraitObligation<'tcx>, - stalled_on: &mut Vec>, + stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { let infcx = self.selcx.infcx; if obligation.predicate.is_global() && !self.selcx.is_intercrate() { @@ -722,7 +723,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { &mut self, obligation: &PredicateObligation<'tcx>, project_obligation: PolyProjectionObligation<'tcx>, - stalled_on: &mut Vec>, + stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { let tcx = self.selcx.tcx(); @@ -775,7 +776,7 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { fn args_infer_vars<'a, 'tcx>( selcx: &SelectionContext<'a, 'tcx>, args: ty::Binder<'tcx, GenericArgsRef<'tcx>>, -) -> impl Iterator> { +) -> impl Iterator + Captures<'tcx> { selcx .infcx .resolve_vars_if_possible(args) From c612ba8e2910a585e4fc0ae126180c478b28e3de Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot Date: Wed, 25 Oct 2023 05:31:14 +0000 Subject: [PATCH 50/51] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 9600195a6a66..60ae5d12598a 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f1a5ce19f5aa0cf61ed7b9f75b30e610befeed72 +2e4e2a8f288f642cafcc41fff211955ceddc453d From 19c4fa60eaddb0ea47130644a01127fc4f516452 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 25 Oct 2023 10:03:09 +0200 Subject: [PATCH 51/51] CLOCK_UPTIME_RAW exists on all macos targets, not just the ARM ones --- src/tools/miri/src/shims/time.rs | 12 ++++-------- src/tools/miri/tests/pass-dep/shims/libc-misc.rs | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index d6d0483f5e3a..4918698c6b27 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -51,13 +51,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "macos" => { absolute_clocks = vec![this.eval_libc_i32("CLOCK_REALTIME")]; relative_clocks = vec![this.eval_libc_i32("CLOCK_MONOTONIC")]; - // Some clocks only seem to exist in the aarch64 version of the target. - if this.tcx.sess.target.arch == "aarch64" { - // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but - // that's not really something a program running inside Miri can tell, anyway. - // We need to support it because std uses it. - relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")); - } + // `CLOCK_UPTIME_RAW` supposed to not increment while the system is asleep... but + // that's not really something a program running inside Miri can tell, anyway. + // We need to support it because std uses it. + relative_clocks.push(this.eval_libc_i32("CLOCK_UPTIME_RAW")); } target => throw_unsup_format!("`clock_gettime` is not supported on target OS {target}"), } @@ -68,7 +65,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } else if relative_clocks.contains(&clk_id) { this.machine.clock.now().duration_since(this.machine.clock.anchor()) } else { - // Unsupported clock. let einval = this.eval_libc("EINVAL"); this.set_last_error(einval)?; return Ok(Scalar::from_i32(-1)); diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs index 82c49cfb17c5..40d3fa19e530 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs @@ -186,7 +186,7 @@ fn test_clocks() { unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC_COARSE, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); } - #[cfg(all(target_os = "macos", target_arch = "aarch64"))] + #[cfg(target_os = "macos")] { let is_error = unsafe { libc::clock_gettime(libc::CLOCK_UPTIME_RAW, tp.as_mut_ptr()) }; assert_eq!(is_error, 0);