From ad7c2b06609c0da21ebdab6e45135cf07290f585 Mon Sep 17 00:00:00 2001 From: Oliver Killane Date: Sun, 5 May 2024 13:54:33 +0100 Subject: [PATCH 001/154] Updated error code explanation --- .../src/error_codes/E0582.md | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/compiler/rustc_error_codes/src/error_codes/E0582.md b/compiler/rustc_error_codes/src/error_codes/E0582.md index e50cc60ea330..ea32e4f9f33f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0582.md +++ b/compiler/rustc_error_codes/src/error_codes/E0582.md @@ -27,6 +27,40 @@ fn bar(t: F, u: G) fn main() { } ``` +This error also includes the use of associated types with lifetime parameters. +```compile_fail,E0582 +trait Foo { + type Assoc<'a>; +} + +struct Bar +where + X: Foo, + F: for<'a> Fn(X::Assoc<'a>) -> &'a i32 +{ + x: X, + f: F +} +``` +This is as `Foo::Assoc<'a>` could be implemented by a type that does not use +the `'a` parameter, so there is no guarentee that `X::Assoc<'a>` actually uses +`'a`. + +To fix this we can pass a dummy parameter: +``` +# trait Foo { +# type Assoc<'a>; +# } +struct Bar +where + X: Foo, + F: for<'a> Fn(X::Assoc<'a>, /* dummy */ &'a ()) -> &'a i32 +{ + x: X, + f: F +} +``` + Note: The examples above used to be (erroneously) accepted by the compiler, but this was since corrected. See [issue #33685] for more details. From f3dcf65985dd956595a3f14dcb2a3052daceeb73 Mon Sep 17 00:00:00 2001 From: Oliver Killane Date: Sun, 5 May 2024 14:55:16 +0100 Subject: [PATCH 002/154] fix whitespace --- compiler/rustc_error_codes/src/error_codes/E0582.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0582.md b/compiler/rustc_error_codes/src/error_codes/E0582.md index ea32e4f9f33f..31927cd5fe34 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0582.md +++ b/compiler/rustc_error_codes/src/error_codes/E0582.md @@ -42,8 +42,8 @@ where f: F } ``` -This is as `Foo::Assoc<'a>` could be implemented by a type that does not use -the `'a` parameter, so there is no guarentee that `X::Assoc<'a>` actually uses +This is as `Foo::Assoc<'a>` could be implemented by a type that does not use +the `'a` parameter, so there is no guarentee that `X::Assoc<'a>` actually uses `'a`. To fix this we can pass a dummy parameter: From a5a60d75a87881f79deea115d7cd002ce3373fd5 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Thu, 28 Mar 2024 14:30:32 +0000 Subject: [PATCH 003/154] Add `size_of`, `size_of_val`, `align_of`, and `align_of_val` to the prelude Many, many projects use `size_of` to get the size of a type. However, it's also often equally easy to hardcode a size (e.g. `8` instead of `size_of::()`). Minimizing friction in the use of `size_of` helps ensure that people use it and make code more self-documenting. The name `size_of` is unambiguous: the name alone, without any prefix or path, is self-explanatory and unmistakeable for any other functionality. Adding it to the prelude cannot produce any name conflicts, as any local definition will silently shadow the one from the prelude. Thus, we don't need to wait for a new edition prelude to add it. Add `size_of_val`, `align_of`, and `align_of_val` as well, with similar justification: widely useful, self-explanatory, unmistakeable for anything else, won't produce conflicts. --- compiler/rustc_middle/src/query/erase.rs | 2 +- library/alloc/src/rc.rs | 2 -- library/alloc/src/sync.rs | 2 -- library/core/src/cell.rs | 2 +- library/core/src/intrinsics.rs | 1 - library/core/src/prelude/common.rs | 3 +++ library/core/src/ptr/mod.rs | 2 +- library/core/src/slice/raw.rs | 1 - library/core/src/sync/atomic.rs | 3 --- .../crates/core_simd/src/simd/ptr/const_ptr.rs | 2 +- .../crates/core_simd/src/simd/ptr/mut_ptr.rs | 2 +- library/proc_macro/src/bridge/fxhash.rs | 1 - library/std/src/io/error/repr_bitpacked.rs | 1 - library/std/src/os/unix/net/ancillary.rs | 2 +- library/std/src/prelude/common.rs | 3 +++ library/std/src/prelude/mod.rs | 4 ++++ tests/ui/resolve/filter-intrinsics.rs | 4 ++-- tests/ui/resolve/filter-intrinsics.stderr | 8 ++++---- 18 files changed, 22 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 320d49ea6467..a4ab6bc7d9de 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -4,7 +4,7 @@ use crate::traits; use crate::ty::adjustment::CoerceUnsizedInfo; use crate::ty::{self, Ty}; use std::intrinsics::transmute_unchecked; -use std::mem::{size_of, MaybeUninit}; +use std::mem::MaybeUninit; #[derive(Copy, Clone)] pub struct Erased { diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 45b205356758..52b91c5ac887 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -257,8 +257,6 @@ use core::intrinsics::abort; #[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::{PhantomData, Unsize}; -#[cfg(not(no_global_oom_handling))] -use core::mem::size_of_val; use core::mem::{self, align_of_val_raw, forget, ManuallyDrop}; use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Receiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index a35c99849b34..d7c3a261fe40 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -18,8 +18,6 @@ use core::intrinsics::abort; #[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::{PhantomData, Unsize}; -#[cfg(not(no_global_oom_handling))] -use core::mem::size_of_val; use core::mem::{self, align_of_val_raw}; use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, Receiver}; use core::panic::{RefUnwindSafe, UnwindSafe}; diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 4b491ffdafa7..dd6466d6285b 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -238,7 +238,7 @@ use crate::cmp::Ordering; use crate::fmt::{self, Debug, Display}; use crate::marker::{PhantomData, Unsize}; -use crate::mem::{self, size_of}; +use crate::mem; use crate::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; use crate::ptr::{self, NonNull}; diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index d1450bf12ce7..56c998d99f25 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -65,7 +65,6 @@ use crate::marker::DiscriminantKind; use crate::marker::Tuple; -use crate::mem::align_of; use crate::ptr; use crate::ub_checks; diff --git a/library/core/src/prelude/common.rs b/library/core/src/prelude/common.rs index afc6817aa1d2..2a0331ef7b27 100644 --- a/library/core/src/prelude/common.rs +++ b/library/core/src/prelude/common.rs @@ -14,6 +14,9 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; #[stable(feature = "core_prelude", since = "1.4.0")] #[doc(no_inline)] pub use crate::mem::drop; +#[stable(feature = "size_of_prelude", since = "CURRENT_RUSTC_VERSION")] +#[doc(no_inline)] +pub use crate::mem::{align_of, align_of_val, size_of, size_of_val}; // Re-exported types and traits #[stable(feature = "core_prelude", since = "1.4.0")] diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 8d7192c1b0fd..3258e338e837 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -392,7 +392,7 @@ use crate::intrinsics; use crate::marker::FnPtr; use crate::ub_checks; -use crate::mem::{self, align_of, size_of, MaybeUninit}; +use crate::mem::{self, MaybeUninit}; mod alignment; #[unstable(feature = "ptr_alignment_type", issue = "102070")] diff --git a/library/core/src/slice/raw.rs b/library/core/src/slice/raw.rs index 29a12f106c5e..3f4305866e68 100644 --- a/library/core/src/slice/raw.rs +++ b/library/core/src/slice/raw.rs @@ -1,7 +1,6 @@ //! Free functions to create `&[T]` and `&mut [T]`. use crate::array; -use crate::mem::{align_of, size_of}; use crate::ops::Range; use crate::ptr; use crate::ub_checks; diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 232ec589093d..482bd19705c2 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1296,7 +1296,6 @@ impl AtomicPtr { #[cfg(target_has_atomic_equal_alignment = "ptr")] #[unstable(feature = "atomic_from_mut", issue = "76314")] pub fn from_mut(v: &mut *mut T) -> &mut Self { - use crate::mem::align_of; let [] = [(); align_of::>() - align_of::<*mut ()>()]; // SAFETY: // - the mutable reference guarantees unique ownership. @@ -2286,7 +2285,6 @@ macro_rules! atomic_int { #[$cfg_align] #[unstable(feature = "atomic_from_mut", issue = "76314")] pub fn from_mut(v: &mut $int_type) -> &mut Self { - use crate::mem::align_of; let [] = [(); align_of::() - align_of::<$int_type>()]; // SAFETY: // - the mutable reference guarantees unique ownership. @@ -2354,7 +2352,6 @@ macro_rules! atomic_int { #[$cfg_align] #[unstable(feature = "atomic_from_mut", issue = "76314")] pub fn from_mut_slice(v: &mut [$int_type]) -> &mut [Self] { - use crate::mem::align_of; let [] = [(); align_of::() - align_of::<$int_type>()]; // SAFETY: // - the mutable reference guarantees unique ownership. diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs index 0f1719206c9c..cbffbc564cfe 100644 --- a/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/const_ptr.rs @@ -96,7 +96,7 @@ where fn cast(self) -> Self::CastPtr { // SimdElement currently requires zero-sized metadata, so this should never fail. // If this ever changes, `simd_cast_ptr` should produce a post-mono error. - use core::{mem::size_of, ptr::Pointee}; + use core::ptr::Pointee; assert_eq!(size_of::<::Metadata>(), 0); assert_eq!(size_of::<::Metadata>(), 0); diff --git a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs index 7ba996d149c0..6bc6ca3ac42d 100644 --- a/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs +++ b/library/portable-simd/crates/core_simd/src/simd/ptr/mut_ptr.rs @@ -93,7 +93,7 @@ where fn cast(self) -> Self::CastPtr { // SimdElement currently requires zero-sized metadata, so this should never fail. // If this ever changes, `simd_cast_ptr` should produce a post-mono error. - use core::{mem::size_of, ptr::Pointee}; + use core::ptr::Pointee; assert_eq!(size_of::<::Metadata>(), 0); assert_eq!(size_of::<::Metadata>(), 0); diff --git a/library/proc_macro/src/bridge/fxhash.rs b/library/proc_macro/src/bridge/fxhash.rs index f4e905441972..0923493d06c7 100644 --- a/library/proc_macro/src/bridge/fxhash.rs +++ b/library/proc_macro/src/bridge/fxhash.rs @@ -7,7 +7,6 @@ use std::collections::HashMap; use std::hash::BuildHasherDefault; use std::hash::Hasher; -use std::mem::size_of; use std::ops::BitXor; /// Type alias for a hashmap using the `fx` hash algorithm. diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs index 6f8d5e377756..c9d3934ad70c 100644 --- a/library/std/src/io/error/repr_bitpacked.rs +++ b/library/std/src/io/error/repr_bitpacked.rs @@ -104,7 +104,6 @@ use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage}; use core::marker::PhantomData; -use core::mem::{align_of, size_of}; use core::ptr::{self, NonNull}; // The 2 least-significant bits are used as tag. diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 0597fdcbd728..fe8e2be93724 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -3,7 +3,7 @@ use super::{sockaddr_un, SocketAddr}; use crate::io::{self, IoSlice, IoSliceMut}; use crate::marker::PhantomData; -use crate::mem::{size_of, zeroed}; +use crate::mem::zeroed; use crate::os::unix::io::RawFd; use crate::path::Path; use crate::ptr::{eq, read_unaligned}; diff --git a/library/std/src/prelude/common.rs b/library/std/src/prelude/common.rs index 01936734d754..ceee3e33c3ef 100644 --- a/library/std/src/prelude/common.rs +++ b/library/std/src/prelude/common.rs @@ -14,6 +14,9 @@ pub use crate::ops::{Drop, Fn, FnMut, FnOnce}; #[stable(feature = "rust1", since = "1.0.0")] #[doc(no_inline)] pub use crate::mem::drop; +#[stable(feature = "size_of_prelude", since = "CURRENT_RUSTC_VERSION")] +#[doc(no_inline)] +pub use crate::mem::{align_of, align_of_val, size_of, size_of_val}; // Re-exported types and traits #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/prelude/mod.rs b/library/std/src/prelude/mod.rs index 0bdbab716adb..2d4639342bf8 100644 --- a/library/std/src/prelude/mod.rs +++ b/library/std/src/prelude/mod.rs @@ -36,6 +36,10 @@ //! operations for both destructors and overloading `()`. //! * [std::mem]::[drop], a convenience function for explicitly //! dropping a value. +//! * [std::mem]::{[size_of], [size_of_val]}, to get the size of +//! a type or value. +//! * [std::mem]::{[align_of], [align_of_val]}, to get the +//! alignment of a type or value. //! * [std::boxed]::[Box], a way to allocate values on the heap. //! * [std::borrow]::[ToOwned], the conversion trait that defines //! [`to_owned`], the generic method for creating an owned type from a diff --git a/tests/ui/resolve/filter-intrinsics.rs b/tests/ui/resolve/filter-intrinsics.rs index c0956ef85aff..8d6d22817dc5 100644 --- a/tests/ui/resolve/filter-intrinsics.rs +++ b/tests/ui/resolve/filter-intrinsics.rs @@ -1,6 +1,6 @@ fn main() { - // Should suggest only `std::mem::size_of` - let _ = size_of::(); + // Should suggest only `std::mem::transmute` + let _ = transmute::(); //~^ ERROR cannot find // Should suggest `std::intrinsics::fabsf64`, diff --git a/tests/ui/resolve/filter-intrinsics.stderr b/tests/ui/resolve/filter-intrinsics.stderr index cc1092dd0cfa..9c9e92f6d4f8 100644 --- a/tests/ui/resolve/filter-intrinsics.stderr +++ b/tests/ui/resolve/filter-intrinsics.stderr @@ -1,12 +1,12 @@ -error[E0425]: cannot find function `size_of` in this scope +error[E0425]: cannot find function `transmute` in this scope --> $DIR/filter-intrinsics.rs:3:13 | -LL | let _ = size_of::(); - | ^^^^^^^ not found in this scope +LL | let _ = transmute::(); + | ^^^^^^^^^ not found in this scope | help: consider importing this function | -LL + use std::mem::size_of; +LL + use std::mem::transmute; | error[E0425]: cannot find function `fabsf64` in this scope From a5d0988a88a7557d4ae507fecd4df3d9ed8ad839 Mon Sep 17 00:00:00 2001 From: Oliver Killane <44177991+OliverKillane@users.noreply.github.com> Date: Wed, 15 May 2024 00:07:21 +0100 Subject: [PATCH 004/154] Update compiler/rustc_error_codes/src/error_codes/E0582.md Co-authored-by: Felix S Klock II --- compiler/rustc_error_codes/src/error_codes/E0582.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0582.md b/compiler/rustc_error_codes/src/error_codes/E0582.md index 31927cd5fe34..26b65b12bc91 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0582.md +++ b/compiler/rustc_error_codes/src/error_codes/E0582.md @@ -42,7 +42,7 @@ where f: F } ``` -This is as `Foo::Assoc<'a>` could be implemented by a type that does not use +The latter scenario encounters this error because `Foo::Assoc<'a>` could be implemented by a type that does not use the `'a` parameter, so there is no guarentee that `X::Assoc<'a>` actually uses `'a`. From 012288b922e5db0ca6a8bbb2d1704c86c0fd79ff Mon Sep 17 00:00:00 2001 From: Oliver Killane Date: Wed, 15 May 2024 01:15:36 +0100 Subject: [PATCH 005/154] tidy fix from suggestion --- compiler/rustc_error_codes/src/error_codes/E0582.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0582.md b/compiler/rustc_error_codes/src/error_codes/E0582.md index 26b65b12bc91..b2cdb509c95c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0582.md +++ b/compiler/rustc_error_codes/src/error_codes/E0582.md @@ -42,9 +42,9 @@ where f: F } ``` -The latter scenario encounters this error because `Foo::Assoc<'a>` could be implemented by a type that does not use -the `'a` parameter, so there is no guarentee that `X::Assoc<'a>` actually uses -`'a`. +The latter scenario encounters this error because `Foo::Assoc<'a>` could be +implemented by a type that does not use the `'a` parameter, so there is no +guarentee that `X::Assoc<'a>` actually uses `'a`. To fix this we can pass a dummy parameter: ``` From a32fb2f8aa0780af750189356a06d501a72698b7 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 15 May 2024 15:11:23 -0400 Subject: [PATCH 006/154] Remove `ref_pat_everywhere` --- compiler/rustc_feature/src/removed.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_hir_typeck/src/pat.rs | 65 ++++--------------- .../feature-gate-ref_pat_everywhere.rs | 14 ---- .../feature-gate-ref_pat_everywhere.stderr | 49 -------------- tests/ui/match/ref_pat_everywhere-fail.rs | 12 ---- tests/ui/match/ref_pat_everywhere-fail.stderr | 38 ----------- tests/ui/match/ref_pat_everywhere.rs | 24 ------- 8 files changed, 14 insertions(+), 191 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs delete mode 100644 tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr delete mode 100644 tests/ui/match/ref_pat_everywhere-fail.rs delete mode 100644 tests/ui/match/ref_pat_everywhere-fail.stderr delete mode 100644 tests/ui/match/ref_pat_everywhere.rs diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index eaaf7ca34e01..f1afde31803e 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -181,6 +181,7 @@ declare_features! ( (removed, pushpop_unsafe, "1.2.0", None, None), (removed, quad_precision_float, "1.0.0", None, None), (removed, quote, "1.33.0", Some(29601), None), + (removed, ref_pat_everywhere, "1.79.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024")), (removed, reflect, "1.0.0", Some(27749), None), /// Allows using the `#[register_attr]` attribute. (removed, register_attr, "1.65.0", Some(66080), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 60b386acf910..1a058a121f3a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -571,8 +571,6 @@ declare_features! ( (unstable, raw_ref_op, "1.41.0", Some(64490)), /// Makes `&` and `&mut` patterns eat only one layer of references in Rust 2024. (incomplete, ref_pat_eat_one_layer_2024, "1.79.0", Some(123076)), - /// Allows `&` and `&mut` patterns to consume match-ergonomics-inserted references. - (incomplete, ref_pat_everywhere, "1.79.0", Some(123076)), /// Allows using the `#[register_tool]` attribute. (unstable, register_tool, "1.41.0", Some(66079)), /// Allows the `#[repr(i128)]` attribute for enums. diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index b9b220d5af8e..d2897f1c0113 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2125,25 +2125,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut expected: Ty<'tcx>, mut pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx> { - // FIXME: repace with `bool` once final decision on 1 vs 2 layers is made - #[derive(Clone, Copy, Debug, PartialEq, Eq)] - enum MatchErgonomicsMode { - EatOneLayer, - EatTwoLayers, - Legacy, - } + let new_match_ergonomics = + pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024; - let match_ergonomics_mode = - if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 { - MatchErgonomicsMode::EatOneLayer - } else if self.tcx.features().ref_pat_everywhere { - MatchErgonomicsMode::EatTwoLayers - } else { - MatchErgonomicsMode::Legacy - }; - - let mut inherited_ref_mutbl_match = false; - if match_ergonomics_mode != MatchErgonomicsMode::Legacy { + if new_match_ergonomics { if pat_mutbl == Mutability::Not { // Prevent the inner pattern from binding with `ref mut`. pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not( @@ -2151,20 +2136,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - if let ByRef::Yes(inh_mut) = pat_info.binding_mode { - inherited_ref_mutbl_match = pat_mutbl <= inh_mut; - } - - if inherited_ref_mutbl_match { - pat_info.binding_mode = ByRef::No; - if match_ergonomics_mode == MatchErgonomicsMode::EatOneLayer { - self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); - self.check_pat(inner, expected, pat_info); - return expected; - } - } else if match_ergonomics_mode == MatchErgonomicsMode::EatOneLayer - && pat_mutbl == Mutability::Mut + if let ByRef::Yes(inh_mut) = pat_info.binding_mode + && pat_mutbl <= inh_mut { + pat_info.binding_mode = ByRef::No; + self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); + self.check_pat(inner, expected, pat_info); + return expected; + } else if pat_mutbl == Mutability::Mut { // `&mut` patterns pell off `&` references let (new_expected, new_bm, max_ref_mutbl) = self.peel_off_references( pat, @@ -2204,33 +2183,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the bad interactions of the given hack detailed in (note_1). debug!("check_pat_ref: expected={:?}", expected); match *expected.kind() { - ty::Ref(_, r_ty, r_mutbl) if r_mutbl == pat_mutbl => { - if r_mutbl == Mutability::Not - && match_ergonomics_mode != MatchErgonomicsMode::Legacy - { + ty::Ref(_, r_ty, r_mutbl) if r_mutbl >= pat_mutbl && new_match_ergonomics => { + if r_mutbl == Mutability::Not { pat_info.max_ref_mutbl = MutblCap::Not; } (expected, r_ty) } - // `&` pattern eats `&mut` reference - ty::Ref(_, r_ty, Mutability::Mut) - if pat_mutbl == Mutability::Not - && match_ergonomics_mode != MatchErgonomicsMode::Legacy => - { - (expected, r_ty) - } - - _ if inherited_ref_mutbl_match - && match_ergonomics_mode == MatchErgonomicsMode::EatTwoLayers => - { - // We already matched against a match-ergonmics inserted reference, - // so we don't need to match against a reference from the original type. - // Save this info for use in lowering later - self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); - (expected, expected) - } + ty::Ref(_, r_ty, r_mutbl) if r_mutbl == pat_mutbl => (expected, r_ty), _ => { let inner_ty = self.next_ty_var(inner.span); diff --git a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs deleted file mode 100644 index ed5db56e0e83..000000000000 --- a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.rs +++ /dev/null @@ -1,14 +0,0 @@ -pub fn main() { - if let Some(Some(&x)) = &Some(&Some(0)) { - //~^ ERROR: mismatched types [E0308] - let _: u32 = x; - } - if let Some(&Some(x)) = &Some(Some(0)) { - //~^ ERROR: mismatched types [E0308] - let _: u32 = x; - } - if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { - //~^ ERROR: mismatched types [E0308] - let _: u32 = x; - } -} diff --git a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr b/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr deleted file mode 100644 index 0f0051325cdf..000000000000 --- a/tests/ui/feature-gates/feature-gate-ref_pat_everywhere.stderr +++ /dev/null @@ -1,49 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_everywhere.rs:2:22 - | -LL | if let Some(Some(&x)) = &Some(&Some(0)) { - | ^^ --------------- this expression has type `&Option<&Option<{integer}>>` - | | - | expected integer, found `&_` - | - = note: expected type `{integer}` - found reference `&_` -help: consider removing `&` from the pattern - | -LL | if let Some(Some(x)) = &Some(&Some(0)) { - | ~ - -error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_everywhere.rs:6:17 - | -LL | if let Some(&Some(x)) = &Some(Some(0)) { - | ^^^^^^^^ -------------- this expression has type `&Option>` - | | - | expected `Option<{integer}>`, found `&_` - | - = note: expected enum `Option<{integer}>` - found reference `&_` - -error[E0308]: mismatched types - --> $DIR/feature-gate-ref_pat_everywhere.rs:10:22 - | -LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { - | ^^^^^^ ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>` - | | - | expected integer, found `&mut _` - | - = note: expected type `{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/feature-gate-ref_pat_everywhere.rs:10:22 - | -LL | if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { - | ^^^^^^ -help: consider removing `&mut` from the pattern - | -LL | if let Some(Some(x)) = &mut Some(&mut Some(0)) { - | ~ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/ref_pat_everywhere-fail.rs b/tests/ui/match/ref_pat_everywhere-fail.rs deleted file mode 100644 index d1b1c04730d3..000000000000 --- a/tests/ui/match/ref_pat_everywhere-fail.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![allow(incomplete_features)] -#![feature(ref_pat_everywhere)] -pub fn main() { - if let Some(&x) = Some(0) { - //~^ ERROR: mismatched types [E0308] - let _: u32 = x; - } - if let Some(&mut x) = Some(&0) { - //~^ ERROR: mismatched types [E0308] - let _: u32 = x; - } -} diff --git a/tests/ui/match/ref_pat_everywhere-fail.stderr b/tests/ui/match/ref_pat_everywhere-fail.stderr deleted file mode 100644 index 25a01129f4a9..000000000000 --- a/tests/ui/match/ref_pat_everywhere-fail.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/ref_pat_everywhere-fail.rs:4:17 - | -LL | if let Some(&x) = Some(0) { - | ^^ ------- this expression has type `Option<{integer}>` - | | - | expected integer, found `&_` - | - = note: expected type `{integer}` - found reference `&_` -help: consider removing `&` from the pattern - | -LL | if let Some(x) = Some(0) { - | ~ - -error[E0308]: mismatched types - --> $DIR/ref_pat_everywhere-fail.rs:8:17 - | -LL | if let Some(&mut x) = Some(&0) { - | ^^^^^^ -------- this expression has type `Option<&{integer}>` - | | - | types differ in mutability - | - = note: expected reference `&{integer}` - found mutable reference `&mut _` -note: to declare a mutable binding use: `mut x` - --> $DIR/ref_pat_everywhere-fail.rs:8:17 - | -LL | if let Some(&mut x) = Some(&0) { - | ^^^^^^ -help: consider removing `&mut` from the pattern - | -LL | if let Some(x) = Some(&0) { - | ~ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/match/ref_pat_everywhere.rs b/tests/ui/match/ref_pat_everywhere.rs deleted file mode 100644 index 9a79c548475f..000000000000 --- a/tests/ui/match/ref_pat_everywhere.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ run-pass -#![allow(incomplete_features)] -#![feature(ref_pat_everywhere)] - -pub fn main() { - if let Some(Some(&x)) = &Some(&Some(0)) { - let _: u32 = x; - } - if let Some(&Some(x)) = &Some(Some(0)) { - let _: u32 = x; - } - if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) { - let _: u32 = x; - } - if let Some(Some(&x)) = &Some(&mut Some(0)) { - let _: u32 = x; - } - if let &Some(x) = &mut Some(0) { - let _: u32 = x; - } - if let Some(&x) = &mut Some(0) { - let _: u32 = x; - } -} From eb91f3b0513acf34701d8598c1312875c6e489a5 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 15 May 2024 15:54:28 -0400 Subject: [PATCH 007/154] `&mut` no longer peels off `&` --- compiler/rustc_hir_typeck/src/pat.rs | 52 +++---- .../ref_pat_eat_one_layer_2024.rs | 15 -- .../ref_pat_eat_one_layer_2024_fail.rs | 29 +++- .../ref_pat_eat_one_layer_2024_fail.stderr | 137 ++++++++++++------ 4 files changed, 146 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index d2897f1c0113..6cd74961cc7f 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -335,9 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match adjust_mode { AdjustMode::Pass => (expected, def_br, max_ref_mutbl), AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut), - AdjustMode::Peel => { - self.peel_off_references(pat, expected, def_br, Mutability::Mut, max_ref_mutbl) - } + AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl), } } @@ -408,7 +406,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, mut def_br: ByRef, - max_peelable_mutability: Mutability, mut max_ref_mutability: MutblCap, ) -> (Ty<'tcx>, ByRef, MutblCap) { let mut expected = self.try_structurally_resolve_type(pat.span, expected); @@ -421,9 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // See the examples in `ui/match-defbm*.rs`. let mut pat_adjustments = vec![]; - while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() - && inner_mutability <= max_peelable_mutability - { + while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() { debug!("inspecting {:?}", expected); debug!("current discriminant is Ref, inserting implicit deref"); @@ -2129,32 +2124,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024; if new_match_ergonomics { + let pat_prefix_span = + inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end)); + if pat_mutbl == Mutability::Not { // Prevent the inner pattern from binding with `ref mut`. - pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not( - inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end)), - ); + pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span); } - if let ByRef::Yes(inh_mut) = pat_info.binding_mode - && pat_mutbl <= inh_mut - { + if let ByRef::Yes(inh_mut) = pat_info.binding_mode { + // ref pattern consumes inherited reference + + if pat_mutbl > inh_mut { + // Tried to match inherited `ref` with `&mut`, which is an error + let err_msg = "cannot match inherited `&` with `&mut` pattern"; + let err = if let Some(span) = pat_prefix_span { + let mut err = self.dcx().struct_span_err(span, err_msg); + err.span_suggestion_verbose( + span, + "replace this `&mut` pattern with `&`", + "&", + Applicability::MachineApplicable, + ); + err + } else { + self.dcx().struct_span_err(pat.span, err_msg) + }; + err.emit(); + } + pat_info.binding_mode = ByRef::No; self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id); self.check_pat(inner, expected, pat_info); return expected; - } else if pat_mutbl == Mutability::Mut { - // `&mut` patterns pell off `&` references - let (new_expected, new_bm, max_ref_mutbl) = self.peel_off_references( - pat, - expected, - pat_info.binding_mode, - Mutability::Not, - pat_info.max_ref_mutbl, - ); - expected = new_expected; - pat_info.binding_mode = new_bm; - pat_info.max_ref_mutbl = max_ref_mutbl; } } else { // Reset binding mode on old editions diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs index 62e4f82a3ffb..829b7f86e262 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs @@ -23,9 +23,6 @@ pub fn main() { if let Some(Some(&x)) = &Some(&Some(0)) { let _: u32 = x; } - if let Some(&mut Some(&x)) = &Some(&mut Some(0)) { - let _: u32 = x; - } if let Some(&Some(&x)) = &mut Some(&Some(0)) { let _: u32 = x; } @@ -35,9 +32,6 @@ pub fn main() { if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) { let _: &u32 = x; } - if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { - let _: &u32 = x; - } if let &Some(Some(x)) = &Some(&mut Some(0)) { let _: &u32 = x; } @@ -59,13 +53,4 @@ pub fn main() { if let Some(&Some(x)) = &mut Some(Some(0)) { let _: u32 = x; } - - let &mut x = &&mut 0; - let _: &u32 = x; - - let &mut x = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; - let _: &u32 = x; - - let &mut &mut &mut &mut x = &mut &&&&mut &&&mut &mut 0; - let _: &u32 = x; } diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs index 96b4ff77ddb4..a2a0c73b53b2 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs @@ -5,26 +5,26 @@ pub fn main() { if let Some(&mut Some(&_)) = &Some(&Some(0)) { - //~^ ERROR: mismatched types + //~^ ERROR: cannot match inherited `&` with `&mut` pattern } if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - //~^ ERROR: mismatched types + //~^ ERROR: cannot match inherited `&` with `&mut` pattern } if let Some(&Some(x)) = &mut Some(&Some(0)) { let _: &mut u32 = x; //~^ ERROR: mismatched types } if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { - //~^ ERROR: mismatched types + //~^ ERROR: cannot match inherited `&` with `&mut` pattern } if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - //~^ ERROR: mismatched types + //~^ ERROR: cannot match inherited `&` with `&mut` pattern } if let Some(&mut Some(x)) = &Some(Some(0)) { - //~^ ERROR: mismatched types + //~^ ERROR: cannot match inherited `&` with `&mut` pattern } if let Some(&mut Some(x)) = &Some(Some(0)) { - //~^ ERROR: mismatched types + //~^ ERROR: cannot match inherited `&` with `&mut` pattern } let &mut _ = &&0; @@ -32,4 +32,21 @@ pub fn main() { let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; //~^ ERROR: mismatched types + + if let Some(&mut Some(&_)) = &Some(&mut Some(0)) { + //~^ ERROR: cannot match inherited `&` with `&mut` pattern + } + + if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { + //~^ ERROR: cannot match inherited `&` with `&mut` pattern + } + + let &mut _ = &&mut 0; + //~^ ERROR: mismatched types + + let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; + //~^ ERROR: mismatched types + + let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; + //~^ ERROR: mismatched types } diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr index e06a645fc0d3..cad67b4f8d67 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr @@ -1,24 +1,24 @@ -error[E0308]: mismatched types +error: cannot match inherited `&` with `&mut` pattern --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:7:17 | LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) { - | ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>` - | | - | expected `Option<{integer}>`, found `&mut _` + | ^^^^^ | - = note: expected enum `Option<{integer}>` - found mutable reference `&mut _` +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(&_)) = &Some(&Some(0)) { + | ~ -error[E0308]: mismatched types +error: cannot match inherited `&` with `&mut` pattern --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:10:23 | LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) { - | ^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { + | ~ error[E0308]: mismatched types --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:14:27 @@ -31,49 +31,49 @@ LL | let _: &mut u32 = x; = note: expected mutable reference `&mut u32` found reference `&{integer}` -error[E0308]: mismatched types +error: cannot match inherited `&` with `&mut` pattern --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:17:23 | LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) { - | ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) { + | ~ -error[E0308]: mismatched types +error: cannot match inherited `&` with `&mut` pattern --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:20:29 | LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) { - | ^^^^^^ ------------------------- this expression has type `&Option>>` - | | - | expected integer, found `&mut _` + | ^^^^^ | - = note: expected type `{integer}` - found mutable reference `&mut _` +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) { + | ~ -error[E0308]: mismatched types +error: cannot match inherited `&` with `&mut` pattern --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:23:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` - | | - | expected `Option<{integer}>`, found `&mut _` + | ^^^^^ | - = note: expected enum `Option<{integer}>` - found mutable reference `&mut _` +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(x)) = &Some(Some(0)) { + | ~ -error[E0308]: mismatched types +error: cannot match inherited `&` with `&mut` pattern --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17 | LL | if let Some(&mut Some(x)) = &Some(Some(0)) { - | ^^^^^^^^^^^^ -------------- this expression has type `&Option>` - | | - | expected `Option<{integer}>`, found `&mut _` + | ^^^^^ | - = note: expected enum `Option<{integer}>` - found mutable reference `&mut _` +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(x)) = &Some(Some(0)) { + | ~ error[E0308]: mismatched types --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:30:9 @@ -81,9 +81,9 @@ error[E0308]: mismatched types LL | let &mut _ = &&0; | ^^^^^^ --- this expression has type `&&{integer}` | | - | expected integer, found `&mut _` + | types differ in mutability | - = note: expected type `{integer}` + = note: expected reference `&&{integer}` found mutable reference `&mut _` error[E0308]: mismatched types @@ -92,11 +92,66 @@ error[E0308]: mismatched types LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0; | ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` | | - | expected integer, found `&mut _` + | types differ in mutability | - = note: expected type `{integer}` + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}` found mutable reference `&mut _` -error: aborting due to 9 previous errors +error: cannot match inherited `&` with `&mut` pattern + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:36:17 + | +LL | if let Some(&mut Some(&_)) = &Some(&mut Some(0)) { + | ^^^^^ + | +help: replace this `&mut` pattern with `&` + | +LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) { + | ~ + +error: cannot match inherited `&` with `&mut` pattern + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:40:22 + | +LL | if let Some(Some(&mut x)) = &Some(Some(&mut 0)) { + | ^^^^^ + | +help: replace this `&mut` pattern with `&` + | +LL | if let Some(Some(&x)) = &Some(Some(&mut 0)) { + | ~ + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:44:9 + | +LL | let &mut _ = &&mut 0; + | ^^^^^^ ------- this expression has type `&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:47:9 + | +LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0; + | ^^^^^^ --------------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:50:14 + | +LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; + | ^^^^^^^^^^^^^^^^ -------------------------- this expression has type `&mut &&&&mut &&&mut &mut {integer}` + | | + | types differ in mutability + | + = note: expected reference `&&&&mut &&&mut &mut {integer}` + found mutable reference `&mut _` + +error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0308`. From 0746577fa27f2a322f3ab5f4e85c6eeb51c6fc6c Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 15 May 2024 16:55:54 -0400 Subject: [PATCH 008/154] Gate implicit mutable by-reference bindings behind `mut ref` --- compiler/rustc_feature/src/removed.rs | 2 ++ compiler/rustc_feature/src/unstable.rs | 2 -- compiler/rustc_hir_typeck/src/pat.rs | 34 ++++++++++++------- .../ref_pat_eat_one_layer_2024_fail.rs | 10 ++++++ .../ref_pat_eat_one_layer_2024_fail.stderr | 25 ++++++++++++-- ...ure-gate-mut_preserve_binding_mode_2024.rs | 14 -------- ...gate-mut_preserve_binding_mode_2024.stderr | 31 ----------------- tests/ui/pattern/match_ergonomics_2024.fixed | 2 +- tests/ui/pattern/match_ergonomics_2024.rs | 2 +- .../pattern/mut_preserve_binding_mode_2021.rs | 2 +- .../pattern/mut_preserve_binding_mode_2024.rs | 2 +- 11 files changed, 61 insertions(+), 65 deletions(-) delete mode 100644 tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs delete mode 100644 tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index f1afde31803e..aea447b2aff1 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -128,6 +128,8 @@ declare_features! ( /// Allows the use of type alias impl trait in function return positions (removed, min_type_alias_impl_trait, "1.56.0", Some(63063), Some("removed in favor of full type_alias_impl_trait")), + /// Make `mut` not reset the binding mode on edition >= 2024. + (removed, mut_preserve_binding_mode_2024, "1.79.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024`")), (removed, needs_allocator, "1.4.0", Some(27389), Some("subsumed by `#![feature(allocator_internals)]`")), /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8 diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 1a058a121f3a..a4ccb0f1412e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -527,8 +527,6 @@ declare_features! ( (unstable, more_qualified_paths, "1.54.0", Some(86935)), /// Allows the `#[must_not_suspend]` attribute. (unstable, must_not_suspend, "1.57.0", Some(83310)), - /// Make `mut` not reset the binding mode on edition >= 2024. - (incomplete, mut_preserve_binding_mode_2024, "1.79.0", Some(123076)), /// Allows `mut ref` and `mut ref mut` identifier patterns. (incomplete, mut_ref, "1.79.0", Some(123076)), /// Allows using `#[naked]` on functions. diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 6cd74961cc7f..8e3b19f79a5b 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -12,7 +12,7 @@ use rustc_infer::infer; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_middle::{bug, span_bug}; -use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; +use rustc_session::{lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS, parse::feature_err}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::Spanned; @@ -669,17 +669,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Determine the binding mode... let bm = match user_bind_annot { - // `mut` resets binding mode on edition <= 2021 - BindingMode(ByRef::No, Mutability::Mut) - if !(pat.span.at_least_rust_2024() - && self.tcx.features().mut_preserve_binding_mode_2024) - && matches!(def_br, ByRef::Yes(_)) => - { - self.typeck_results - .borrow_mut() - .rust_2024_migration_desugared_pats_mut() - .insert(pat_info.top_info.hir_id); - BindingMode(ByRef::No, Mutability::Mut) + BindingMode(ByRef::No, Mutability::Mut) if matches!(def_br, ByRef::Yes(_)) => { + if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 { + if !self.tcx.features().mut_ref { + feature_err( + &self.tcx.sess, + sym::mut_ref, + pat.span.until(ident.span), + "binding cannot be both mutable and by-reference", + ) + .emit(); + } + + BindingMode(def_br, Mutability::Mut) + } else { + // `mut` resets binding mode on edition <= 2021 + self.typeck_results + .borrow_mut() + .rust_2024_migration_desugared_pats_mut() + .insert(pat_info.top_info.hir_id); + BindingMode(ByRef::No, Mutability::Mut) + } } BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl), BindingMode(ByRef::Yes(_), _) => user_bind_annot, diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs index a2a0c73b53b2..40e8293e2411 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs @@ -49,4 +49,14 @@ pub fn main() { let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; //~^ ERROR: mismatched types + + struct Foo(u8); + + let Foo(mut a) = &Foo(0); + //~^ ERROR: binding cannot be both mutable and by-reference + a = &42; + + let Foo(mut a) = &mut Foo(0); + //~^ ERROR: binding cannot be both mutable and by-reference + a = &mut 42; } diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr index cad67b4f8d67..26317e43d023 100644 --- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr +++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr @@ -152,6 +152,27 @@ LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0; = note: expected reference `&&&&mut &&&mut &mut {integer}` found mutable reference `&mut _` -error: aborting due to 14 previous errors +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:55:13 + | +LL | let Foo(mut a) = &Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -For more information about this error, try `rustc --explain E0308`. +error[E0658]: binding cannot be both mutable and by-reference + --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:59:13 + | +LL | let Foo(mut a) = &mut Foo(0); + | ^^^^ + | + = note: see issue #123076 for more information + = help: add `#![feature(mut_ref)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 16 previous errors + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs deleted file mode 100644 index 15c542e6bf10..000000000000 --- a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ edition: 2024 -//@ compile-flags: -Zunstable-options - -struct Foo(u8); - -fn main() { - let Foo(mut a) = &Foo(0); - a = &42; - //~^ ERROR: mismatched types - - let Foo(mut a) = &mut Foo(0); - a = &mut 42; - //~^ ERROR: mismatched types -} diff --git a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr deleted file mode 100644 index 6d0a034be21c..000000000000 --- a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:8:9 - | -LL | let Foo(mut a) = &Foo(0); - | ----- expected due to the type of this binding -LL | a = &42; - | ^^^ expected `u8`, found `&{integer}` - | -help: consider removing the borrow - | -LL - a = &42; -LL + a = 42; - | - -error[E0308]: mismatched types - --> $DIR/feature-gate-mut_preserve_binding_mode_2024.rs:12:9 - | -LL | let Foo(mut a) = &mut Foo(0); - | ----- expected due to the type of this binding -LL | a = &mut 42; - | ^^^^^^^ expected `u8`, found `&mut {integer}` - | -help: consider removing the borrow - | -LL - a = &mut 42; -LL + a = 42; - | - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/pattern/match_ergonomics_2024.fixed b/tests/ui/pattern/match_ergonomics_2024.fixed index d8dbcb217c04..1ec2b5a214bf 100644 --- a/tests/ui/pattern/match_ergonomics_2024.fixed +++ b/tests/ui/pattern/match_ergonomics_2024.fixed @@ -2,7 +2,7 @@ //@ run-rustfix //@ rustfix-only-machine-applicable //@ aux-build:match_ergonomics_2024_macros.rs -#![feature(mut_preserve_binding_mode_2024, ref_pat_eat_one_layer_2024)] +#![feature(mut_ref, ref_pat_eat_one_layer_2024)] #![allow(incomplete_features, unused)] #![deny(rust_2024_incompatible_pat)] diff --git a/tests/ui/pattern/match_ergonomics_2024.rs b/tests/ui/pattern/match_ergonomics_2024.rs index 38dc0c8bebb2..c9f992c12d4a 100644 --- a/tests/ui/pattern/match_ergonomics_2024.rs +++ b/tests/ui/pattern/match_ergonomics_2024.rs @@ -2,7 +2,7 @@ //@ run-rustfix //@ rustfix-only-machine-applicable //@ aux-build:match_ergonomics_2024_macros.rs -#![feature(mut_preserve_binding_mode_2024, ref_pat_eat_one_layer_2024)] +#![feature(mut_ref, ref_pat_eat_one_layer_2024)] #![allow(incomplete_features, unused)] #![deny(rust_2024_incompatible_pat)] diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2021.rs b/tests/ui/pattern/mut_preserve_binding_mode_2021.rs index befa49fdc247..282e0ef95d22 100644 --- a/tests/ui/pattern/mut_preserve_binding_mode_2021.rs +++ b/tests/ui/pattern/mut_preserve_binding_mode_2021.rs @@ -1,6 +1,6 @@ //@ edition: 2021 //@ compile-flags: -Zunstable-options -#![feature(mut_preserve_binding_mode_2024)] +#![feature(ref_pat_eat_one_layer_2024)] #![allow(incomplete_features)] struct Foo(u8); diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2024.rs b/tests/ui/pattern/mut_preserve_binding_mode_2024.rs index 5454962e16ce..19aa73573b46 100644 --- a/tests/ui/pattern/mut_preserve_binding_mode_2024.rs +++ b/tests/ui/pattern/mut_preserve_binding_mode_2024.rs @@ -1,7 +1,7 @@ //@ run-pass //@ edition: 2024 //@ compile-flags: -Zunstable-options -#![feature(mut_preserve_binding_mode_2024)] +#![feature(mut_ref, ref_pat_eat_one_layer_2024)] #![allow(incomplete_features, unused)] struct Foo(u8); From af75014cc52a97c93eb3d115441337874f525236 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 15 May 2024 17:20:18 -0400 Subject: [PATCH 009/154] "No `ref mut` behind `&`" on all editions --- compiler/rustc_hir_typeck/src/pat.rs | 35 ++++++++++++----------- tests/ui/pattern/no_ref_mut_behind_and.rs | 9 ++++++ 2 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 tests/ui/pattern/no_ref_mut_behind_and.rs diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 8e3b19f79a5b..617c08181fb0 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -406,7 +406,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, mut def_br: ByRef, - mut max_ref_mutability: MutblCap, + mut max_ref_mutbl: MutblCap, ) -> (Ty<'tcx>, ByRef, MutblCap) { let mut expected = self.try_structurally_resolve_type(pat.span, expected); // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example, @@ -438,10 +438,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); } - if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 { - def_br = def_br.cap_ref_mutability(max_ref_mutability.as_mutbl()); + if self.tcx.features().ref_pat_eat_one_layer_2024 { + def_br = def_br.cap_ref_mutability(max_ref_mutbl.as_mutbl()); if def_br == ByRef::Yes(Mutability::Not) { - max_ref_mutability = MutblCap::Not; + max_ref_mutbl = MutblCap::Not; } } @@ -453,7 +453,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .insert(pat.hir_id, pat_adjustments); } - (expected, def_br, max_ref_mutability) + (expected, def_br, max_ref_mutbl) } fn check_pat_lit( @@ -2130,18 +2130,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut expected: Ty<'tcx>, mut pat_info: PatInfo<'tcx, '_>, ) -> Ty<'tcx> { - let new_match_ergonomics = - pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024; + let no_ref_mut_behind_and = self.tcx.features().ref_pat_eat_one_layer_2024; + let new_match_ergonomics = pat.span.at_least_rust_2024() && no_ref_mut_behind_and; - if new_match_ergonomics { - let pat_prefix_span = - inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end)); + let pat_prefix_span = + inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end)); + if no_ref_mut_behind_and { if pat_mutbl == Mutability::Not { // Prevent the inner pattern from binding with `ref mut`. pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span); } + } else { + pat_info.max_ref_mutbl = MutblCap::Mut; + } + if new_match_ergonomics { if let ByRef::Yes(inh_mut) = pat_info.binding_mode { // ref pattern consumes inherited reference @@ -2179,8 +2183,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .rust_2024_migration_desugared_pats_mut() .insert(pat_info.top_info.hir_id); } - - pat_info.max_ref_mutbl = MutblCap::Mut; } let tcx = self.tcx; @@ -2195,16 +2197,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // the bad interactions of the given hack detailed in (note_1). debug!("check_pat_ref: expected={:?}", expected); match *expected.kind() { - ty::Ref(_, r_ty, r_mutbl) if r_mutbl >= pat_mutbl && new_match_ergonomics => { - if r_mutbl == Mutability::Not { + ty::Ref(_, r_ty, r_mutbl) + if (new_match_ergonomics && r_mutbl >= pat_mutbl) + || r_mutbl == pat_mutbl => + { + if no_ref_mut_behind_and && r_mutbl == Mutability::Not { pat_info.max_ref_mutbl = MutblCap::Not; } (expected, r_ty) } - ty::Ref(_, r_ty, r_mutbl) if r_mutbl == pat_mutbl => (expected, r_ty), - _ => { let inner_ty = self.next_ty_var(inner.span); let ref_ty = self.new_ref_ty(pat.span, pat_mutbl, inner_ty); diff --git a/tests/ui/pattern/no_ref_mut_behind_and.rs b/tests/ui/pattern/no_ref_mut_behind_and.rs new file mode 100644 index 000000000000..c18d64904d03 --- /dev/null +++ b/tests/ui/pattern/no_ref_mut_behind_and.rs @@ -0,0 +1,9 @@ +//@ edition: 2021 +//@ run-pass +#![allow(incomplete_features)] +#![feature(ref_pat_eat_one_layer_2024)] + +fn main() { + let &[[x]] = &[&mut [42]]; + let _: &i32 = x; +} From d6e4fe569c84c6a9d20690f139ad15a3d3da9550 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Wed, 22 May 2024 09:26:02 -0400 Subject: [PATCH 010/154] A custom error message for lending iterators --- compiler/rustc_resolve/messages.ftl | 4 ++ compiler/rustc_resolve/src/errors.rs | 9 +++++ compiler/rustc_resolve/src/late.rs | 40 ++++++++++++++++--- tests/ui/lifetimes/no_lending_iterators.rs | 12 ++++++ .../ui/lifetimes/no_lending_iterators.stderr | 14 +++++++ 5 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 tests/ui/lifetimes/no_lending_iterators.rs create mode 100644 tests/ui/lifetimes/no_lending_iterators.stderr diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index f824e4faf5d0..90339b2498b4 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -234,6 +234,10 @@ resolve_items_in_traits_are_not_importable = resolve_label_with_similar_name_reachable = a label with a similar name is reachable +resolve_lending_iterator_report_error = + associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type. + .note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type. + resolve_lifetime_param_in_enum_discriminant = lifetime parameters may not be used in enum discriminant values diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index edfeacec7e3b..e9989b803e8a 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -882,6 +882,15 @@ pub(crate) struct ElidedAnonymousLivetimeReportError { pub(crate) suggestion: Option, } +#[derive(Diagnostic)] +#[diag(resolve_lending_iterator_report_error)] +pub(crate) struct LendingIteratorReportError { + #[primary_span] + pub(crate) lifetime: Span, + #[note] + pub(crate) ty: Span, +} + #[derive(Subdiagnostic)] #[multipart_suggestion( resolve_elided_anonymous_lifetime_report_error_suggestion, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 63d0d6c260db..08196619befa 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -9,7 +9,7 @@ use crate::{errors, path_names_to_string, rustdoc, BindingError, Finalize, LexicalScopeBinding}; use crate::{BindingKey, Used}; use crate::{Module, ModuleOrUniformRoot, NameBinding, ParentScope, PathResult}; -use crate::{ResolutionError, Resolver, Segment, UseError}; +use crate::{ResolutionError, Resolver, Segment, TyCtxt, UseError}; use rustc_ast::ptr::P; use rustc_ast::visit::{visit_opt, walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}; @@ -1703,10 +1703,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { break; } } - self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError { - span: lifetime.ident.span, - suggestion, - }); + + // Is it caused by user trying to implement a lending iterator? + if !self.in_func_body + && let Some((module, _)) = &self.current_trait_ref + && let Some(ty) = &self.diag_metadata.current_self_type + && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind + && def_id_matches_path( + self.r.tcx, + trait_id, + &["core", "iter", "traits", "iterator", "Iterator"], + ) + { + self.r.dcx().emit_err(errors::LendingIteratorReportError { + lifetime: lifetime.ident.span, + ty: ty.span(), + }); + } else { + self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError { + span: lifetime.ident.span, + suggestion, + }); + } } else { self.r.dcx().emit_err(errors::ExplicitAnonymousLivetimeReportError { span: lifetime.ident.span, @@ -4824,3 +4842,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } + +/// Check if definition matches a path +fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str]) -> bool { + let mut path = expected_path.iter().rev(); + while let (Some(parent), Some(next_step)) = (tcx.opt_parent(def_id), path.next()) { + if !tcx.opt_item_name(def_id).map_or(false, |n| n.as_str() == *next_step) { + return false; + } + def_id = parent; + } + return true; +} diff --git a/tests/ui/lifetimes/no_lending_iterators.rs b/tests/ui/lifetimes/no_lending_iterators.rs new file mode 100644 index 000000000000..1f8340672182 --- /dev/null +++ b/tests/ui/lifetimes/no_lending_iterators.rs @@ -0,0 +1,12 @@ +struct Data(String); + +impl Iterator for Data { + type Item = &str; + //~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type. + + fn next(&mut self) -> Option { + Some(&self.0) + } +} + +fn main() {} diff --git a/tests/ui/lifetimes/no_lending_iterators.stderr b/tests/ui/lifetimes/no_lending_iterators.stderr new file mode 100644 index 000000000000..d052bfac3840 --- /dev/null +++ b/tests/ui/lifetimes/no_lending_iterators.stderr @@ -0,0 +1,14 @@ +error: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type. + --> $DIR/no_lending_iterators.rs:4:17 + | +LL | type Item = &str; + | ^ + | +note: you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type. + --> $DIR/no_lending_iterators.rs:3:19 + | +LL | impl Iterator for Data { + | ^^^^ + +error: aborting due to 1 previous error + From b70fb4159be7ea3e549a242cf7a6e4ebcb41f168 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Fri, 24 May 2024 11:20:33 -0400 Subject: [PATCH 011/154] And more general error --- compiler/rustc_resolve/messages.ftl | 6 +++- compiler/rustc_resolve/src/errors.rs | 8 ++++++ compiler/rustc_resolve/src/late.rs | 28 +++++++++++++------ .../assoc-type.rs | 2 +- .../assoc-type.stderr | 4 +-- tests/ui/lifetimes/no_lending_iterators.rs | 25 ++++++++++++++++- .../ui/lifetimes/no_lending_iterators.stderr | 20 +++++++++++-- 7 files changed, 78 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl index 90339b2498b4..358f25e23343 100644 --- a/compiler/rustc_resolve/messages.ftl +++ b/compiler/rustc_resolve/messages.ftl @@ -11,6 +11,10 @@ resolve_added_macro_use = resolve_ancestor_only = visibilities can only be restricted to ancestor modules +resolve_anonymous_livetime_non_gat_report_error = + in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + .label = this lifetime must come from the implemented type + resolve_arguments_macro_use_not_allowed = arguments to `macro_use` are not allowed here resolve_associated_const_with_similar_name_exists = @@ -235,7 +239,7 @@ resolve_label_with_similar_name_reachable = a label with a similar name is reachable resolve_lending_iterator_report_error = - associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type. + associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type .note = you can't create an `Iterator` that borrows each `Item` from itself, but you can instead create a new type that borrows your existing type and implement `Iterator` for that new type. resolve_lifetime_param_in_enum_discriminant = diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index e9989b803e8a..0620f3d709eb 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -891,6 +891,14 @@ pub(crate) struct LendingIteratorReportError { pub(crate) ty: Span, } +#[derive(Diagnostic)] +#[diag(resolve_anonymous_livetime_non_gat_report_error)] +pub(crate) struct AnonymousLivetimeNonGatReportError { + #[primary_span] + #[label] + pub(crate) lifetime: Span, +} + #[derive(Subdiagnostic)] #[multipart_suggestion( resolve_elided_anonymous_lifetime_report_error_suggestion, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 08196619befa..8f80b9ad5fdc 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -629,6 +629,9 @@ struct DiagMetadata<'ast> { in_assignment: Option<&'ast Expr>, is_assign_rhs: bool, + /// If we are setting an associated type in trait impl, is it a non-GAT type? + in_non_gat_assoc_type: Option, + /// Used to detect possible `.` -> `..` typo when calling methods. in_range: Option<(&'ast Expr, &'ast Expr)>, @@ -1704,21 +1707,28 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } } - // Is it caused by user trying to implement a lending iterator? + // are we trying to use an anonymous lifetime + // on a non GAT associated trait type? if !self.in_func_body && let Some((module, _)) = &self.current_trait_ref && let Some(ty) = &self.diag_metadata.current_self_type + && Some(true) == self.diag_metadata.in_non_gat_assoc_type && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind - && def_id_matches_path( + { + if def_id_matches_path( self.r.tcx, trait_id, &["core", "iter", "traits", "iterator", "Iterator"], - ) - { - self.r.dcx().emit_err(errors::LendingIteratorReportError { - lifetime: lifetime.ident.span, - ty: ty.span(), - }); + ) { + self.r.dcx().emit_err(errors::LendingIteratorReportError { + lifetime: lifetime.ident.span, + ty: ty.span(), + }); + } else { + self.r.dcx().emit_err(errors::AnonymousLivetimeNonGatReportError { + lifetime: lifetime.ident.span, + }); + } } else { self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError { span: lifetime.ident.span, @@ -3076,6 +3086,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); } AssocItemKind::Type(box TyAlias { generics, .. }) => { + self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty()); debug!("resolve_implementation AssocItemKind::Type"); // We also need a new scope for the impl item type parameters. self.with_generic_param_rib( @@ -3104,6 +3115,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { }); }, ); + self.diag_metadata.in_non_gat_assoc_type = None; } AssocItemKind::Delegation(box delegation) => { debug!("resolve_implementation AssocItemKind::Delegation"); diff --git a/tests/ui/impl-header-lifetime-elision/assoc-type.rs b/tests/ui/impl-header-lifetime-elision/assoc-type.rs index b0089a37aa05..db3c416540fc 100644 --- a/tests/ui/impl-header-lifetime-elision/assoc-type.rs +++ b/tests/ui/impl-header-lifetime-elision/assoc-type.rs @@ -9,7 +9,7 @@ trait MyTrait { impl MyTrait for &i32 { type Output = &i32; - //~^ ERROR `&` without an explicit lifetime name cannot be used here + //~^ ERROR 11:19: 11:20: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type } impl MyTrait for &u32 { diff --git a/tests/ui/impl-header-lifetime-elision/assoc-type.stderr b/tests/ui/impl-header-lifetime-elision/assoc-type.stderr index c4f27e0b80e4..e650eeca48ad 100644 --- a/tests/ui/impl-header-lifetime-elision/assoc-type.stderr +++ b/tests/ui/impl-header-lifetime-elision/assoc-type.stderr @@ -1,8 +1,8 @@ -error[E0637]: `&` without an explicit lifetime name cannot be used here +error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type --> $DIR/assoc-type.rs:11:19 | LL | type Output = &i32; - | ^ explicit lifetime name needed here + | ^ this lifetime must come from the implemented type error[E0637]: `'_` cannot be used here --> $DIR/assoc-type.rs:16:20 diff --git a/tests/ui/lifetimes/no_lending_iterators.rs b/tests/ui/lifetimes/no_lending_iterators.rs index 1f8340672182..21395475fb3d 100644 --- a/tests/ui/lifetimes/no_lending_iterators.rs +++ b/tests/ui/lifetimes/no_lending_iterators.rs @@ -2,11 +2,34 @@ struct Data(String); impl Iterator for Data { type Item = &str; - //~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type. + //~^ ERROR 4:17: 4:18: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type fn next(&mut self) -> Option { Some(&self.0) } } +trait Bar { + type Item; + fn poke(&mut self, item: Self::Item); +} + +impl Bar for usize { + type Item = &usize; + //~^ ERROR 18:17: 18:18: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + + fn poke(&mut self, item: Self::Item) { + self += *item; + } +} + +impl Bar for isize { + type Item<'a> = &'a isize; + //~^ ERROR 27:14: 27:18: lifetime parameters or bounds on type `Item` do not match the trait declaration [E0195] + + fn poke(&mut self, item: Self::Item) { + self += *item; + } +} + fn main() {} diff --git a/tests/ui/lifetimes/no_lending_iterators.stderr b/tests/ui/lifetimes/no_lending_iterators.stderr index d052bfac3840..c3784770d792 100644 --- a/tests/ui/lifetimes/no_lending_iterators.stderr +++ b/tests/ui/lifetimes/no_lending_iterators.stderr @@ -1,4 +1,4 @@ -error: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type. +error: associated type `Iterator::Item` is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type --> $DIR/no_lending_iterators.rs:4:17 | LL | type Item = &str; @@ -10,5 +10,21 @@ note: you can't create an `Iterator` that borrows each `Item` from itself, but y LL | impl Iterator for Data { | ^^^^ -error: aborting due to 1 previous error +error: in the trait associated type is declared without lifetime parameters, so using a borrowed type for them requires that lifetime to come from the implemented type + --> $DIR/no_lending_iterators.rs:18:17 + | +LL | type Item = &usize; + | ^ this lifetime must come from the implemented type +error[E0195]: lifetime parameters or bounds on type `Item` do not match the trait declaration + --> $DIR/no_lending_iterators.rs:27:14 + | +LL | type Item; + | - lifetimes in impl do not match this type in trait +... +LL | type Item<'a> = &'a isize; + | ^^^^ lifetimes do not match type in trait + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0195`. From 9f8b1caf2957f281f88577ff62b20811d5fcb419 Mon Sep 17 00:00:00 2001 From: Alona Enraght-Moony Date: Fri, 24 May 2024 17:17:25 +0000 Subject: [PATCH 012/154] Add intra-doc-links to rustc_middle crate-level docs. --- compiler/rustc_middle/src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index e52a5863fd03..ea7b8baf3f2c 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -4,15 +4,16 @@ //! has their own README with further details). //! //! - **HIR.** The "high-level (H) intermediate representation (IR)" is -//! defined in the `hir` module. +//! defined in the [`hir`] module. //! - **MIR.** The "mid-level (M) intermediate representation (IR)" is -//! defined in the `mir` module. This module contains only the +//! defined in the [`mir`] module. This module contains only the //! *definition* of the MIR; the passes that transform and operate //! on MIR are found in `rustc_const_eval` crate. //! - **Types.** The internal representation of types used in rustc is -//! defined in the `ty` module. This includes the **type context** -//! (or `tcx`), which is the central context during most of -//! compilation, containing the interners and other things. +//! defined in the [`ty`] module. This includes the +//! [**type context**][ty::TyCtxt] (or `tcx`), which is the central +//! context during most of compilation, containing the interners and +//! other things. //! //! For more information about how rustc works, see the [rustc dev guide]. //! From d6d2ff055e6c2865008fc94f658929964e04b566 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 27 May 2024 09:36:23 +1000 Subject: [PATCH 013/154] Remove a stray comment that shouldn't be here. --- compiler/rustc_expand/src/mbe/transcribe.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index e1f50876b058..3196b8260854 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -267,7 +267,6 @@ pub(super) fn transcribe<'a>( // some of the unnecessary whitespace. let ident = MacroRulesNormalizedIdent::new(original_ident); if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { - // njn: explain the use of alone here let tt = match cur_matched { MatchedSingle(ParseNtResult::Tt(tt)) => { // `tt`s are emitted into the output stream directly as "raw tokens", From 3607cee3e7009c91dfdf3d4f8669ac8156a36ac0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 27 May 2024 09:40:14 +1000 Subject: [PATCH 014/154] Use let chains in `pretty_printing_compatibility_hack`. To reduce indentation and improve readability. --- compiler/rustc_expand/src/base.rs | 71 ++++++++++++++----------------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 91af8758e516..470e8bf47f56 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1338,47 +1338,38 @@ pub fn parse_macro_name_and_helper_attrs( /// FIXME(#73933): Remove this eventually. fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool { let name = item.ident.name; - if name == sym::ProceduralMasqueradeDummyType { - if let ast::ItemKind::Enum(enum_def, _) = &item.kind { - if let [variant] = &*enum_def.variants { - if variant.ident.name == sym::Input { - let filename = sess.source_map().span_to_filename(item.ident.span); - if let FileName::Real(real) = filename { - if let Some(c) = real - .local_path() - .unwrap_or(Path::new("")) - .components() - .flat_map(|c| c.as_os_str().to_str()) - .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental")) - { - let crate_matches = if c.starts_with("allsorts-rental") { - true - } else { - let mut version = c.trim_start_matches("rental-").split('.'); - version.next() == Some("0") - && version.next() == Some("5") - && version - .next() - .and_then(|c| c.parse::().ok()) - .is_some_and(|v| v < 6) - }; + if name == sym::ProceduralMasqueradeDummyType + && let ast::ItemKind::Enum(enum_def, _) = &item.kind + && let [variant] = &*enum_def.variants + && variant.ident.name == sym::Input + && let FileName::Real(real) = sess.source_map().span_to_filename(item.ident.span) + && let Some(c) = real + .local_path() + .unwrap_or(Path::new("")) + .components() + .flat_map(|c| c.as_os_str().to_str()) + .find(|c| c.starts_with("rental") || c.starts_with("allsorts-rental")) + { + let crate_matches = if c.starts_with("allsorts-rental") { + true + } else { + let mut version = c.trim_start_matches("rental-").split('.'); + version.next() == Some("0") + && version.next() == Some("5") + && version.next().and_then(|c| c.parse::().ok()).is_some_and(|v| v < 6) + }; - if crate_matches { - sess.psess.buffer_lint( - PROC_MACRO_BACK_COMPAT, - item.ident.span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::ProcMacroBackCompat { - crate_name: "rental".to_string(), - fixed_version: "0.5.6".to_string(), - }, - ); - return true; - } - } - } - } - } + if crate_matches { + sess.psess.buffer_lint( + PROC_MACRO_BACK_COMPAT, + item.ident.span, + ast::CRATE_NODE_ID, + BuiltinLintDiag::ProcMacroBackCompat { + crate_name: "rental".to_string(), + fixed_version: "0.5.6".to_string(), + }, + ); + return true; } } false From cf0c2c73334eb1c7c6a45e2603244238e4bd3ef7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 27 May 2024 09:00:48 +1000 Subject: [PATCH 015/154] Convert `proc_macro_back_compat` lint to an unconditional error. We still check for the `rental`/`allsorts-rental` crates. But now if they are detected we just emit a fatal error, instead of emitting a warning and providing alternative behaviour. The original "hack" implementing alternative behaviour was added in #73345. The lint was added in #83127. The tracking issue is #83125. The direct motivation for the change is that providing the alternative behaviour is interfering with #125174 and follow-on work. --- compiler/rustc_expand/messages.ftl | 3 + compiler/rustc_expand/src/base.rs | 41 ++-- compiler/rustc_expand/src/errors.rs | 10 + compiler/rustc_expand/src/proc_macro.rs | 21 +- .../rustc_expand/src/proc_macro_server.rs | 29 ++- compiler/rustc_lint/messages.ftl | 3 - .../rustc_lint/src/context/diagnostics.rs | 3 - compiler/rustc_lint/src/lints.rs | 8 - compiler/rustc_lint_defs/src/builtin.rs | 48 ----- compiler/rustc_lint_defs/src/lib.rs | 4 - .../pretty-print-hack-show.local.stderr | 183 +----------------- .../pretty-print-hack-show.local.stdout | 44 ----- .../pretty-print-hack-show.remapped.stderr | 183 +----------------- .../pretty-print-hack-show.remapped.stdout | 44 ----- 14 files changed, 54 insertions(+), 570 deletions(-) delete mode 100644 tests/ui/proc-macro/pretty-print-hack-show.local.stdout delete mode 100644 tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index 530b37aadb1f..718129c5b6e2 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -124,6 +124,9 @@ expand_not_a_meta_item = expand_only_one_word = must only be one word +expand_proc_macro_back_compat = using an old version of `{$crate_name}` + .note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives + expand_proc_macro_derive_panicked = proc-macro derive panicked .help = message: {$message} diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 470e8bf47f56..4539129bd0f7 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -14,8 +14,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult}; use rustc_feature::Features; -use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; -use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, RegisteredTools}; +use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools}; use rustc_parse::{parser, MACRO_ARGUMENTS}; use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::{parse::ParseSess, Limit, Session}; @@ -1330,13 +1329,10 @@ pub fn parse_macro_name_and_helper_attrs( Some((trait_ident.name, proc_attrs)) } -/// This nonterminal looks like some specific enums from -/// `proc-macro-hack` and `procedural-masquerade` crates. -/// We need to maintain some special pretty-printing behavior for them due to incorrect -/// asserts in old versions of those crates and their wide use in the ecosystem. -/// See issue #73345 for more details. +/// If this item looks like a specific enums from `rental`, emit a fatal error. +/// See #73345 and #83125 for more details. /// FIXME(#73933): Remove this eventually. -fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool { +fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) { let name = item.ident.name; if name == sym::ProceduralMasqueradeDummyType && let ast::ItemKind::Enum(enum_def, _) = &item.kind @@ -1360,41 +1356,36 @@ fn pretty_printing_compatibility_hack(item: &Item, sess: &Session) -> bool { }; if crate_matches { - sess.psess.buffer_lint( - PROC_MACRO_BACK_COMPAT, - item.ident.span, - ast::CRATE_NODE_ID, - BuiltinLintDiag::ProcMacroBackCompat { - crate_name: "rental".to_string(), - fixed_version: "0.5.6".to_string(), - }, - ); - return true; + // FIXME: make this translatable + #[allow(rustc::untranslatable_diagnostic)] + sess.psess.dcx.emit_fatal(errors::ProcMacroBackCompat { + crate_name: "rental".to_string(), + fixed_version: "0.5.6".to_string(), + }); } } - false } -pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) -> bool { +pub(crate) fn ann_pretty_printing_compatibility_hack(ann: &Annotatable, sess: &Session) { let item = match ann { Annotatable::Item(item) => item, Annotatable::Stmt(stmt) => match &stmt.kind { ast::StmtKind::Item(item) => item, - _ => return false, + _ => return, }, - _ => return false, + _ => return, }; pretty_printing_compatibility_hack(item, sess) } -pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) -> bool { +pub(crate) fn nt_pretty_printing_compatibility_hack(nt: &Nonterminal, sess: &Session) { let item = match nt { Nonterminal::NtItem(item) => item, Nonterminal::NtStmt(stmt) => match &stmt.kind { ast::StmtKind::Item(item) => item, - _ => return false, + _ => return, }, - _ => return false, + _ => return, }; pretty_printing_compatibility_hack(item, sess) } diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index a5fc9e9d89c1..3f8b4661e5f5 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -440,3 +440,13 @@ pub(crate) struct EmptyDelegationList { #[primary_span] pub span: Span, } + +// This used to be the `proc_macro_back_compat` lint (#83125). It was later +// turned into a hard error. +#[derive(Diagnostic)] +#[diag(expand_proc_macro_back_compat)] +#[note] +pub struct ProcMacroBackCompat { + pub crate_name: String, + pub fixed_version: String, +} diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index 530059e53c21..c11369f505f8 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -4,14 +4,12 @@ use crate::proc_macro_server; use rustc_ast as ast; use rustc_ast::ptr::P; -use rustc_ast::token; use rustc_ast::tokenstream::TokenStream; -use rustc_data_structures::sync::Lrc; use rustc_errors::ErrorGuaranteed; use rustc_parse::parser::ForceCollect; use rustc_session::config::ProcMacroExecutionStrategy; use rustc_span::profiling::SpannedEventArgRecorder; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; struct MessagePipe { tx: std::sync::mpsc::SyncSender, @@ -120,18 +118,13 @@ impl MultiItemModifier for DeriveProcMacro { // We need special handling for statement items // (e.g. `fn foo() { #[derive(Debug)] struct Bar; }`) let is_stmt = matches!(item, Annotatable::Stmt(..)); - let hack = crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess); - let input = if hack { - let nt = match item { - Annotatable::Item(item) => token::NtItem(item), - Annotatable::Stmt(stmt) => token::NtStmt(stmt), - _ => unreachable!(), - }; - TokenStream::token_alone(token::Interpolated(Lrc::new(nt)), DUMMY_SP) - } else { - item.to_tokens() - }; + // We used to have an alternative behaviour for crates that needed it. + // We had a lint for a long time, but now we just emit a hard error. + // Eventually we might remove the special case hard error check + // altogether. See #73345. + crate::base::ann_pretty_printing_compatibility_hack(&item, &ecx.sess); + let input = item.to_tokens(); let stream = { let _timer = ecx.sess.prof.generic_activity_with_arg_recorder("expand_proc_macro", |recorder| { diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index ec7e4416b913..c2e799abae80 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -276,21 +276,20 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec { let stream = TokenStream::from_nonterminal_ast(&nt); - // A hack used to pass AST fragments to attribute and derive - // macros as a single nonterminal token instead of a token - // stream. Such token needs to be "unwrapped" and not - // represented as a delimited group. - // FIXME: It needs to be removed, but there are some - // compatibility issues (see #73345). - if crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess) { - trees.extend(Self::from_internal((stream, rustc))); - } else { - trees.push(TokenTree::Group(Group { - delimiter: pm::Delimiter::None, - stream: Some(stream), - span: DelimSpan::from_single(span), - })) - } + // We used to have an alternative behaviour for crates that + // needed it: a hack used to pass AST fragments to + // attribute and derive macros as a single nonterminal + // token instead of a token stream. Such token needs to be + // "unwrapped" and not represented as a delimited group. We + // had a lint for a long time, but now we just emit a hard + // error. Eventually we might remove the special case hard + // error check altogether. See #73345. + crate::base::nt_pretty_printing_compatibility_hack(&nt, rustc.ecx.sess); + trees.push(TokenTree::Group(Group { + delimiter: pm::Delimiter::None, + stream: Some(stream), + span: DelimSpan::from_single(span), + })) } OpenDelim(..) | CloseDelim(..) => unreachable!(), diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index a9304f27fe55..12488df260f7 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -629,9 +629,6 @@ lint_pattern_in_foreign = patterns aren't allowed in foreign function declaratio lint_private_extern_crate_reexport = extern crate `{$ident}` is private, and cannot be re-exported, consider declaring with `pub` -lint_proc_macro_back_compat = using an old version of `{$crate_name}` - .note = older versions of the `{$crate_name}` crate will stop compiling in future versions of Rust; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives - lint_proc_macro_derive_resolution_fallback = cannot find {$ns} `{$ident}` in this scope .label = names from parent modules are not accessible without an explicit import diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 26f34486a3de..194704156848 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -159,9 +159,6 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & BuiltinLintDiag::LegacyDeriveHelpers(label_span) => { lints::LegacyDeriveHelpers { span: label_span }.decorate_lint(diag); } - BuiltinLintDiag::ProcMacroBackCompat { crate_name, fixed_version } => { - lints::ProcMacroBackCompat { crate_name, fixed_version }.decorate_lint(diag); - } BuiltinLintDiag::OrPatternsBackCompat(suggestion_span, suggestion) => { lints::OrPatternsBackCompat { span: suggestion_span, suggestion }.decorate_lint(diag); } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 42963a11f71a..54cdc73ca789 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2542,14 +2542,6 @@ pub struct LegacyDeriveHelpers { pub span: Span, } -#[derive(LintDiagnostic)] -#[diag(lint_proc_macro_back_compat)] -#[note] -pub struct ProcMacroBackCompat { - pub crate_name: String, - pub fixed_version: String, -} - #[derive(LintDiagnostic)] #[diag(lint_or_patterns_back_compat)] pub struct OrPatternsBackCompat { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 13867319e5cd..81c2d10add54 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -75,7 +75,6 @@ declare_lint_pass! { PATTERNS_IN_FNS_WITHOUT_BODY, PRIVATE_BOUNDS, PRIVATE_INTERFACES, - PROC_MACRO_BACK_COMPAT, PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_LIFETIMES, @@ -3705,53 +3704,6 @@ declare_lint! { "detects invalid `#[doc(...)]` attributes", } -declare_lint! { - /// The `proc_macro_back_compat` lint detects uses of old versions of certain - /// proc-macro crates, which have hardcoded workarounds in the compiler. - /// - /// ### Example - /// - /// ```rust,ignore (needs-dependency) - /// - /// use time_macros_impl::impl_macros; - /// struct Foo; - /// impl_macros!(Foo); - /// ``` - /// - /// This will produce: - /// - /// ```text - /// warning: using an old version of `time-macros-impl` - /// ::: $DIR/group-compat-hack.rs:27:5 - /// | - /// LL | impl_macros!(Foo); - /// | ------------------ in this macro invocation - /// | - /// = note: `#[warn(proc_macro_back_compat)]` on by default - /// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - /// = note: for more information, see issue #83125 - /// = note: the `time-macros-impl` crate will stop compiling in futures version of Rust. Please update to the latest version of the `time` crate to avoid breakage - /// = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - /// ``` - /// - /// ### Explanation - /// - /// Eventually, the backwards-compatibility hacks present in the compiler will be removed, - /// causing older versions of certain crates to stop compiling. - /// This is a [future-incompatible] lint to ease the transition to an error. - /// See [issue #83125] for more details. - /// - /// [issue #83125]: https://github.com/rust-lang/rust/issues/83125 - /// [future-incompatible]: ../index.md#future-incompatible-lints - pub PROC_MACRO_BACK_COMPAT, - Deny, - "detects usage of old versions of certain proc-macro crates", - @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, - reference: "issue #83125 ", - }; -} - declare_lint! { /// The `rust_2021_incompatible_or_patterns` lint detects usage of old versions of or-patterns. /// diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c8a9fb02bf2e..746b668803b9 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -618,10 +618,6 @@ pub enum BuiltinLintDiag { is_foreign: bool, }, LegacyDeriveHelpers(Span), - ProcMacroBackCompat { - crate_name: String, - fixed_version: String, - }, OrPatternsBackCompat(Span, String), ReservedPrefix(Span, String), TrailingMacro(bool, Ident), diff --git a/tests/ui/proc-macro/pretty-print-hack-show.local.stderr b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr index 118882f73a3e..889cd0c90ebb 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.local.stderr +++ b/tests/ui/proc-macro/pretty-print-hack-show.local.stderr @@ -1,185 +1,6 @@ error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default + = note: older versions of the `rental` crate no longer compile; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 8 previous errors - -Future incompatibility report: Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/pretty-print-hack-show.local.stdout b/tests/ui/proc-macro/pretty-print-hack-show.local.stdout deleted file mode 100644 index 3d793d2a0145..000000000000 --- a/tests/ui/proc-macro/pretty-print-hack-show.local.stdout +++ /dev/null @@ -1,44 +0,0 @@ -PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } -PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } -PRINT-DERIVE INPUT (DEBUG): TokenStream [ - Ident { - ident: "enum", - span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0), - }, - Ident { - ident: "ProceduralMasqueradeDummyType", - span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0), - }, - Group { - delimiter: Brace, - stream: TokenStream [ - Ident { - ident: "Input", - span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0), - }, - ], - span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0), - }, -] -PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } -PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } -PRINT-DERIVE INPUT (DEBUG): TokenStream [ - Ident { - ident: "enum", - span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0), - }, - Ident { - ident: "ProceduralMasqueradeDummyType", - span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0), - }, - Group { - delimiter: Brace, - stream: TokenStream [ - Ident { - ident: "Input", - span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0), - }, - ], - span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0), - }, -] diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr index 118882f73a3e..889cd0c90ebb 100644 --- a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr +++ b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stderr @@ -1,185 +1,6 @@ error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default + = note: older versions of the `rental` crate no longer compile; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 8 previous errors - -Future incompatibility report: Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default - -Future breakage diagnostic: -error: using an old version of `rental` - --> $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6 - | -LL | enum ProceduralMasqueradeDummyType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #83125 - = note: older versions of the `rental` crate will stop compiling in future versions of Rust; please update to `rental` v0.5.6, or switch to one of the `rental` alternatives - = note: `#[deny(proc_macro_back_compat)]` on by default +error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout b/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout deleted file mode 100644 index 3d793d2a0145..000000000000 --- a/tests/ui/proc-macro/pretty-print-hack-show.remapped.stdout +++ /dev/null @@ -1,44 +0,0 @@ -PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } -PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } -PRINT-DERIVE INPUT (DEBUG): TokenStream [ - Ident { - ident: "enum", - span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:1: 4:5 (#0), - }, - Ident { - ident: "ProceduralMasqueradeDummyType", - span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:6: 4:35 (#0), - }, - Group { - delimiter: Brace, - stream: TokenStream [ - Ident { - ident: "Input", - span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:13:5: 13:10 (#0), - }, - ], - span: $DIR/pretty-print-hack/allsorts-rental-0.5.6/src/lib.rs:4:36: 14:2 (#0), - }, -] -PRINT-DERIVE INPUT (DISPLAY): enum ProceduralMasqueradeDummyType { Input, } -PRINT-DERIVE RE-COLLECTED (DISPLAY): enum ProceduralMasqueradeDummyType { Input } -PRINT-DERIVE INPUT (DEBUG): TokenStream [ - Ident { - ident: "enum", - span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:1: 4:5 (#0), - }, - Ident { - ident: "ProceduralMasqueradeDummyType", - span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:6: 4:35 (#0), - }, - Group { - delimiter: Brace, - stream: TokenStream [ - Ident { - ident: "Input", - span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:13:5: 13:10 (#0), - }, - ], - span: $DIR/pretty-print-hack/rental-0.5.5/src/lib.rs:4:36: 14:2 (#0), - }, -] From b4834a1c981b1ebddc9a4f33039f1348730540ba Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 28 May 2024 14:37:08 -0400 Subject: [PATCH 016/154] rewrite resolve-rename in rmake --- src/tools/run-make-support/src/rustc.rs | 6 ++++++ src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/resolve-rename/Makefile | 7 ------- tests/run-make/resolve-rename/rmake.rs | 15 +++++++++++++++ 4 files changed, 21 insertions(+), 8 deletions(-) delete mode 100644 tests/run-make/resolve-rename/Makefile create mode 100644 tests/run-make/resolve-rename/rmake.rs diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index 1c83b630861c..3e4e61218caa 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -70,6 +70,12 @@ impl Rustc { self } + /// Add a suffix in each output filename. + pub fn extra_filename(&mut self, suffix: &str) -> &mut Self { + self.cmd.arg(format!("-Cextra-filename={suffix}")); + self + } + /// Specify type(s) of output files to generate. pub fn emit(&mut self, kinds: &str) -> &mut Self { self.cmd.arg(format!("--emit={kinds}")); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 2329b8b44dea..845dd7f0eee9 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -216,7 +216,6 @@ run-make/remap-path-prefix-dwarf/Makefile run-make/remap-path-prefix/Makefile run-make/reproducible-build-2/Makefile run-make/reproducible-build/Makefile -run-make/resolve-rename/Makefile run-make/return-non-c-like-enum-from-c/Makefile run-make/return-non-c-like-enum/Makefile run-make/rlib-chain/Makefile diff --git a/tests/run-make/resolve-rename/Makefile b/tests/run-make/resolve-rename/Makefile deleted file mode 100644 index 00f83a5d6b2d..000000000000 --- a/tests/run-make/resolve-rename/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) -C extra-filename=-hash foo.rs - $(RUSTC) bar.rs - mv $(TMPDIR)/libfoo-hash.rlib $(TMPDIR)/libfoo-another-hash.rlib - $(RUSTC) baz.rs diff --git a/tests/run-make/resolve-rename/rmake.rs b/tests/run-make/resolve-rename/rmake.rs new file mode 100644 index 000000000000..7539d367758e --- /dev/null +++ b/tests/run-make/resolve-rename/rmake.rs @@ -0,0 +1,15 @@ +// If a library is compiled with -C extra-filename, the rust compiler +// will take this into account when searching for libraries. However, +// if that library is then renamed, the rust compiler should fall back +// to its regular library location logic and not immediately fail to find +// the renamed library. +// See https://github.com/rust-lang/rust/pull/49253 + +use run_make_support::{rustc, tmp_dir}; +use std::fs; +fn main() { + rustc().extra_filename("-hash").input("foo.rs").run(); + rustc().input("bar.rs").run(); + fs::rename(tmp_dir().join("libfoo-hash.rlib"), tmp_dir().join("libfoo-another-hash.rlib")); + rustc().input("baz.rs").run(); +} From d553d5ba2d77feb67fde6649c03e8d1c486eb278 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 28 May 2024 15:41:51 -0400 Subject: [PATCH 017/154] rewrite incr-prev-body-beyond-eof in rmake --- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../incr-prev-body-beyond-eof/Makefile | 19 ----------- .../incr-prev-body-beyond-eof/rmake.rs | 32 +++++++++++++++++++ 3 files changed, 32 insertions(+), 20 deletions(-) delete mode 100644 tests/run-make/incr-prev-body-beyond-eof/Makefile create mode 100644 tests/run-make/incr-prev-body-beyond-eof/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 845dd7f0eee9..4e69d67057a7 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -79,7 +79,6 @@ run-make/inaccessible-temp-dir/Makefile run-make/include_bytes_deps/Makefile run-make/incr-add-rust-src-component/Makefile run-make/incr-foreign-head-span/Makefile -run-make/incr-prev-body-beyond-eof/Makefile run-make/incremental-debugger-visualizer/Makefile run-make/incremental-session-fail/Makefile run-make/inline-always-many-cgu/Makefile diff --git a/tests/run-make/incr-prev-body-beyond-eof/Makefile b/tests/run-make/incr-prev-body-beyond-eof/Makefile deleted file mode 100644 index aa47552f52c9..000000000000 --- a/tests/run-make/incr-prev-body-beyond-eof/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# ignore-none no-std is not supported -# ignore-nvptx64-nvidia-cuda FIXME: can't find crate for `std` - -include ../tools.mk - -# Tests that we don't ICE during incremental compilation after modifying a -# function span such that its previous end line exceeds the number of lines -# in the new file, but its start line/column and length remain the same. - -SRC=$(TMPDIR)/src -INCR=$(TMPDIR)/incr - -all: - mkdir $(SRC) - mkdir $(INCR) - cp a.rs $(SRC)/main.rs - $(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET) - cp b.rs $(SRC)/main.rs - $(RUSTC) -C incremental=$(INCR) $(SRC)/main.rs --target $(TARGET) diff --git a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs new file mode 100644 index 000000000000..43f137fea20e --- /dev/null +++ b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs @@ -0,0 +1,32 @@ +// After modifying the span of a function, if the length of +// the span remained the same but the end line number became different, +// this would cause an internal compiler error (ICE), fixed in #76256. + +// This test compiles main.rs twice, first with end line 16 and +// then with end line 12. If compilation is successful, the end line +// was hashed by rustc in addition to the span length, and the fix still +// works. + +// FIXME: Ignore flags temporarily disabled for the test. +// ignore-none +// ignore-nvptx64-nvidia-cuda + +use run_make_support::{rustc, target, tmp_dir}; +use std::fs; + +fn main() { + fs::create_dir(tmp_dir().join("src")); + fs::create_dir(tmp_dir().join("incr")); + fs::copy("a.rs", tmp_dir().join("main.rs")); + rustc() + .incremental(tmp_dir().join("incr")) + .input(tmp_dir().join("src/main.rs")) + .target(target()) + .run(); + fs::copy("b.rs", tmp_dir().join("main.rs")); + rustc() + .incremental(tmp_dir().join("incr")) + .input(tmp_dir().join("src/main.rs")) + .target(target()) + .run(); +} From 7cd732f990ec341efdac53f6519a44b72e07861f Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Wed, 29 May 2024 14:19:09 +0200 Subject: [PATCH 018/154] Avoid `mut` and simplify initialization of `TASK_QUEUE` --- library/std/src/sys/pal/sgx/thread.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index 7d271e6d2b65..d70c6e31fb73 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -15,7 +15,7 @@ pub use self::task_queue::JoinNotifier; mod task_queue { use super::wait_notify; - use crate::sync::{Mutex, MutexGuard, Once}; + use crate::sync::{Mutex, MutexGuard}; pub type JoinHandle = wait_notify::Waiter; @@ -32,6 +32,8 @@ mod task_queue { done: JoinNotifier, } + unsafe impl Send for Task {} + impl Task { pub(super) fn new(p: Box) -> (Task, JoinHandle) { let (done, recv) = wait_notify::new(); @@ -45,18 +47,12 @@ mod task_queue { } } - #[cfg_attr(test, linkage = "available_externally")] - #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread15TASK_QUEUE_INITE"] - static TASK_QUEUE_INIT: Once = Once::new(); #[cfg_attr(test, linkage = "available_externally")] #[export_name = "_ZN16__rust_internals3std3sys3sgx6thread10TASK_QUEUEE"] - static mut TASK_QUEUE: Option>> = None; + static TASK_QUEUE: Mutex> = Mutex::new(Vec::new()); pub(super) fn lock() -> MutexGuard<'static, Vec> { - unsafe { - TASK_QUEUE_INIT.call_once(|| TASK_QUEUE = Some(Default::default())); - TASK_QUEUE.as_ref().unwrap().lock().unwrap() - } + TASK_QUEUE.lock().unwrap() } } From e485b193d07a77495dcdcb3f52f5976c9c9ca1f4 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 30 May 2024 19:45:27 -0400 Subject: [PATCH 019/154] Don't drop Upcast candidate in intercrate mode --- .../src/traits/select/candidate_assembly.rs | 6 ++++++ .../ui/specialization/dont-drop-upcast-candidate.rs | 13 +++++++++++++ .../dont-drop-upcast-candidate.stderr | 11 +++++++++++ 3 files changed, 30 insertions(+) create mode 100644 tests/ui/specialization/dont-drop-upcast-candidate.rs create mode 100644 tests/ui/specialization/dont-drop-upcast-candidate.stderr diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index fd7c47ad6fb3..f0ecbd833410 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -921,6 +921,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { param_env: ty::ParamEnv<'tcx>, cause: &ObligationCause<'tcx>, ) -> Option> { + // Don't drop any candidates in intercrate mode, as it's incomplete. + // (Not that it matters, since `Unsize` is not a stable trait.) + if self.infcx.intercrate { + return None; + } + let tcx = self.tcx(); if tcx.features().trait_upcasting { return None; diff --git a/tests/ui/specialization/dont-drop-upcast-candidate.rs b/tests/ui/specialization/dont-drop-upcast-candidate.rs new file mode 100644 index 000000000000..98d8cad7c1fb --- /dev/null +++ b/tests/ui/specialization/dont-drop-upcast-candidate.rs @@ -0,0 +1,13 @@ +#![feature(unsize)] + +use std::marker::Unsize; +use std::ops::Deref; + +trait Foo: Bar {} +trait Bar {} + +impl Bar for T where dyn Foo: Unsize {} +impl Bar for () {} +//~^ ERROR conflicting implementations of trait `Bar` for type `()` + +fn main() {} diff --git a/tests/ui/specialization/dont-drop-upcast-candidate.stderr b/tests/ui/specialization/dont-drop-upcast-candidate.stderr new file mode 100644 index 000000000000..dc0c54f9aa82 --- /dev/null +++ b/tests/ui/specialization/dont-drop-upcast-candidate.stderr @@ -0,0 +1,11 @@ +error[E0119]: conflicting implementations of trait `Bar` for type `()` + --> $DIR/dont-drop-upcast-candidate.rs:10:1 + | +LL | impl Bar for T where dyn Foo: Unsize {} + | ------------------------------------------------ first implementation here +LL | impl Bar for () {} + | ^^^^^^^^^^^^^^^ conflicting implementation for `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. From 5e802f07bae5a078c241ed1c2a122e756cbcad30 Mon Sep 17 00:00:00 2001 From: Hai-Hsin Date: Sat, 1 Jun 2024 23:13:33 +0800 Subject: [PATCH 020/154] rustc_codegen_ssa: fix get_rpath_relative_to_output panic when lib only contains file name --- compiler/rustc_codegen_ssa/src/back/rpath.rs | 5 +++++ .../rustc_codegen_ssa/src/back/rpath/tests.rs | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/back/rpath.rs b/compiler/rustc_codegen_ssa/src/back/rpath.rs index 3114f1c38ae7..f499bbcf8533 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath.rs @@ -85,6 +85,11 @@ fn get_rpath_relative_to_output(config: &RPathConfig<'_>, lib: &Path) -> OsStrin // Strip filenames let lib = lib.parent().unwrap(); let output = config.out_filename.parent().unwrap(); + + // If output or lib is empty, just assume it locates in current path + let lib = if lib == Path::new("") { Path::new(".") } else { lib }; + let output = if output == Path::new("") { Path::new(".") } else { output }; + let lib = try_canonicalize(lib).unwrap(); let output = try_canonicalize(output).unwrap(); let relative = path_relative_from(&lib, &output) diff --git a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs index ac2e54072c41..0de90a1036ec 100644 --- a/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs +++ b/compiler/rustc_codegen_ssa/src/back/rpath/tests.rs @@ -57,6 +57,22 @@ fn test_rpath_relative() { } } +#[test] +fn test_rpath_relative_issue_119571() { + let config = &mut RPathConfig { + libs: &[], + out_filename: PathBuf::from("rustc"), + has_rpath: true, + is_like_osx: false, + linker_is_gnu: true, + }; + // Should not panic when out_filename only contains filename. + // Issue 119571 + let _ = get_rpath_relative_to_output(config, Path::new("lib/libstd.so")); + // Should not panic when lib only contains filename. + let _ = get_rpath_relative_to_output(config, Path::new("libstd.so")); +} + #[test] fn test_xlinker() { let args = rpaths_to_flags(vec!["a/normal/path".into(), "a,comma,path".into()]); From c3de4b3aad6a2be86d4711086267e21660bf2b23 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sun, 2 Jun 2024 12:40:07 +0000 Subject: [PATCH 021/154] Handle all GVN binops in a single place. --- compiler/rustc_mir_transform/src/gvn.rs | 70 ++++++++++++++----------- 1 file changed, 40 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index fadb5edefdfb..548e4e309360 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -223,7 +223,6 @@ enum Value<'tcx> { NullaryOp(NullOp<'tcx>, Ty<'tcx>), UnaryOp(UnOp, VnIndex), BinaryOp(BinOp, VnIndex, VnIndex), - CheckedBinaryOp(BinOp, VnIndex, VnIndex), // FIXME get rid of this, work like MIR instead Cast { kind: CastKind, value: VnIndex, @@ -508,17 +507,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let val = self.ecx.binary_op(bin_op, &lhs, &rhs).ok()?; val.into() } - CheckedBinaryOp(bin_op, lhs, rhs) => { - let lhs = self.evaluated[lhs].as_ref()?; - let lhs = self.ecx.read_immediate(lhs).ok()?; - let rhs = self.evaluated[rhs].as_ref()?; - let rhs = self.ecx.read_immediate(rhs).ok()?; - let val = self - .ecx - .binary_op(bin_op.wrapping_to_overflowing().unwrap(), &lhs, &rhs) - .ok()?; - val.into() - } Cast { kind, value, from: _, to } => match kind { CastKind::IntToInt | CastKind::IntToFloat => { let value = self.evaluated[value].as_ref()?; @@ -829,17 +817,10 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { let lhs = lhs?; let rhs = rhs?; - if let Some(op) = op.overflowing_to_wrapping() { - if let Some(value) = self.simplify_binary(op, true, ty, lhs, rhs) { - return Some(value); - } - Value::CheckedBinaryOp(op, lhs, rhs) - } else { - if let Some(value) = self.simplify_binary(op, false, ty, lhs, rhs) { - return Some(value); - } - Value::BinaryOp(op, lhs, rhs) + if let Some(value) = self.simplify_binary(op, ty, lhs, rhs) { + return Some(value); } + Value::BinaryOp(op, lhs, rhs) } Rvalue::UnaryOp(op, ref mut arg) => { let arg = self.simplify_operand(arg, location)?; @@ -970,7 +951,6 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { fn simplify_binary( &mut self, op: BinOp, - checked: bool, lhs_ty: Ty<'tcx>, lhs: VnIndex, rhs: VnIndex, @@ -999,22 +979,39 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { use Either::{Left, Right}; let a = as_bits(lhs).map_or(Right(lhs), Left); let b = as_bits(rhs).map_or(Right(rhs), Left); + let result = match (op, a, b) { // Neutral elements. - (BinOp::Add | BinOp::BitOr | BinOp::BitXor, Left(0), Right(p)) + ( + BinOp::Add + | BinOp::AddWithOverflow + | BinOp::AddUnchecked + | BinOp::BitOr + | BinOp::BitXor, + Left(0), + Right(p), + ) | ( BinOp::Add + | BinOp::AddWithOverflow + | BinOp::AddUnchecked | BinOp::BitOr | BinOp::BitXor | BinOp::Sub + | BinOp::SubWithOverflow + | BinOp::SubUnchecked | BinOp::Offset | BinOp::Shl | BinOp::Shr, Right(p), Left(0), ) - | (BinOp::Mul, Left(1), Right(p)) - | (BinOp::Mul | BinOp::Div, Right(p), Left(1)) => p, + | (BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked, Left(1), Right(p)) + | ( + BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::Div, + Right(p), + Left(1), + ) => p, // Attempt to simplify `x & ALL_ONES` to `x`, with `ALL_ONES` depending on type size. (BinOp::BitAnd, Right(p), Left(ones)) | (BinOp::BitAnd, Left(ones), Right(p)) if ones == layout.size.truncate(u128::MAX) @@ -1023,10 +1020,21 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { p } // Absorbing elements. - (BinOp::Mul | BinOp::BitAnd, _, Left(0)) + ( + BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked | BinOp::BitAnd, + _, + Left(0), + ) | (BinOp::Rem, _, Left(1)) | ( - BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl | BinOp::Shr, + BinOp::Mul + | BinOp::MulWithOverflow + | BinOp::MulUnchecked + | BinOp::Div + | BinOp::Rem + | BinOp::BitAnd + | BinOp::Shl + | BinOp::Shr, Left(0), _, ) => self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty), @@ -1038,7 +1046,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { self.insert_scalar(Scalar::from_uint(ones, layout.size), lhs_ty) } // Sub/Xor with itself. - (BinOp::Sub | BinOp::BitXor, a, b) if a == b => { + (BinOp::Sub | BinOp::SubWithOverflow | BinOp::SubUnchecked | BinOp::BitXor, a, b) + if a == b => + { self.insert_scalar(Scalar::from_uint(0u128, layout.size), lhs_ty) } // Comparison: @@ -1052,7 +1062,7 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { _ => return None, }; - if checked { + if op.is_overflowing() { let false_val = self.insert_bool(false); Some(self.insert_tuple(vec![result, false_val])) } else { From 8530285f4ef240bf748cb207fa7d1794dca2e68f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 3 Jun 2024 01:01:18 +0300 Subject: [PATCH 022/154] rustc_span: Inline some hot functions --- compiler/rustc_span/src/span_encoding.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index 788a52faf568..6a0282266316 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -216,6 +216,7 @@ impl Span { // Returns either syntactic context, if it can be retrieved without taking the interner lock, // or an index into the interner if it cannot. + #[inline] fn inline_ctxt(self) -> Result { Ok(if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER { if self.len_with_tag_or_marker & PARENT_TAG == 0 { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 61ca0d54ca49..fe883e03c44c 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2213,6 +2213,7 @@ impl fmt::Display for IdentPrinter { pub struct MacroRulesNormalizedIdent(Ident); impl MacroRulesNormalizedIdent { + #[inline] pub fn new(ident: Ident) -> Self { Self(ident.normalize_to_macro_rules()) } From 92f85f12a82ac23b794dcdd58a76b0ae7519951c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 3 Jun 2024 06:58:30 +0300 Subject: [PATCH 023/154] wipe bootstrap build before switching to bumped rustc Technically, wiping bootstrap builds can increase the build time. But in practice, trying to manually resolve post-bump issues and even accidentally removing the entire build directory will result in a much greater loss of time. After all, the bootstrap build process is not a particularly lengthy operation. Signed-off-by: onur-ozkan --- src/bootstrap/bootstrap.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index e60e8f0aa1f7..9861121aac0a 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -599,6 +599,12 @@ class RustBuild(object): print('Choosing a pool size of', pool_size, 'for the unpacking of the tarballs') p = Pool(pool_size) try: + # FIXME: A cheap workaround for https://github.com/rust-lang/rust/issues/125578, + # remove this once the issue is closed. + bootstrap_out = self.bootstrap_out() + if os.path.exists(bootstrap_out): + shutil.rmtree(bootstrap_out) + p.map(unpack_component, tarballs_download_info) finally: p.close() @@ -864,6 +870,16 @@ class RustBuild(object): return line[start + 1:end] return None + def bootstrap_out(self): + """Return the path of the bootstrap build artifacts + + >>> rb = RustBuild() + >>> rb.build_dir = "build" + >>> rb.bootstrap_binary() == os.path.join("build", "bootstrap") + True + """ + return os.path.join(self.build_dir, "bootstrap") + def bootstrap_binary(self): """Return the path of the bootstrap binary @@ -873,7 +889,7 @@ class RustBuild(object): ... "debug", "bootstrap") True """ - return os.path.join(self.build_dir, "bootstrap", "debug", "bootstrap") + return os.path.join(self.bootstrap_out(), "debug", "bootstrap") def build_bootstrap(self): """Build bootstrap""" From 940594ff1842026cf16efb0af5210de6966fbfdb Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 27 May 2024 10:03:54 -0700 Subject: [PATCH 024/154] Explain LazyCell in core::cell overview --- library/core/src/cell.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index ac026de95da1..6cdc1e00f479 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -82,6 +82,20 @@ //! //! The corresponding [`Sync`] version of `OnceCell` is [`OnceLock`]. //! +//! ## `LazyCell` +//! +//! A common pattern with OnceCell is, for a given OnceCell, to use the same function on every +//! call to [`OnceCell::get_or_init`] with that cell. This is what is offered by [`LazyCell`], +//! which pairs cells of `T` with functions of `F`, and always calls `F` before it yields `&T`. +//! This happens implicitly by simply attempting to dereference the LazyCell to get its contents, +//! so its use is much more transparent with a place which has been initialized by a constant. +//! +//! More complicated patterns that don't fit this description can be built on `OnceCell` instead. +//! +//! `LazyCell` works by providing an implementation of `impl Deref` that calls the function, +//! so you can just use it by dereference (e.g. `*lazy_cell` or `lazy_cell.deref()`). +//! +//! The corresponding [`Sync`] version of `LazyCell` is [`LazyLock`]. //! //! # When to choose interior mutability //! @@ -230,6 +244,7 @@ //! [`RwLock`]: ../../std/sync/struct.RwLock.html //! [`Mutex`]: ../../std/sync/struct.Mutex.html //! [`OnceLock`]: ../../std/sync/struct.OnceLock.html +//! [`LazyLock`]: ../../std/sync/struct.LazyLock.html //! [`Sync`]: ../../std/marker/trait.Sync.html //! [`atomic`]: crate::sync::atomic From fdb96f2123a8306e24f6ef0c77296bf0d2f9af99 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 27 May 2024 10:24:28 -0700 Subject: [PATCH 025/154] Differ LazyLock vs. OnceLock in std::sync overview --- library/std/src/sync/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index fb7d601b0947..70e8f5f90c61 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -136,7 +136,10 @@ //! - [`Once`]: Used for a thread-safe, one-time global initialization routine //! //! - [`OnceLock`]: Used for thread-safe, one-time initialization of a -//! global variable. +//! variable, with potentially different initializers based on the caller. +//! +//! - [`LazyLock`]: Used for thread-safe, one-time initialization of a +//! variable, using one nullary initializer function provided at creation. //! //! - [`RwLock`]: Provides a mutual exclusion mechanism which allows //! multiple readers at the same time, while allowing only one From 2d0ebca9798f76ff5ff1ef171cdf73fb5c8d7127 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 27 May 2024 13:02:39 -0700 Subject: [PATCH 026/154] Move first OnceLock example to LazyLock This example is spiritually an example of LazyLock, as it computes a variable at runtime but accepts no inputs into that process. It is also slightly simpler and thus easier to understand. Change it to an even-more concise version and move it to LazyLock. The example now editorializes slightly more. This may be unnecessary, but it can be educational for the reader. --- library/std/src/sync/lazy_lock.rs | 36 ++++++++++++------------------- library/std/src/sync/once_lock.rs | 36 ------------------------------- 2 files changed, 14 insertions(+), 58 deletions(-) diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index d3bb3bfdff92..7a2eed93dd4f 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -29,34 +29,26 @@ union Data { /// # Examples /// /// Initialize static variables with `LazyLock`. -/// /// ``` -/// use std::collections::HashMap; -/// /// use std::sync::LazyLock; /// -/// static HASHMAP: LazyLock> = LazyLock::new(|| { -/// println!("initializing"); -/// let mut m = HashMap::new(); -/// m.insert(13, "Spica".to_string()); -/// m.insert(74, "Hoyten".to_string()); -/// m +/// // n.b. static items do not call [`Drop`] on program termination, so this won't be deallocated. +/// // this is fine, as the OS can deallocate the terminated program faster than we can free memory +/// // but tools like valgrind might report "memory leaks" as it isn't obvious this is intentional. +/// static DEEP_THOUGHT: LazyLock = LazyLock::new(|| { +/// # mod another_crate { +/// # pub fn great_question() -> String { "42".to_string() } +/// # } +/// // M3 Ultra takes about 16 million years in --release config +/// another_crate::great_question() /// }); /// -/// fn main() { -/// println!("ready"); -/// std::thread::spawn(|| { -/// println!("{:?}", HASHMAP.get(&13)); -/// }).join().unwrap(); -/// println!("{:?}", HASHMAP.get(&74)); -/// -/// // Prints: -/// // ready -/// // initializing -/// // Some("Spica") -/// // Some("Hoyten") -/// } +/// // The `String` is built, stored in the `LazyLock`, and returned as `&String`. +/// let _ = &*DEEP_THOUGHT; +/// // The `String` is retrieved from the `LazyLock` and returned as `&String`. +/// let _ = &*DEEP_THOUGHT; /// ``` +/// /// Initialize fields with `LazyLock`. /// ``` /// use std::sync::LazyLock; diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index fc830baccedd..d52f610c1f45 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -13,42 +13,6 @@ use crate::sync::Once; /// /// # Examples /// -/// Using `OnceLock` to store a function’s previously computed value (a.k.a. -/// ‘lazy static’ or ‘memoizing’): -/// -/// ``` -/// use std::sync::OnceLock; -/// -/// struct DeepThought { -/// answer: String, -/// } -/// -/// impl DeepThought { -/// # fn great_question() -> String { -/// # "42".to_string() -/// # } -/// # -/// fn new() -> Self { -/// Self { -/// // M3 Ultra takes about 16 million years in --release config -/// answer: Self::great_question(), -/// } -/// } -/// } -/// -/// fn computation() -> &'static DeepThought { -/// // n.b. static items do not call [`Drop`] on program termination, so if -/// // [`DeepThought`] impls Drop, that will not be used for this instance. -/// static COMPUTATION: OnceLock = OnceLock::new(); -/// COMPUTATION.get_or_init(|| DeepThought::new()) -/// } -/// -/// // The `DeepThought` is built, stored in the `OnceLock`, and returned. -/// let _ = computation().answer; -/// // The `DeepThought` is retrieved from the `OnceLock` and returned. -/// let _ = computation().answer; -/// ``` -/// /// Writing to a `OnceLock` from a separate thread: /// /// ``` From 9ed7cfc952b06fb4e552fb02bbd65070e56cfdc0 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 27 May 2024 13:21:38 -0700 Subject: [PATCH 027/154] Add "OnceList" example to motivate OnceLock While slightly verbose, it helps explain "why bother with OnceLock?" This is a point of confusion that has been raised multiple times shortly before and after the stabilization of LazyLock. --- library/std/src/sync/once_lock.rs | 55 +++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index d52f610c1f45..22083bc29333 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -8,8 +8,14 @@ use crate::sync::Once; /// A synchronization primitive which can be written to only once. /// /// This type is a thread-safe [`OnceCell`], and can be used in statics. +/// In many simple cases, you can use [`LazyLock`] instead to get the benefits of this type +/// with less effort: `LazyLock` "looks like" `&T` because it initializes with `F` on deref! +/// Where OnceLock shines is when LazyLock is too simple to support a given case, as LazyLock +/// doesn't allow additional inputs to its function after you call [`LazyLock::new(|| ...)`]. /// /// [`OnceCell`]: crate::cell::OnceCell +/// [`LazyLock`]: crate::sync::LazyLock +/// [`LazyLock::new(|| ...)`]: crate::sync::LazyLock::new /// /// # Examples /// @@ -37,6 +43,55 @@ use crate::sync::Once; /// Some(&12345), /// ); /// ``` +/// +/// You can use `OnceLock` to implement a type that requires "append-only" logic: +/// +/// ``` +/// use std::sync::{OnceLock, atomic::{AtomicU32, Ordering}}; +/// use std::thread; +/// +/// struct OnceList { +/// data: OnceLock, +/// next: OnceLock>>, +/// } +/// impl OnceList { +/// const fn new() -> OnceList { +/// OnceList { data: OnceLock::new(), next: OnceLock::new() } +/// } +/// fn push(&self, value: T) { +/// // FIXME: this impl is concise, but is also slow for long lists or many threads. +/// // as an exercise, consider how you might improve on it while preserving the behavior +/// if let Err(value) = self.data.set(value) { +/// let next = self.next.get_or_init(|| Box::new(OnceList::new())); +/// next.push(value) +/// }; +/// } +/// fn contains(&self, example: &T) -> bool +/// where +/// T: PartialEq, +/// { +/// self.data.get().map(|item| item == example).filter(|v| *v).unwrap_or_else(|| { +/// self.next.get().map(|next| next.contains(example)).unwrap_or(false) +/// }) +/// } +/// } +/// +/// // Let's exercise this new Sync append-only list by doing a little counting +/// static LIST: OnceList = OnceList::new(); +/// static COUNTER: AtomicU32 = AtomicU32::new(0); +/// +/// let vec = (0..thread::available_parallelism().unwrap().get()).map(|_| thread::spawn(|| { +/// while let i @ 0..=1000 = COUNTER.fetch_add(1, Ordering::Relaxed) { +/// LIST.push(i); +/// } +/// })).collect::>>(); +/// vec.into_iter().for_each(|handle| handle.join().unwrap()); +/// +/// for i in 0..=1000 { +/// assert!(LIST.contains(&i)); +/// } +/// +/// ``` #[stable(feature = "once_cell", since = "1.70.0")] pub struct OnceLock { once: Once, From 9d1ec7ea069ab3897e715464be8b6d93e529020a Mon Sep 17 00:00:00 2001 From: dalance Date: Sun, 5 May 2024 09:01:47 +0900 Subject: [PATCH 028/154] Add translation support by mdbook-i18n-helpers to bootstrap --- Cargo.lock | 148 +++++++++++++++++++++- src/bootstrap/src/core/build_steps/doc.rs | 40 ++++-- src/tools/rustbook/Cargo.toml | 1 + src/tools/rustbook/src/main.rs | 13 ++ 4 files changed, 186 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1018eac13ff1..0e950e288072 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -372,7 +372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6798148dccfbff0fae41c7574d2fa8f1ef3492fba0face179de5d8d447d67b05" dependencies = [ "memchr", - "regex-automata 0.3.9", + "regex-automata 0.3.7", "serde", ] @@ -2206,6 +2206,21 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "line-wrap" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" + +[[package]] +name = "linereader" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d921fea6860357575519aca014c6e22470585accdd543b370c404a8a72d0dd1d" +dependencies = [ + "memchr", +] + [[package]] name = "linkchecker" version = "0.1.0" @@ -2214,6 +2229,12 @@ dependencies = [ "regex", ] +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "lint-docs" version = "0.1.0" @@ -2364,6 +2385,25 @@ dependencies = [ "topological-sort", ] +[[package]] +name = "mdbook-i18n-helpers" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f71f5961d6f3376e1ff3e5989c2e3ecccc3e8a00f3a3acde446847f84852e4" +dependencies = [ + "anyhow", + "chrono", + "mdbook", + "polib", + "pulldown-cmark 0.10.3", + "pulldown-cmark-to-cmark", + "regex", + "semver", + "serde_json", + "syntect", + "textwrap", +] + [[package]] name = "mdbook-trpl-listing" version = "0.1.0" @@ -2650,6 +2690,28 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "onig" +version = "6.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f" +dependencies = [ + "bitflags 1.3.2", + "libc", + "once_cell", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "opener" version = "0.6.1" @@ -2968,6 +3030,29 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "plist" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9" +dependencies = [ + "base64", + "indexmap", + "line-wrap", + "quick-xml", + "serde", + "time", +] + +[[package]] +name = "polib" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b393b155cf9be86249cba1b56cc81be0e6212c66d94ac0d76d37a1761f3bb1b" +dependencies = [ + "linereader", +] + [[package]] name = "polonius-engine" version = "0.13.0" @@ -3126,6 +3211,15 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9e1dcb320d6839f6edb64f7a4a59d39b30480d4d1765b56873f7c858538a5fe" +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", +] + [[package]] name = "quine-mc_cluskey" version = "0.2.4" @@ -3261,12 +3355,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" dependencies = [ "aho-corasick", "memchr", + "regex-automata 0.3.7", "regex-syntax 0.7.5", ] @@ -3290,9 +3385,14 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.5", +] [[package]] name = "regex-lite" @@ -3367,6 +3467,7 @@ dependencies = [ "clap", "env_logger", "mdbook", + "mdbook-i18n-helpers", "mdbook-trpl-listing", "mdbook-trpl-note", ] @@ -5372,6 +5473,28 @@ dependencies = [ "syn 2.0.64", ] +[[package]] +name = "syntect" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1" +dependencies = [ + "bincode", + "bitflags 1.3.2", + "flate2", + "fnv", + "once_cell", + "onig", + "plist", + "regex-syntax 0.8.3", + "serde", + "serde_derive", + "serde_json", + "thiserror", + "walkdir", + "yaml-rust", +] + [[package]] name = "sysinfo" version = "0.30.12" @@ -5497,6 +5620,12 @@ dependencies = [ "std", ] +[[package]] +name = "textwrap" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" + [[package]] name = "thin-vec" version = "0.2.13" @@ -6476,6 +6605,15 @@ dependencies = [ "lzma-sys", ] +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "yansi-term" version = "0.1.2" diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 30b3edfd3aed..b37b2b5bcefb 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -29,7 +29,7 @@ macro_rules! submodule_helper { } macro_rules! book { - ($($name:ident, $path:expr, $book_name:expr $(, submodule $(= $submodule:literal)? )? ;)+) => { + ($($name:ident, $path:expr, $book_name:expr, $lang:expr $(, submodule $(= $submodule:literal)? )? ;)+) => { $( #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct $name { @@ -61,6 +61,7 @@ macro_rules! book { name: $book_name.to_owned(), src: builder.src.join($path), parent: Some(self), + languages: $lang.into(), }) } } @@ -74,15 +75,15 @@ macro_rules! book { // FIXME: Make checking for a submodule automatic somehow (maybe by having a list of all submodules // and checking against it?). book!( - CargoBook, "src/tools/cargo/src/doc", "cargo", submodule = "src/tools/cargo"; - ClippyBook, "src/tools/clippy/book", "clippy"; - EditionGuide, "src/doc/edition-guide", "edition-guide", submodule; - EmbeddedBook, "src/doc/embedded-book", "embedded-book", submodule; - Nomicon, "src/doc/nomicon", "nomicon", submodule; - Reference, "src/doc/reference", "reference", submodule; - RustByExample, "src/doc/rust-by-example", "rust-by-example", submodule; - RustdocBook, "src/doc/rustdoc", "rustdoc"; - StyleGuide, "src/doc/style-guide", "style-guide"; + CargoBook, "src/tools/cargo/src/doc", "cargo", &[], submodule = "src/tools/cargo"; + ClippyBook, "src/tools/clippy/book", "clippy", &[]; + EditionGuide, "src/doc/edition-guide", "edition-guide", &[], submodule; + EmbeddedBook, "src/doc/embedded-book", "embedded-book", &[], submodule; + Nomicon, "src/doc/nomicon", "nomicon", &[], submodule; + Reference, "src/doc/reference", "reference", &[], submodule; + RustByExample, "src/doc/rust-by-example", "rust-by-example", &["ja"], submodule; + RustdocBook, "src/doc/rustdoc", "rustdoc", &[]; + StyleGuide, "src/doc/style-guide", "style-guide", &[]; ); #[derive(Debug, Clone, Hash, PartialEq, Eq)] @@ -110,6 +111,7 @@ impl Step for UnstableBook { name: "unstable-book".to_owned(), src: builder.md_doc_out(self.target).join("unstable-book"), parent: Some(self), + languages: vec![], }) } } @@ -120,6 +122,7 @@ struct RustbookSrc { name: String, src: PathBuf, parent: Option

, + languages: Vec<&'static str>, } impl Step for RustbookSrc

{ @@ -151,7 +154,19 @@ impl Step for RustbookSrc

{ builder.info(&format!("Rustbook ({target}) - {name}")); let _ = fs::remove_dir_all(&out); - builder.run(rustbook_cmd.arg("build").arg(src).arg("-d").arg(out)); + builder.run(rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out)); + + for lang in &self.languages { + let out = out.join(lang); + + builder.info(&format!("Rustbook ({target}) - {name} - {lang}")); + let _ = fs::remove_dir_all(&out); + + let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); + builder.run( + rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out).arg("-l").arg(lang), + ); + } } if self.parent.is_some() { @@ -214,6 +229,7 @@ impl Step for TheBook { name: "book".to_owned(), src: absolute_path.clone(), parent: Some(self), + languages: vec![], }); // building older edition redirects @@ -225,6 +241,7 @@ impl Step for TheBook { // There should only be one book that is marked as the parent for each target, so // treat the other editions as not having a parent. parent: Option::::None, + languages: vec![], }); } @@ -1208,6 +1225,7 @@ impl Step for RustcBook { name: "rustc".to_owned(), src: out_base, parent: Some(self), + languages: vec![], }); } } diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 2b0dd0062b90..95f1a5d6e1d3 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -9,6 +9,7 @@ clap = "4.0.32" env_logger = "0.11" mdbook-trpl-listing = { path = "../../doc/book/packages/mdbook-trpl-listing" } mdbook-trpl-note = { path = "../../doc/book/packages/mdbook-trpl-note" } +mdbook-i18n-helpers = "0.3.3" [dependencies.mdbook] version = "0.4.37" diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 9a06754e4a66..31bba56addeb 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -7,6 +7,7 @@ use clap::{arg, ArgMatches, Command}; use mdbook::errors::Result as Result3; use mdbook::MDBook; +use mdbook_i18n_helpers::preprocessors::Gettext; use mdbook_trpl_listing::TrplListing; use mdbook_trpl_note::TrplNote; @@ -19,6 +20,11 @@ fn main() { .required(false) .value_parser(clap::value_parser!(PathBuf)); + let l_arg = arg!(-l --"lang" +"The output language") + .required(false) + .value_parser(clap::value_parser!(String)); + let dir_arg = arg!([dir] "Root directory for the book\n\ (Defaults to the current directory when omitted)") .value_parser(clap::value_parser!(PathBuf)); @@ -33,6 +39,7 @@ fn main() { Command::new("build") .about("Build the book from the markdown files") .arg(d_arg) + .arg(l_arg) .arg(&dir_arg), ) .subcommand( @@ -63,6 +70,12 @@ pub fn build(args: &ArgMatches) -> Result3<()> { let book_dir = get_book_dir(args); let mut book = load_book(&book_dir)?; + if let Some(lang) = args.get_one::("lang") { + let gettext = Gettext; + book.with_preprocessor(gettext); + book.config.set("book.language", lang).unwrap(); + } + // Set this to allow us to catch bugs in advance. book.config.build.create_missing = false; From 07dc3ebf5c82f1f1420f37d68204600b87522383 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 3 Jun 2024 10:45:16 +0000 Subject: [PATCH 029/154] Allow static mut definitions with #[linkage] Unlike static declarations with #[linkage], for definitions rustc doesn't rewrite it to add an extra indirection. --- .../rustc_codegen_ssa/src/codegen_attrs.rs | 25 ++++++++++--------- .../linkage-attr-mutable-static.rs | 15 ++++++++--- .../linkage-attr-mutable-static.stderr | 10 ++++---- 3 files changed, 30 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 5d7257b15c42..15955170e873 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -324,21 +324,22 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { let linkage = Some(linkage_by_name(tcx, did, val.as_str())); if tcx.is_foreign_item(did) { codegen_fn_attrs.import_linkage = linkage; + + if tcx.is_mutable_static(did.into()) { + let mut diag = tcx.dcx().struct_span_err( + attr.span, + "extern mutable statics are not allowed with `#[linkage]`", + ); + diag.note( + "marking the extern static mutable would allow changing which symbol \ + the static references rather than make the target of the symbol \ + mutable", + ); + diag.emit(); + } } else { codegen_fn_attrs.linkage = linkage; } - if tcx.is_mutable_static(did.into()) { - let mut diag = tcx.dcx().struct_span_err( - attr.span, - "mutable statics are not allowed with `#[linkage]`", - ); - diag.note( - "making the static mutable would allow changing which symbol the \ - static references rather than make the target of the symbol \ - mutable", - ); - diag.emit(); - } } } sym::link_section => { diff --git a/tests/ui/linkage-attr/linkage-attr-mutable-static.rs b/tests/ui/linkage-attr/linkage-attr-mutable-static.rs index a7109c6d930b..ed11947f59e7 100644 --- a/tests/ui/linkage-attr/linkage-attr-mutable-static.rs +++ b/tests/ui/linkage-attr/linkage-attr-mutable-static.rs @@ -4,12 +4,21 @@ #![feature(linkage)] fn main() { + #[rustfmt::skip] extern "C" { - #[linkage = "weak"] //~ ERROR mutable statics are not allowed with `#[linkage]` - static mut ABC: *const u8; + #[linkage = "extern_weak"] //~ ERROR extern mutable statics are not allowed with `#[linkage]` + static mut EXTERN_WEAK: *const u8; } unsafe { - assert_eq!(ABC as usize, 0); + assert_eq!(EXTERN_WEAK as usize, 0); + } + + // static mut is fine here as this is a definition rather than declaration. + #[linkage = "weak"] + static mut WEAK_DEF: u8 = 42; + + unsafe { + assert_eq!(WEAK_DEF, 0); } } diff --git a/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr b/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr index 4db41b623938..ad9997690475 100644 --- a/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr +++ b/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr @@ -1,10 +1,10 @@ -error: mutable statics are not allowed with `#[linkage]` - --> $DIR/linkage-attr-mutable-static.rs:8:9 +error: extern mutable statics are not allowed with `#[linkage]` + --> $DIR/linkage-attr-mutable-static.rs:9:9 | -LL | #[linkage = "weak"] - | ^^^^^^^^^^^^^^^^^^^ +LL | #[linkage = "extern_weak"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: making the static mutable would allow changing which symbol the static references rather than make the target of the symbol mutable + = note: marking the extern static mutable would allow changing which symbol the static references rather than make the target of the symbol mutable error: aborting due to 1 previous error From d392c50ca35d6d9a5e575467e3350ff798ab9930 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 3 Jun 2024 13:46:56 +0200 Subject: [PATCH 030/154] Ignore `vec_deque_alloc_error::test_shrink_to_unwind` test on non-unwind targets --- library/alloc/tests/vec_deque_alloc_error.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/alloc/tests/vec_deque_alloc_error.rs b/library/alloc/tests/vec_deque_alloc_error.rs index c11f4556da9a..8b516ddbc5c5 100644 --- a/library/alloc/tests/vec_deque_alloc_error.rs +++ b/library/alloc/tests/vec_deque_alloc_error.rs @@ -8,6 +8,7 @@ use std::{ }; #[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] fn test_shrink_to_unwind() { // This tests that `shrink_to` leaves the deque in a consistent state when // the call to `RawVec::shrink_to_fit` unwinds. The code is adapted from #123369 From e9c4eb3cd31cd373867369e78b2695f1f5a3c299 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 31 May 2024 09:30:41 -0400 Subject: [PATCH 031/154] chore: update src/tools/rustc-perf This is needed for fixing the missing license issue. See https://github.com/rust-lang/rust/pull/125465. --- src/tools/rustc-perf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf index cc81f9654dac..72daa50ce235 160000 --- a/src/tools/rustc-perf +++ b/src/tools/rustc-perf @@ -1 +1 @@ -Subproject commit cc81f9654dac3fe08de286907dba747538417afd +Subproject commit 72daa50ce2350f5a9b5ae6dc3ad6babccd14ec0a From 9436fbe00dd4def2efa6651de5f469f8d637fceb Mon Sep 17 00:00:00 2001 From: Tim Kurdov Date: Mon, 3 Jun 2024 17:35:58 +0100 Subject: [PATCH 032/154] Fix typo in the docs of `HashMap::raw_entry_mut` --- library/std/src/collections/hash/map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 5039f0b6bb28..fcd1c307b5af 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -1218,7 +1218,7 @@ where /// will cause the map to produce seemingly random results. Higher-level and /// more foolproof APIs like `entry` should be preferred when possible. /// - /// In particular, the hash used to initialized the raw entry must still be + /// In particular, the hash used to initialize the raw entry must still be /// consistent with the hash of the key that is ultimately stored in the entry. /// This is because implementations of HashMap may need to recompute hashes /// when resizing, at which point only the keys are available. From 47053d1621502c66b58c465499627bc2ce60a436 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:00:52 -0400 Subject: [PATCH 033/154] Update books --- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustc-dev-guide | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/book b/src/doc/book index 85442a608426..5228bfac8267 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 85442a608426d3667f1c9458ad457b241a36b569 +Subproject commit 5228bfac8267ad24659a81b92ec5417976b5edbc diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 0c68e90acaae..bbaabbe088e2 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 0c68e90acaae5a611f8f5098a3c2980de9845ab2 +Subproject commit bbaabbe088e21a81a0d9ae6757705020d5d7b416 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index dd962bb82865..b10c6acaf0f4 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit dd962bb82865a5284f2404e5234f1e3222b9c022 +Subproject commit b10c6acaf0f43481f6600e95d4b5013446e29f7a diff --git a/src/doc/reference b/src/doc/reference index e356977fceaa..6019b76f5b28 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit e356977fceaa8591c762312d8d446769166d4b3e +Subproject commit 6019b76f5b28938565b251bbba0bf5cc5c43d863 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 20482893d1a5..4840dca06cad 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 20482893d1a502df72f76762c97aed88854cdf81 +Subproject commit 4840dca06cadf48b305d3ce0aeafde7f80933f80 diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index b6d4a4940bab..6a7374bd87cb 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit b6d4a4940bab85cc91eec70cc2e3096dd48da62d +Subproject commit 6a7374bd87cbac0f8be4fd4877d8186d9c313985 From 832b8b8688bebb413dd29cb22eb574d250853e65 Mon Sep 17 00:00:00 2001 From: Julia Ryan Date: Mon, 3 Jun 2024 10:27:10 -0700 Subject: [PATCH 034/154] Update fuchsia maintainers --- src/doc/rustc/src/platform-support/fuchsia.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md index 3e1db692f50b..5643c6a0188a 100644 --- a/src/doc/rustc/src/platform-support/fuchsia.md +++ b/src/doc/rustc/src/platform-support/fuchsia.md @@ -10,9 +10,9 @@ updatable, and performant. The [Fuchsia team]: - Tyler Mandry ([@tmandry](https://github.com/tmandry)) -- Dan Johnson ([@computerdruid](https://github.com/computerdruid)) - David Koloski ([@djkoloski](https://github.com/djkoloski)) -- Joseph Ryan ([@P1n3appl3](https://github.com/P1n3appl3)) +- Julia Ryan ([@P1n3appl3](https://github.com/P1n3appl3)) +- Erick Tryzelaar ([@erickt](https://github.com/erickt)) As the team evolves over time, the specific members listed here may differ from the members reported by the API. The API should be considered to be From 0a11dcfdf4bd108579093dbe5ecb74481b273035 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Mon, 3 Jun 2024 11:41:31 -0400 Subject: [PATCH 035/154] feat(opt-dist): new flag `--benchmark-cargo-config` The flag propagates cargo configs to `rustc-perf --cargo-config`, which is particularly useful when the environment is air-gapped, and you want to use the default set of training crates vendored in the rustc-src tarball. --- src/tools/opt-dist/src/environment.rs | 7 +++++++ src/tools/opt-dist/src/main.rs | 6 ++++++ src/tools/opt-dist/src/training.rs | 14 ++++++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/tools/opt-dist/src/environment.rs b/src/tools/opt-dist/src/environment.rs index ff782a1687e2..bc01b7fb8a37 100644 --- a/src/tools/opt-dist/src/environment.rs +++ b/src/tools/opt-dist/src/environment.rs @@ -17,6 +17,9 @@ pub struct Environment { host_llvm_dir: Utf8PathBuf, /// List of test paths that should be skipped when testing the optimized artifacts. skipped_tests: Vec, + /// Arguments passed to `rustc-perf --cargo-config ` when running benchmarks. + #[builder(default)] + benchmark_cargo_config: Vec, /// Directory containing a pre-built rustc-perf checkout. #[builder(default)] prebuilt_rustc_perf: Option, @@ -94,6 +97,10 @@ impl Environment { pub fn skipped_tests(&self) -> &[String] { &self.skipped_tests } + + pub fn benchmark_cargo_config(&self) -> &[String] { + &self.benchmark_cargo_config + } } /// What is the extension of binary executables on this platform? diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index a709076f2458..e4271a6e2dd9 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -90,6 +90,10 @@ enum EnvironmentCmd { #[clap(flatten)] shared: SharedArgs, + + /// Arguments passed to `rustc-perf --cargo-config ` when running benchmarks. + #[arg(long)] + benchmark_cargo_config: Vec, }, /// Perform an optimized build on Linux CI, from inside Docker. LinuxCi { @@ -119,6 +123,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> llvm_shared, use_bolt, skipped_tests, + benchmark_cargo_config, shared, } => { let env = EnvironmentBuilder::default() @@ -132,6 +137,7 @@ fn create_environment(args: Args) -> anyhow::Result<(Environment, Vec)> .shared_llvm(llvm_shared) .use_bolt(use_bolt) .skipped_tests(skipped_tests) + .benchmark_cargo_config(benchmark_cargo_config) .build()?; (env, shared.build_args) diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index 46040e32a039..09263dc645e2 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -36,7 +36,7 @@ fn init_compiler_benchmarks( // Run rustc-perf benchmarks // Benchmark using profile_local with eprintln, which essentially just means // don't actually benchmark -- just make sure we run rustc a bunch of times. - cmd(&[ + let mut cmd = cmd(&[ env.cargo_stage_0().as_str(), "run", "-p", @@ -61,7 +61,17 @@ fn init_compiler_benchmarks( .env("RUST_LOG", "collector=debug") .env("RUSTC", env.rustc_stage_0().as_str()) .env("RUSTC_BOOTSTRAP", "1") - .workdir(&env.rustc_perf_dir()) + .workdir(&env.rustc_perf_dir()); + + // This propagates cargo configs to `rustc-perf --cargo-config`, + // which is particularly useful when the environment is air-gapped, + // and you want to use the default set of training crates vendored + // in the rustc-src tarball. + for config in env.benchmark_cargo_config() { + cmd = cmd.arg("--cargo-config").arg(config); + } + + cmd } /// Describes which `llvm-profdata` binary should be used for merging PGO profiles. From 8f0862544327d5419a158c9483ed905d3fb55bf2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 2 Jun 2024 21:19:11 -0400 Subject: [PATCH 036/154] Remove a bunch of redundant args from report_method_error --- compiler/rustc_hir_typeck/src/expr.rs | 31 +++++----- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 10 +--- compiler/rustc_hir_typeck/src/method/mod.rs | 1 - .../rustc_hir_typeck/src/method/suggest.rs | 58 ++++++++++++------- compiler/rustc_hir_typeck/src/pat.rs | 8 +-- tests/ui/issues/issue-28344.stderr | 2 +- tests/ui/resolve/issue-82865.stderr | 7 --- tests/ui/traits/item-privacy.stderr | 9 +-- 8 files changed, 64 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 3d88c4255245..386f4c3af688 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -13,7 +13,6 @@ use crate::errors::{ YieldExprOutsideOfCoroutine, }; use crate::fatally_break_rust; -use crate::method::SelfSource; use crate::type_error_struct; use crate::CoroutineTypes; use crate::Expectation::{self, ExpectCastableToType, ExpectHasType, NoExpectation}; @@ -507,7 +506,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let (res, opt_ty, segs) = - self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span, Some(args)); + self.resolve_ty_and_res_fully_qualified_call(qpath, expr.hir_id, expr.span); let ty = match res { Res::Err => { self.suggest_assoc_method_call(segs); @@ -1331,9 +1330,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let rcvr_t = self.check_expr(rcvr); // no need to check for bot/err -- callee does that let rcvr_t = self.structurally_resolve_type(rcvr.span, rcvr_t); - let span = segment.ident.span; - let method = match self.lookup_method(rcvr_t, segment, span, expr, rcvr, args) { + let method = match self.lookup_method(rcvr_t, segment, segment.ident.span, expr, rcvr, args) + { Ok(method) => { // We could add a "consider `foo::`" suggestion here, but I wasn't able to // trigger this codepath causing `structurally_resolve_type` to emit an error. @@ -1342,18 +1341,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Err(error) => { if segment.ident.name != kw::Empty { - if let Some(err) = self.report_method_error( - span, - Some(rcvr), - rcvr_t, - segment.ident, - expr.hir_id, - SelfSource::MethodCall(rcvr), - error, - Some(args), - expected, - false, - ) { + if let Some(err) = + self.report_method_error(expr.hir_id, rcvr_t, error, expected, false) + { err.emit(); } } @@ -1362,7 +1352,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; // Call the generic checker. - self.check_method_argument_types(span, expr, method, args, DontTupleArguments, expected) + self.check_method_argument_types( + segment.ident.span, + expr, + method, + args, + DontTupleArguments, + expected, + ) } fn check_expr_cast( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 0c10c67db8c3..3c36eab18cff 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1,6 +1,6 @@ use crate::callee::{self, DeferredCallResolution}; use crate::errors::{self, CtorIsPrivate}; -use crate::method::{self, MethodCallee, SelfSource}; +use crate::method::{self, MethodCallee}; use crate::rvalue_scopes; use crate::{BreakableCtxt, Diverges, Expectation, FnCtxt, LoweredTy}; use rustc_data_structures::fx::FxHashSet; @@ -735,7 +735,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { qpath: &'tcx QPath<'tcx>, hir_id: HirId, span: Span, - args: Option<&'tcx [hir::Expr<'tcx>]>, ) -> (Res, Option>, &'tcx [hir::PathSegment<'tcx>]) { debug!( "resolve_ty_and_res_fully_qualified_call: qpath={:?} hir_id={:?} span={:?}", @@ -828,14 +827,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if item_name.name != kw::Empty { if let Some(e) = self.report_method_error( - span, - None, - ty.normalized, - item_name, hir_id, - SelfSource::QPath(qself), + ty.normalized, error, - args, Expectation::NoExpectation, trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021 ) { diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs index 4165ccb1b80a..1f90d5e4c88a 100644 --- a/compiler/rustc_hir_typeck/src/method/mod.rs +++ b/compiler/rustc_hir_typeck/src/method/mod.rs @@ -7,7 +7,6 @@ mod prelude_edition_lints; pub mod probe; mod suggest; -pub use self::suggest::SelfSource; pub use self::MethodError::*; use crate::FnCtxt; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index daaaf630f2c4..b3947e142b26 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -16,11 +16,11 @@ use rustc_data_structures::unord::UnordSet; use rustc_errors::{ codes::*, pluralize, struct_span_code_err, Applicability, Diag, MultiSpan, StashKey, }; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; use rustc_hir::PathSegment; +use rustc_hir::{self as hir, HirId}; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::{self, RegionVariableOrigin}; use rustc_middle::bug; @@ -187,37 +187,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { #[instrument(level = "debug", skip(self))] pub fn report_method_error( &self, - span: Span, - rcvr_opt: Option<&'tcx hir::Expr<'tcx>>, + call_id: HirId, rcvr_ty: Ty<'tcx>, - item_name: Ident, - expr_id: hir::HirId, - source: SelfSource<'tcx>, error: MethodError<'tcx>, - args: Option<&'tcx [hir::Expr<'tcx>]>, expected: Expectation<'tcx>, trait_missing_method: bool, ) -> Option> { + let (span, sugg_span, source, item_name, args) = match self.tcx.hir_node(call_id) { + hir::Node::Expr(&hir::Expr { + kind: hir::ExprKind::MethodCall(segment, rcvr, args, _), + span, + .. + }) => { + (segment.ident.span, span, SelfSource::MethodCall(rcvr), segment.ident, Some(args)) + } + hir::Node::Expr(&hir::Expr { + kind: hir::ExprKind::Path(QPath::TypeRelative(rcvr, segment)), + span, + .. + }) + | hir::Node::Pat(&hir::Pat { + kind: + hir::PatKind::Path(QPath::TypeRelative(rcvr, segment)) + | hir::PatKind::Struct(QPath::TypeRelative(rcvr, segment), ..) + | hir::PatKind::TupleStruct(QPath::TypeRelative(rcvr, segment), ..), + span, + .. + }) => { + let args = match self.tcx.parent_hir_node(call_id) { + hir::Node::Expr(&hir::Expr { + kind: hir::ExprKind::Call(callee, args), .. + }) if callee.hir_id == call_id => Some(args), + _ => None, + }; + (segment.ident.span, span, SelfSource::QPath(rcvr), segment.ident, args) + } + node => unreachable!("{node:?}"), + }; + // Avoid suggestions when we don't know what's going on. if rcvr_ty.references_error() { return None; } - let sugg_span = if let SelfSource::MethodCall(expr) = source { - // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing. - self.tcx.hir().expect_expr(self.tcx.parent_hir_id(expr.hir_id)).span - } else { - span - }; - match error { MethodError::NoMatch(mut no_match_data) => { return self.report_no_match_method_error( span, - rcvr_opt, rcvr_ty, item_name, - expr_id, + call_id, source, args, sugg_span, @@ -362,7 +381,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn suggest_use_shadowed_binding_with_method( &self, - rcvr_opt: Option<&'tcx hir::Expr<'tcx>>, + self_source: SelfSource<'tcx>, method_name: Ident, ty_str_reported: &str, err: &mut Diag<'_>, @@ -502,7 +521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if let Some(rcvr) = rcvr_opt + if let SelfSource::MethodCall(rcvr) = self_source && let hir::ExprKind::Path(QPath::Resolved(_, path)) = rcvr.kind && let hir::def::Res::Local(recv_id) = path.res && let Some(segment) = path.segments.first() @@ -548,7 +567,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn report_no_match_method_error( &self, mut span: Span, - rcvr_opt: Option<&'tcx hir::Expr<'tcx>>, rcvr_ty: Ty<'tcx>, item_name: Ident, expr_id: hir::HirId, @@ -658,7 +676,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if is_method { self.suggest_use_shadowed_binding_with_method( - rcvr_opt, + source, item_name, &ty_str_reported, &mut err, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index b37aba386196..93fb83fb3e4e 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -223,9 +223,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info; let path_res = match &pat.kind { - PatKind::Path(qpath) => Some( - self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None), - ), + PatKind::Path(qpath) => { + Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span)) + } _ => None, }; let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); @@ -1184,7 +1184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Resolve the path and check the definition for errors. let (res, opt_ty, segments) = - self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span, None); + self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span); if res == Res::Err { let e = tcx.dcx().span_delayed_bug(pat.span, "`Res::Err` but no error emitted"); self.set_tainted_by_errors(e); diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr index ddc1027c16b8..d30fb3cfe58a 100644 --- a/tests/ui/issues/issue-28344.stderr +++ b/tests/ui/issues/issue-28344.stderr @@ -52,7 +52,7 @@ error[E0599]: no function or associated item named `bitor` found for trait objec LL | let g = BitXor::bitor; | ^^^^^ function or associated item not found in `dyn BitXor<_>` | -help: there is a method `bitxor` with a similar name, but with different arguments +help: there is a method `bitxor` with a similar name --> $SRC_DIR/core/src/ops/bit.rs:LL:COL error: aborting due to 4 previous errors; 2 warnings emitted diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr index 9d0439d9d876..730fd6d60264 100644 --- a/tests/ui/resolve/issue-82865.stderr +++ b/tests/ui/resolve/issue-82865.stderr @@ -15,13 +15,6 @@ LL | Box::z LL | mac!(); | ------ in this macro invocation | -note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions: - Box::::new - Box::::new_uninit - Box::::new_zeroed - Box::::try_new - and 18 others - --> $SRC_DIR/alloc/src/boxed.rs:LL:COL = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index d08bb4745bf5..50b561dfd165 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -126,14 +126,15 @@ LL | S::B; | ^ associated item not found in `S` | = help: items from traits can only be used if the trait is in scope +help: there is a method `b` with a similar name + --> $DIR/item-privacy.rs:11:9 + | +LL | fn b(&self) { } + | ^^^^^^^^^^^ help: trait `B` which provides `B` is implemented but not in scope; perhaps you want to import it | LL + use assoc_const::B; | -help: there is a method `b` with a similar name - | -LL | S::b; - | ~ error[E0624]: associated constant `A` is private --> $DIR/item-privacy.rs:101:14 From e9957b922a8b81dc113e11c19a5ef93d1bdbdcf6 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 2 Jun 2024 21:34:21 -0400 Subject: [PATCH 037/154] Stop passing empty args to check_expr_path --- compiler/rustc_hir_typeck/src/expr.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 386f4c3af688..4cc936eed08c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -222,7 +222,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = ensure_sufficient_stack(|| match &expr.kind { hir::ExprKind::Path( qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)), - ) => self.check_expr_path(qpath, expr, args, call), + ) => self.check_expr_path(qpath, expr, Some(args), call), _ => self.check_expr_kind(expr, expected), }); let ty = self.resolve_vars_if_possible(ty); @@ -289,7 +289,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ExprKind::Path(QPath::LangItem(lang_item, _)) => { self.check_lang_item_path(lang_item, expr) } - ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, &[], None), + ExprKind::Path(ref qpath) => self.check_expr_path(qpath, expr, None, None), ExprKind::InlineAsm(asm) => { // We defer some asm checks as we may not have resolved the input and output types yet (they may still be infer vars). self.deferred_asm_checks.borrow_mut().push((asm, expr.hir_id)); @@ -501,7 +501,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, qpath: &'tcx hir::QPath<'tcx>, expr: &'tcx hir::Expr<'tcx>, - args: &'tcx [hir::Expr<'tcx>], + args: Option<&'tcx [hir::Expr<'tcx>]>, call: Option<&'tcx hir::Expr<'tcx>>, ) -> Ty<'tcx> { let tcx = self.tcx; @@ -563,7 +563,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We just want to check sizedness, so instead of introducing // placeholder lifetimes with probing, we just replace higher lifetimes // with fresh vars. - let span = args.get(i).map(|a| a.span).unwrap_or(expr.span); + let span = args.and_then(|args| args.get(i)).map_or(expr.span, |arg| arg.span); let input = self.instantiate_binder_with_fresh_vars( span, infer::BoundRegionConversionTime::FnCall, From b7a8f1f225db2fef723317a4bfb4cc649cc9ff84 Mon Sep 17 00:00:00 2001 From: Sergi-Ferrez Date: Tue, 4 Jun 2024 02:11:37 +0200 Subject: [PATCH 038/154] Include trailing commas in functions --- src/librustdoc/html/format.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index d20cef745ab0..de92fb80b938 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1431,20 +1431,16 @@ impl clean::FnDecl { cx: &Context<'_>, ) -> fmt::Result { let amp = if f.alternate() { "&" } else { "&" }; - + write!(f, "(")?; if let Some(n) = line_wrapping_indent && !self.inputs.values.is_empty() { write!(f, "\n{}", Indent(n + 4))?; } + + let last_input_index = self.inputs.values.len() - 1; for (i, input) in self.inputs.values.iter().enumerate() { - if i > 0 { - match line_wrapping_indent { - None => write!(f, ", ")?, - Some(n) => write!(f, ",\n{}", Indent(n + 4))?, - }; - } if let Some(selfty) = input.to_self() { match selfty { clean::SelfValue => { @@ -1477,18 +1473,24 @@ impl clean::FnDecl { write!(f, "{}: ", input.name)?; input.type_.print(cx).fmt(f)?; } + match line_wrapping_indent { + None if i == last_input_index => (), + None => write!(f, ", ")?, + Some(_n) if i == last_input_index => write!(f, ",\n")?, + Some(n) => write!(f, ",\n{}", Indent(n + 4))?, + } } if self.c_variadic { match line_wrapping_indent { - None => write!(f, ", ...")?, - Some(n) => write!(f, "\n{}...", Indent(n + 4))?, + None => write!(f, "...")?, + Some(n) => write!(f, "{}...\n", Indent(n + 4))?, }; } match line_wrapping_indent { None => write!(f, ")")?, - Some(n) => write!(f, "\n{})", Indent(n))?, + Some(n) => write!(f, "{})", Indent(n))?, }; self.print_output(cx).fmt(f) From e609c9b2541fe337872b26af849223ec37aed50d Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Jun 2024 16:57:17 +1000 Subject: [PATCH 039/154] Add unit tests for `Span::trim_start` --- compiler/rustc_span/src/tests.rs | 38 ++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/compiler/rustc_span/src/tests.rs b/compiler/rustc_span/src/tests.rs index cb88fa89058d..5c9dcc2a80fc 100644 --- a/compiler/rustc_span/src/tests.rs +++ b/compiler/rustc_span/src/tests.rs @@ -42,3 +42,41 @@ fn test_normalize_newlines() { check("\r\r\n", "\r\n", &[2]); check("hello\rworld", "hello\rworld", &[]); } + +#[test] +fn test_trim() { + let span = |lo: usize, hi: usize| { + Span::new(BytePos::from_usize(lo), BytePos::from_usize(hi), SyntaxContext::root(), None) + }; + + // Various positions, named for their relation to `start` and `end`. + let well_before = 1; + let before = 3; + let start = 5; + let mid = 7; + let end = 9; + let after = 11; + let well_after = 13; + + // The resulting span's context should be that of `self`, not `other`. + let other = span(start, end).with_ctxt(SyntaxContext::from_u32(999)); + + // Test cases for `trim_start`. + + assert_eq!(span(after, well_after).trim_start(other), Some(span(after, well_after))); + assert_eq!(span(end, well_after).trim_start(other), Some(span(end, well_after))); + assert_eq!(span(mid, well_after).trim_start(other), Some(span(end, well_after))); + assert_eq!(span(start, well_after).trim_start(other), Some(span(end, well_after))); + assert_eq!(span(before, well_after).trim_start(other), Some(span(end, well_after))); + + assert_eq!(span(mid, end).trim_start(other), None); + assert_eq!(span(start, end).trim_start(other), None); + assert_eq!(span(before, end).trim_start(other), None); + + assert_eq!(span(start, mid).trim_start(other), None); + assert_eq!(span(before, mid).trim_start(other), None); + + assert_eq!(span(before, start).trim_start(other), None); + + assert_eq!(span(well_before, before).trim_start(other), None); +} From df96cba432d9e869765385d6474b505494533435 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Jun 2024 17:00:10 +1000 Subject: [PATCH 040/154] Add `Span::trim_end` This is the counterpart of `Span::trim_start`. --- compiler/rustc_span/src/lib.rs | 7 +++++++ compiler/rustc_span/src/tests.rs | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index b2ca01fe3b94..82179a4a0586 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -682,6 +682,13 @@ impl Span { if span.hi > other.hi { Some(span.with_lo(cmp::max(span.lo, other.hi))) } else { None } } + /// Returns `Some(span)`, where the end is trimmed by the start of `other`. + pub fn trim_end(self, other: Span) -> Option { + let span = self.data(); + let other = other.data(); + if span.lo < other.lo { Some(span.with_hi(cmp::min(span.hi, other.lo))) } else { None } + } + /// Returns the source span -- this is either the supplied span, or the span for /// the macro callsite that expanded to it. pub fn source_callsite(self) -> Span { diff --git a/compiler/rustc_span/src/tests.rs b/compiler/rustc_span/src/tests.rs index 5c9dcc2a80fc..48fa786fb1c8 100644 --- a/compiler/rustc_span/src/tests.rs +++ b/compiler/rustc_span/src/tests.rs @@ -61,6 +61,25 @@ fn test_trim() { // The resulting span's context should be that of `self`, not `other`. let other = span(start, end).with_ctxt(SyntaxContext::from_u32(999)); + // Test cases for `trim_end`. + + assert_eq!(span(well_before, before).trim_end(other), Some(span(well_before, before))); + assert_eq!(span(well_before, start).trim_end(other), Some(span(well_before, start))); + assert_eq!(span(well_before, mid).trim_end(other), Some(span(well_before, start))); + assert_eq!(span(well_before, end).trim_end(other), Some(span(well_before, start))); + assert_eq!(span(well_before, after).trim_end(other), Some(span(well_before, start))); + + assert_eq!(span(start, mid).trim_end(other), None); + assert_eq!(span(start, end).trim_end(other), None); + assert_eq!(span(start, after).trim_end(other), None); + + assert_eq!(span(mid, end).trim_end(other), None); + assert_eq!(span(mid, after).trim_end(other), None); + + assert_eq!(span(end, after).trim_end(other), None); + + assert_eq!(span(after, well_after).trim_end(other), None); + // Test cases for `trim_start`. assert_eq!(span(after, well_after).trim_start(other), Some(span(after, well_after))); From 9c931c01f70d12d7296fead28b1c3dc417bb9372 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Jun 2024 15:27:30 +1000 Subject: [PATCH 041/154] coverage: Return a nested vector from initial span extraction This will allow the span extractor to produce multiple separate buckets, instead of just one flat list of spans. --- .../rustc_mir_transform/src/coverage/spans.rs | 15 +++++++++------ .../src/coverage/spans/from_mir.rs | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index f2f76ac70c20..b0bd514f6903 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -20,13 +20,16 @@ pub(super) fn extract_refined_covspans( basic_coverage_blocks: &CoverageGraph, code_mappings: &mut impl Extend, ) { - let sorted_spans = + let sorted_span_buckets = from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks); - let coverage_spans = SpansRefiner::refine_sorted_spans(sorted_spans); - code_mappings.extend(coverage_spans.into_iter().map(|RefinedCovspan { bcb, span, .. }| { - // Each span produced by the generator represents an ordinary code region. - mappings::CodeMapping { span, bcb } - })); + for bucket in sorted_span_buckets { + let refined_spans = SpansRefiner::refine_sorted_spans(bucket); + code_mappings.extend(refined_spans.into_iter().map(|covspan| { + let RefinedCovspan { span, bcb, is_hole: _ } = covspan; + // Each span produced by the refiner represents an ordinary code region. + mappings::CodeMapping { span, bcb } + })); + } } #[derive(Debug)] diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index d1727a94a35e..8e4466a99718 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -23,7 +23,7 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( mir_body: &mir::Body<'_>, hir_info: &ExtractedHirInfo, basic_coverage_blocks: &CoverageGraph, -) -> Vec { +) -> Vec> { let &ExtractedHirInfo { body_span, .. } = hir_info; let mut initial_spans = vec![]; @@ -67,7 +67,7 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( // requires a lot more complexity in the span refiner, for little benefit.) initial_spans.dedup_by(|b, a| a.span.source_equal(b.span)); - initial_spans + vec![initial_spans] } /// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate From 464dee24ffb1295d8dfb36455452b8658ae37878 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Jun 2024 15:56:09 +1000 Subject: [PATCH 042/154] coverage: Build up initial spans by appending to a vector This is less elegant than returning an iterator, but more flexible. --- .../src/coverage/spans/from_mir.rs | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 8e4466a99718..3fa37198732e 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -1,4 +1,3 @@ -use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::mir::coverage::CoverageKind; @@ -29,7 +28,7 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( let mut initial_spans = vec![]; for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() { - initial_spans.extend(bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data)); + bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data, &mut initial_spans); } // Only add the signature span if we found at least one span in the body. @@ -135,8 +134,9 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( body_span: Span, bcb: BasicCoverageBlock, bcb_data: &'a BasicCoverageBlockData, -) -> impl Iterator + Captures<'a> + Captures<'tcx> { - bcb_data.basic_blocks.iter().flat_map(move |&bb| { + initial_covspans: &mut Vec, +) { + for &bb in &bcb_data.basic_blocks { let data = &mir_body[bb]; let unexpand = move |expn_span| { @@ -146,24 +146,27 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( .filter(|(span, _)| !span.source_equal(body_span)) }; - let statement_spans = data.statements.iter().filter_map(move |statement| { - let expn_span = filtered_statement_span(statement)?; - let (span, visible_macro) = unexpand(expn_span)?; + for statement in data.statements.iter() { + let _: Option<()> = try { + let expn_span = filtered_statement_span(statement)?; + let (span, visible_macro) = unexpand(expn_span)?; - // A statement that looks like the assignment of a closure expression - // is treated as a "hole" span, to be carved out of other spans. - Some(SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement))) - }); + // A statement that looks like the assignment of a closure expression + // is treated as a "hole" span, to be carved out of other spans. + let covspan = + SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement)); + initial_covspans.push(covspan); + }; + } - let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| { + let _: Option<()> = try { + let terminator = data.terminator(); let expn_span = filtered_terminator_span(terminator)?; let (span, visible_macro) = unexpand(expn_span)?; - Some(SpanFromMir::new(span, visible_macro, bcb, false)) - }); - - statement_spans.chain(terminator_span) - }) + initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb, false)); + }; + } } fn is_closure_like(statement: &Statement<'_>) -> bool { From 6d1557f268f3dd5e7767ffdf7568856f659a3d57 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 3 Jun 2024 17:15:50 +1000 Subject: [PATCH 043/154] coverage: Use hole spans to carve up coverage spans into separate buckets This performs the same task as the hole-carving code in the main span refiner, but in a separate earlier pass. --- .../rustc_mir_transform/src/coverage/spans.rs | 2 +- .../src/coverage/spans/from_mir.rs | 199 +++++++++++++----- tests/coverage/closure_macro.cov-map | 8 +- tests/coverage/closure_macro_async.cov-map | 8 +- 4 files changed, 152 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index b0bd514f6903..9cda71cdd077 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -262,7 +262,7 @@ impl SpansRefiner { // a region of code, such as skipping past a hole. debug!(?prev, "prev.span starts after curr.span, so curr will be dropped"); } else { - self.some_curr = Some(CurrCovspan::new(curr.span, curr.bcb, curr.is_hole)); + self.some_curr = Some(CurrCovspan::new(curr.span, curr.bcb, false)); return true; } } diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 3fa37198732e..b1f71035dded 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -1,3 +1,6 @@ +use std::collections::VecDeque; + +use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; use rustc_middle::mir::coverage::CoverageKind; @@ -16,8 +19,11 @@ use crate::coverage::ExtractedHirInfo; /// spans, each associated with a node in the coverage graph (BCB) and possibly /// other metadata. /// -/// The returned spans are sorted in a specific order that is expected by the -/// subsequent span-refinement step. +/// The returned spans are divided into one or more buckets, such that: +/// - The spans in each bucket are strictly after all spans in previous buckets, +/// and strictly before all spans in subsequent buckets. +/// - The contents of each bucket are also sorted, in a specific order that is +/// expected by the subsequent span-refinement step. pub(super) fn mir_to_initial_sorted_coverage_spans( mir_body: &mir::Body<'_>, hir_info: &ExtractedHirInfo, @@ -26,13 +32,21 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( let &ExtractedHirInfo { body_span, .. } = hir_info; let mut initial_spans = vec![]; + let mut holes = vec![]; for (bcb, bcb_data) in basic_coverage_blocks.iter_enumerated() { - bcb_to_initial_coverage_spans(mir_body, body_span, bcb, bcb_data, &mut initial_spans); + bcb_to_initial_coverage_spans( + mir_body, + body_span, + bcb, + bcb_data, + &mut initial_spans, + &mut holes, + ); } // Only add the signature span if we found at least one span in the body. - if !initial_spans.is_empty() { + if !initial_spans.is_empty() || !holes.is_empty() { // If there is no usable signature span, add a fake one (before refinement) // to avoid an ugly gap between the body start and the first real span. // FIXME: Find a more principled way to solve this problem. @@ -44,29 +58,82 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( remove_unwanted_macro_spans(&mut initial_spans); split_visible_macro_spans(&mut initial_spans); - initial_spans.sort_by(|a, b| { - // First sort by span start. - Ord::cmp(&a.span.lo(), &b.span.lo()) - // If span starts are the same, sort by span end in reverse order. - // This ensures that if spans A and B are adjacent in the list, - // and they overlap but are not equal, then either: - // - Span A extends further left, or - // - Both have the same start and span A extends further right - .then_with(|| Ord::cmp(&a.span.hi(), &b.span.hi()).reverse()) - // If two spans have the same lo & hi, put hole spans first, - // as they take precedence over non-hole spans. - .then_with(|| Ord::cmp(&a.is_hole, &b.is_hole).reverse()) + let compare_covspans = |a: &SpanFromMir, b: &SpanFromMir| { + compare_spans(a.span, b.span) // After deduplication, we want to keep only the most-dominated BCB. .then_with(|| basic_coverage_blocks.cmp_in_dominator_order(a.bcb, b.bcb).reverse()) - }); + }; + initial_spans.sort_by(compare_covspans); - // Among covspans with the same span, keep only one. Hole spans take - // precedence, otherwise keep the one with the most-dominated BCB. + // Among covspans with the same span, keep only one, + // preferring the one with the most-dominated BCB. // (Ideally we should try to preserve _all_ non-dominating BCBs, but that // requires a lot more complexity in the span refiner, for little benefit.) initial_spans.dedup_by(|b, a| a.span.source_equal(b.span)); - vec![initial_spans] + // Sort the holes, and merge overlapping/adjacent holes. + holes.sort_by(|a, b| compare_spans(a.span, b.span)); + holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b)); + + // Now we're ready to start carving holes out of the initial coverage spans, + // and grouping them in buckets separated by the holes. + + let mut initial_spans = VecDeque::from(initial_spans); + let mut fragments: Vec = vec![]; + + // For each hole: + // - Identify the spans that are entirely or partly before the hole. + // - Put those spans in a corresponding bucket, truncated to the start of the hole. + // - If one of those spans also extends after the hole, put the rest of it + // in a "fragments" vector that is processed by the next hole. + let mut buckets = (0..holes.len()).map(|_| vec![]).collect::>(); + for (hole, bucket) in holes.iter().zip(&mut buckets) { + let fragments_from_prev = std::mem::take(&mut fragments); + + // Only inspect spans that precede or overlap this hole, + // leaving the rest to be inspected by later holes. + // (This relies on the spans and holes both being sorted.) + let relevant_initial_spans = + drain_front_while(&mut initial_spans, |c| c.span.lo() < hole.span.hi()); + + for covspan in fragments_from_prev.into_iter().chain(relevant_initial_spans) { + let (before, after) = covspan.split_around_hole_span(hole.span); + bucket.extend(before); + fragments.extend(after); + } + } + + // After finding the spans before each hole, any remaining fragments/spans + // form their own final bucket, after the final hole. + // (If there were no holes, this will just be all of the initial spans.) + fragments.extend(initial_spans); + buckets.push(fragments); + + // Make sure each individual bucket is still internally sorted. + for bucket in &mut buckets { + bucket.sort_by(compare_covspans); + } + buckets +} + +fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering { + // First sort by span start. + Ord::cmp(&a.lo(), &b.lo()) + // If span starts are the same, sort by span end in reverse order. + // This ensures that if spans A and B are adjacent in the list, + // and they overlap but are not equal, then either: + // - Span A extends further left, or + // - Both have the same start and span A extends further right + .then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse()) +} + +/// Similar to `.drain(..)`, but stops just before it would remove an item not +/// satisfying the predicate. +fn drain_front_while<'a, T>( + queue: &'a mut VecDeque, + mut pred_fn: impl FnMut(&T) -> bool, +) -> impl Iterator + Captures<'a> { + std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None }) } /// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate @@ -79,8 +146,8 @@ pub(super) fn mir_to_initial_sorted_coverage_spans( fn remove_unwanted_macro_spans(initial_spans: &mut Vec) { let mut seen_macro_spans = FxHashSet::default(); initial_spans.retain(|covspan| { - // Ignore (retain) hole spans and non-macro-expansion spans. - if covspan.is_hole || covspan.visible_macro.is_none() { + // Ignore (retain) non-macro-expansion spans. + if covspan.visible_macro.is_none() { return true; } @@ -97,10 +164,6 @@ fn split_visible_macro_spans(initial_spans: &mut Vec) { let mut extra_spans = vec![]; initial_spans.retain(|covspan| { - if covspan.is_hole { - return true; - } - let Some(visible_macro) = covspan.visible_macro else { return true }; let split_len = visible_macro.as_str().len() as u32 + 1; @@ -113,9 +176,8 @@ fn split_visible_macro_spans(initial_spans: &mut Vec) { return true; } - assert!(!covspan.is_hole); - extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb, false)); - extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb, false)); + extra_spans.push(SpanFromMir::new(before, covspan.visible_macro, covspan.bcb)); + extra_spans.push(SpanFromMir::new(after, covspan.visible_macro, covspan.bcb)); false // Discard the original covspan that we just split. }); @@ -135,6 +197,7 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( bcb: BasicCoverageBlock, bcb_data: &'a BasicCoverageBlockData, initial_covspans: &mut Vec, + holes: &mut Vec, ) { for &bb in &bcb_data.basic_blocks { let data = &mir_body[bb]; @@ -146,26 +209,31 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>( .filter(|(span, _)| !span.source_equal(body_span)) }; - for statement in data.statements.iter() { - let _: Option<()> = try { - let expn_span = filtered_statement_span(statement)?; - let (span, visible_macro) = unexpand(expn_span)?; + let mut extract_statement_span = |statement| { + let expn_span = filtered_statement_span(statement)?; + let (span, visible_macro) = unexpand(expn_span)?; - // A statement that looks like the assignment of a closure expression - // is treated as a "hole" span, to be carved out of other spans. - let covspan = - SpanFromMir::new(span, visible_macro, bcb, is_closure_like(statement)); - initial_covspans.push(covspan); - }; + // A statement that looks like the assignment of a closure expression + // is treated as a "hole" span, to be carved out of other spans. + if is_closure_like(statement) { + holes.push(Hole { span }); + } else { + initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb)); + } + Some(()) + }; + for statement in data.statements.iter() { + extract_statement_span(statement); } - let _: Option<()> = try { - let terminator = data.terminator(); + let mut extract_terminator_span = |terminator| { let expn_span = filtered_terminator_span(terminator)?; let (span, visible_macro) = unexpand(expn_span)?; - initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb, false)); + initial_covspans.push(SpanFromMir::new(span, visible_macro, bcb)); + Some(()) }; + extract_terminator_span(data.terminator()); } } @@ -333,6 +401,22 @@ fn unexpand_into_body_span_with_prev( Some((curr, prev)) } +#[derive(Debug)] +struct Hole { + span: Span, +} + +impl Hole { + fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool { + if !self.span.overlaps_or_adjacent(other.span) { + return false; + } + + self.span = self.span.to(other.span); + true + } +} + #[derive(Debug)] pub(super) struct SpanFromMir { /// A span that has been extracted from MIR and then "un-expanded" back to @@ -345,23 +429,30 @@ pub(super) struct SpanFromMir { pub(super) span: Span, visible_macro: Option, pub(super) bcb: BasicCoverageBlock, - /// If true, this covspan represents a "hole" that should be carved out - /// from other spans, e.g. because it represents a closure expression that - /// will be instrumented separately as its own function. - pub(super) is_hole: bool, } impl SpanFromMir { fn for_fn_sig(fn_sig_span: Span) -> Self { - Self::new(fn_sig_span, None, START_BCB, false) + Self::new(fn_sig_span, None, START_BCB) } - fn new( - span: Span, - visible_macro: Option, - bcb: BasicCoverageBlock, - is_hole: bool, - ) -> Self { - Self { span, visible_macro, bcb, is_hole } + fn new(span: Span, visible_macro: Option, bcb: BasicCoverageBlock) -> Self { + Self { span, visible_macro, bcb } + } + + /// Splits this span into 0-2 parts: + /// - The part that is strictly before the hole span, if any. + /// - The part that is strictly after the hole span, if any. + fn split_around_hole_span(&self, hole_span: Span) -> (Option, Option) { + let before = try { + let span = self.span.trim_end(hole_span)?; + Self { span, ..*self } + }; + let after = try { + let span = self.span.trim_start(hole_span)?; + Self { span, ..*self } + }; + + (before, after) } } diff --git a/tests/coverage/closure_macro.cov-map b/tests/coverage/closure_macro.cov-map index fd8fbd9fa757..156947f4e21c 100644 --- a/tests/coverage/closure_macro.cov-map +++ b/tests/coverage/closure_macro.cov-map @@ -7,16 +7,14 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 29, 1) to (start + 2, 2) Function name: closure_macro::main -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 21, 01, 01, 21, 02, 02, 09, 00, 12, 02, 00, 0f, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 21, 01, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 +Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 33, 1) to (start + 1, 33) -- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 18) - = (c0 - c1) -- Code(Expression(0, Sub)) at (prev + 0, 15) to (start + 0, 84) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) diff --git a/tests/coverage/closure_macro_async.cov-map b/tests/coverage/closure_macro_async.cov-map index 43b52008f33e..0f2b4e017483 100644 --- a/tests/coverage/closure_macro_async.cov-map +++ b/tests/coverage/closure_macro_async.cov-map @@ -15,16 +15,14 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 35, 1) to (start + 0, 43) Function name: closure_macro_async::test::{closure#0} -Raw bytes (36): 0x[01, 01, 01, 01, 05, 06, 01, 23, 2b, 01, 21, 02, 02, 09, 00, 12, 02, 00, 0f, 00, 54, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] +Raw bytes (31): 0x[01, 01, 01, 01, 05, 05, 01, 23, 2b, 01, 21, 02, 02, 09, 00, 0f, 05, 00, 54, 00, 55, 02, 02, 09, 02, 0b, 01, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 1 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 6 +Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 35, 43) to (start + 1, 33) -- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 18) - = (c0 - c1) -- Code(Expression(0, Sub)) at (prev + 0, 15) to (start + 0, 84) +- Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 0, 15) = (c0 - c1) - Code(Counter(1)) at (prev + 0, 84) to (start + 0, 85) - Code(Expression(0, Sub)) at (prev + 2, 9) to (start + 2, 11) From c57a1d1baa0a2fc4328f81be66dc7b518c1953bb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 2 Jun 2024 22:35:13 +1000 Subject: [PATCH 044/154] coverage: Remove hole-carving code from the main span refiner Now that hole spans are handled by a separate earlier pass, this code never sees hole spans, and therefore doesn't need to deal with them. --- .../rustc_mir_transform/src/coverage/spans.rs | 99 ++++--------------- 1 file changed, 19 insertions(+), 80 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 9cda71cdd077..743f1cc24bee 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -24,8 +24,7 @@ pub(super) fn extract_refined_covspans( from_mir::mir_to_initial_sorted_coverage_spans(mir_body, hir_info, basic_coverage_blocks); for bucket in sorted_span_buckets { let refined_spans = SpansRefiner::refine_sorted_spans(bucket); - code_mappings.extend(refined_spans.into_iter().map(|covspan| { - let RefinedCovspan { span, bcb, is_hole: _ } = covspan; + code_mappings.extend(refined_spans.into_iter().map(|RefinedCovspan { span, bcb }| { // Each span produced by the refiner represents an ordinary code region. mappings::CodeMapping { span, bcb } })); @@ -36,24 +35,16 @@ pub(super) fn extract_refined_covspans( struct CurrCovspan { span: Span, bcb: BasicCoverageBlock, - is_hole: bool, } impl CurrCovspan { - fn new(span: Span, bcb: BasicCoverageBlock, is_hole: bool) -> Self { - Self { span, bcb, is_hole } + fn new(span: Span, bcb: BasicCoverageBlock) -> Self { + Self { span, bcb } } fn into_prev(self) -> PrevCovspan { - let Self { span, bcb, is_hole } = self; - PrevCovspan { span, bcb, merged_spans: vec![span], is_hole } - } - - fn into_refined(self) -> RefinedCovspan { - // This is only called in cases where `curr` is a hole span that has - // been carved out of `prev`. - debug_assert!(self.is_hole); - self.into_prev().into_refined() + let Self { span, bcb } = self; + PrevCovspan { span, bcb, merged_spans: vec![span] } } } @@ -64,12 +55,11 @@ struct PrevCovspan { /// List of all the original spans from MIR that have been merged into this /// span. Mainly used to precisely skip over gaps when truncating a span. merged_spans: Vec, - is_hole: bool, } impl PrevCovspan { fn is_mergeable(&self, other: &CurrCovspan) -> bool { - self.bcb == other.bcb && !self.is_hole && !other.is_hole + self.bcb == other.bcb } fn merge_from(&mut self, other: &CurrCovspan) { @@ -87,14 +77,9 @@ impl PrevCovspan { if self.merged_spans.is_empty() { None } else { Some(self.into_refined()) } } - fn refined_copy(&self) -> RefinedCovspan { - let &Self { span, bcb, merged_spans: _, is_hole } = self; - RefinedCovspan { span, bcb, is_hole } - } - fn into_refined(self) -> RefinedCovspan { - // Even though we consume self, we can just reuse the copying impl. - self.refined_copy() + let Self { span, bcb, merged_spans: _ } = self; + RefinedCovspan { span, bcb } } } @@ -102,12 +87,11 @@ impl PrevCovspan { struct RefinedCovspan { span: Span, bcb: BasicCoverageBlock, - is_hole: bool, } impl RefinedCovspan { fn is_mergeable(&self, other: &Self) -> bool { - self.bcb == other.bcb && !self.is_hole && !other.is_hole + self.bcb == other.bcb } fn merge_from(&mut self, other: &Self) { @@ -122,8 +106,6 @@ impl RefinedCovspan { /// * Remove duplicate source code coverage regions /// * Merge spans that represent continuous (both in source code and control flow), non-branching /// execution -/// * Carve out (leave uncovered) any "hole" spans that need to be left blank -/// (e.g. closures that will be counted by their own MIR body) struct SpansRefiner { /// The initial set of coverage spans, sorted by `Span` (`lo` and `hi`) and by relative /// dominance between the `BasicCoverageBlock`s of equal `Span`s. @@ -184,13 +166,6 @@ impl SpansRefiner { ); let prev = self.take_prev().into_refined(); self.refined_spans.push(prev); - } else if prev.is_hole { - // drop any equal or overlapping span (`curr`) and keep `prev` to test again in the - // next iter - debug!(?prev, "prev (a hole) overlaps curr, so discarding curr"); - self.take_curr(); // Discards curr. - } else if curr.is_hole { - self.carve_out_span_for_hole(); } else { self.cutoff_prev_at_overlapping_curr(); } @@ -214,9 +189,6 @@ impl SpansRefiner { } }); - // Discard hole spans, since their purpose was to carve out chunks from - // other spans, but we don't want the holes themselves in the final mappings. - self.refined_spans.retain(|covspan| !covspan.is_hole); self.refined_spans } @@ -252,50 +224,17 @@ impl SpansRefiner { if let Some(curr) = self.some_curr.take() { self.some_prev = Some(curr.into_prev()); } - while let Some(curr) = self.sorted_spans_iter.next() { - debug!("FOR curr={:?}", curr); - if let Some(prev) = &self.some_prev - && prev.span.lo() > curr.span.lo() - { - // Skip curr because prev has already advanced beyond the end of curr. - // This can only happen if a prior iteration updated `prev` to skip past - // a region of code, such as skipping past a hole. - debug!(?prev, "prev.span starts after curr.span, so curr will be dropped"); - } else { - self.some_curr = Some(CurrCovspan::new(curr.span, curr.bcb, false)); - return true; + if let Some(SpanFromMir { span, bcb, .. }) = self.sorted_spans_iter.next() { + // This code only sees sorted spans after hole-carving, so there should + // be no way for `curr` to start before `prev`. + if let Some(prev) = &self.some_prev { + debug_assert!(prev.span.lo() <= span.lo()); } - } - false - } - - /// If `prev`s span extends left of the hole (`curr`), carve out the hole's span from - /// `prev`'s span. Add the portion of the span to the left of the hole; and if the span - /// extends to the right of the hole, update `prev` to that portion of the span. - fn carve_out_span_for_hole(&mut self) { - let prev = self.prev(); - let curr = self.curr(); - - let left_cutoff = curr.span.lo(); - let right_cutoff = curr.span.hi(); - let has_pre_hole_span = prev.span.lo() < right_cutoff; - let has_post_hole_span = prev.span.hi() > right_cutoff; - - if has_pre_hole_span { - let mut pre_hole = prev.refined_copy(); - pre_hole.span = pre_hole.span.with_hi(left_cutoff); - debug!(?pre_hole, "prev overlaps a hole; adding pre-hole span"); - self.refined_spans.push(pre_hole); - } - - if has_post_hole_span { - // Mutate `prev.span` to start after the hole (and discard curr). - self.prev_mut().span = self.prev().span.with_lo(right_cutoff); - debug!(prev=?self.prev(), "mutated prev to start after the hole"); - - // Prevent this curr from becoming prev. - let hole_covspan = self.take_curr().into_refined(); - self.refined_spans.push(hole_covspan); // since self.prev() was already updated + self.some_curr = Some(CurrCovspan::new(span, bcb)); + debug!(?self.some_prev, ?self.some_curr, "next_coverage_span"); + true + } else { + false } } From f4b060e452fa00a04f20ad7a0ec140fda48f3b50 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 28 May 2024 11:18:46 -0600 Subject: [PATCH 045/154] Add more ABI test cases. --- .../miri/tests/pass/function_calls/abi_compat.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs index 136660a305af..0cfcd532ff4b 100644 --- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs +++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs @@ -83,12 +83,24 @@ fn main() { test_abi_compat(main as fn(), id:: as fn(i32) -> i32); // - 1-ZST test_abi_compat((), [0u8; 0]); - // - Guaranteed null-pointer-optimizations (RFC 3391). + // - Guaranteed Option null-pointer-optimizations (RFC 3391). test_abi_compat(&0u32 as *const u32, Some(&0u32)); test_abi_compat(main as fn(), Some(main as fn())); test_abi_compat(0u32, Some(num::NonZero::new(1u32).unwrap())); test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32))); - test_abi_compat(0u32, Some(Wrapper(num::NonZero::new(1u32).unwrap()))); + test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1u32).unwrap()))); + // - Guaranteed Result does the same as Option (RFC 3391) + test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(&0u32)); + test_abi_compat(main as fn(), Result::<_, ()>::Ok(main as fn())); + test_abi_compat(0u32, Result::<_, ()>::Ok(num::NonZeroU32::new(1).unwrap())); + test_abi_compat(&0u32 as *const u32, Result::<_, ()>::Ok(Wrapper(&0u32))); + test_abi_compat(0u32, Result::<_, ()>::Ok(Wrapper(num::NonZeroU32::new(1).unwrap()))); + // - Guaranteed Result also does the same as Option (RFC 3391) + test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(&0u32)); + test_abi_compat(main as fn(), Result::<(), _>::Err(main as fn())); + test_abi_compat(0u32, Result::<(), _>::Err(num::NonZeroU32::new(1).unwrap())); + test_abi_compat(&0u32 as *const u32, Result::<(), _>::Err(Wrapper(&0u32))); + test_abi_compat(0u32, Result::<(), _>::Err(Wrapper(num::NonZeroU32::new(1).unwrap()))); // These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible // with the wrapped field. From fd648a3c76a16a1287ed793fd28ebdc33b7124be Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 3 Jun 2024 19:01:35 +0000 Subject: [PATCH 046/154] std::unix::fs::get_path: using fcntl codepath for netbsd instead. on netbsd, procfs is not as central as on linux/solaris thus can be perfectly not mounted. Thus using fcntl with F_GETPATH, the kernel deals with MAXPATHLEN internally too. --- library/std/src/sys/pal/unix/fs.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs index fbbd40bfb796..3d4452e73a64 100644 --- a/library/std/src/sys/pal/unix/fs.rs +++ b/library/std/src/sys/pal/unix/fs.rs @@ -1481,29 +1481,33 @@ impl FromRawFd for File { impl fmt::Debug for File { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - #[cfg(any( - target_os = "linux", - target_os = "netbsd", - target_os = "illumos", - target_os = "solaris" - ))] + #[cfg(any(target_os = "linux", target_os = "illumos", target_os = "solaris"))] fn get_path(fd: c_int) -> Option { let mut p = PathBuf::from("/proc/self/fd"); p.push(&fd.to_string()); readlink(&p).ok() } - #[cfg(target_vendor = "apple")] + #[cfg(any(target_vendor = "apple", target_os = "netbsd"))] fn get_path(fd: c_int) -> Option { // FIXME: The use of PATH_MAX is generally not encouraged, but it - // is inevitable in this case because Apple targets define `fcntl` + // is inevitable in this case because Apple targets and NetBSD define `fcntl` // with `F_GETPATH` in terms of `MAXPATHLEN`, and there are no // alternatives. If a better method is invented, it should be used // instead. let mut buf = vec![0; libc::PATH_MAX as usize]; let n = unsafe { libc::fcntl(fd, libc::F_GETPATH, buf.as_ptr()) }; if n == -1 { - return None; + cfg_if::cfg_if! { + if #[cfg(target_os = "netbsd")] { + // fallback to procfs as last resort + let mut p = PathBuf::from("/proc/self/fd"); + p.push(&fd.to_string()); + return readlink(&p).ok(); + } else { + return None; + } + } } let l = buf.iter().position(|&c| c == 0).unwrap(); buf.truncate(l as usize); From f67a0eb2b72294f108051381cbc833c295aadad9 Mon Sep 17 00:00:00 2001 From: bohan Date: Tue, 4 Jun 2024 12:40:41 +0800 Subject: [PATCH 047/154] resolve: mark it undetermined if single import is not has any bindings --- compiler/rustc_resolve/src/ident.rs | 29 +++++++++++++++++-- compiler/rustc_resolve/src/imports.rs | 4 +-- tests/crashes/124490.rs | 16 ---------- tests/crashes/125013-1.rs | 5 ---- tests/crashes/125013-2.rs | 16 ---------- .../imports/cycle-import-in-diff-module-0.rs | 14 +++++++++ .../imports/cycle-import-in-diff-module-1.rs | 14 +++++++++ .../shadow-glob-module-resolution-1.rs | 17 +++++++++++ .../shadow-glob-module-resolution-1.stderr | 23 +++++++++++++++ .../shadow-glob-module-resolution-2.rs | 19 ++++++++++++ .../shadow-glob-module-resolution-2.stderr | 26 +++++++++++++++++ 11 files changed, 142 insertions(+), 41 deletions(-) delete mode 100644 tests/crashes/124490.rs delete mode 100644 tests/crashes/125013-1.rs delete mode 100644 tests/crashes/125013-2.rs create mode 100644 tests/ui/imports/cycle-import-in-diff-module-0.rs create mode 100644 tests/ui/imports/cycle-import-in-diff-module-1.rs create mode 100644 tests/ui/imports/shadow-glob-module-resolution-1.rs create mode 100644 tests/ui/imports/shadow-glob-module-resolution-1.stderr create mode 100644 tests/ui/imports/shadow-glob-module-resolution-2.rs create mode 100644 tests/ui/imports/shadow-glob-module-resolution-2.stderr diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 57db765c07e5..78bd3c4e49f2 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -965,6 +965,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // if it can then our result is not determined and can be invalidated. for single_import in &resolution.single_imports { let Some(import_vis) = single_import.vis.get() else { + // This branch handles a cycle in single imports, which occurs + // when we've previously captured the `vis` value during an import + // process. + // + // For example: + // ``` + // use a::b; + // use b as a; + // ``` + // 1. Steal the `vis` in `use a::b` and attempt to locate `a` in the + // current module. + // 2. Encounter the import `use b as a`, which is a `single_import` for `a`, + // and try to find `b` in the current module. + // 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`. + // This leads to entering this branch. continue; }; if !self.is_accessible_from(import_vis, parent_scope.module) { @@ -979,15 +994,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // named imports. continue; } + let Some(module) = single_import.imported_module.get() else { return Err((Undetermined, Weak::No)); }; - let ImportKind::Single { source: ident, .. } = single_import.kind else { + let ImportKind::Single { source: ident, source_bindings, .. } = &single_import.kind + else { unreachable!(); }; + if binding.map_or(false, |binding| binding.module().is_some()) + && source_bindings.iter().all(|binding| matches!(binding.get(), Err(Undetermined))) + { + // This branch allows the binding to be defined or updated later, + // avoiding module inconsistency between the resolve process and the finalize process. + // See more details in #124840 + return Err((Undetermined, Weak::No)); + } match self.resolve_ident_in_module( module, - ident, + *ident, ns, &single_import.parent_scope, None, diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 6bbde26db344..27ea7760f589 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -352,9 +352,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { (old_glob @ true, false) | (old_glob @ false, true) => { let (glob_binding, nonglob_binding) = if old_glob { (old_binding, binding) } else { (binding, old_binding) }; - if glob_binding.res() != nonglob_binding.res() - && key.ns == MacroNS + if key.ns == MacroNS && nonglob_binding.expansion != LocalExpnId::ROOT + && glob_binding.res() != nonglob_binding.res() { resolution.binding = Some(this.ambiguity( AmbiguityKind::GlobVsExpanded, diff --git a/tests/crashes/124490.rs b/tests/crashes/124490.rs deleted file mode 100644 index 9f605c32cf26..000000000000 --- a/tests/crashes/124490.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#124490 -use io::{self as std}; -use std::collections::{self as io}; - -mod a { - pub mod b { - pub mod c {} - } -} - -use a::*; - -use b::c; -use c as b; - -fn main() {} diff --git a/tests/crashes/125013-1.rs b/tests/crashes/125013-1.rs deleted file mode 100644 index ae66d7a14669..000000000000 --- a/tests/crashes/125013-1.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ known-bug: rust-lang/rust#125013 -//@ edition:2021 -use io::{self as std}; -use std::ops::Deref::{self as io}; -pub fn main() {} diff --git a/tests/crashes/125013-2.rs b/tests/crashes/125013-2.rs deleted file mode 100644 index a14c8a76b63e..000000000000 --- a/tests/crashes/125013-2.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: rust-lang/rust#125013 -//@ edition:2021 -mod a { - pub mod b { - pub mod c { - pub trait D {} - } - } -} - -use a::*; - -use e as b; -use b::c::D as e; - -fn main() { } diff --git a/tests/ui/imports/cycle-import-in-diff-module-0.rs b/tests/ui/imports/cycle-import-in-diff-module-0.rs new file mode 100644 index 000000000000..962603a89716 --- /dev/null +++ b/tests/ui/imports/cycle-import-in-diff-module-0.rs @@ -0,0 +1,14 @@ +//@ check-pass + +// https://github.com/rust-lang/rust/pull/124840#issuecomment-2098148587 + +mod a { + pub(crate) use crate::S; +} +mod b { + pub struct S; +} +use self::a::S; +use self::b::*; + +fn main() {} diff --git a/tests/ui/imports/cycle-import-in-diff-module-1.rs b/tests/ui/imports/cycle-import-in-diff-module-1.rs new file mode 100644 index 000000000000..8c67df376c3f --- /dev/null +++ b/tests/ui/imports/cycle-import-in-diff-module-1.rs @@ -0,0 +1,14 @@ +//@ check-pass + +// similar `cycle-import-in-diff-module-0.rs` + +mod a { + pub(crate) use crate::s; +} +mod b { + pub mod s {} +} +use self::b::*; +use self::a::s; + +fn main() {} diff --git a/tests/ui/imports/shadow-glob-module-resolution-1.rs b/tests/ui/imports/shadow-glob-module-resolution-1.rs new file mode 100644 index 000000000000..ba1e65cddc65 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-1.rs @@ -0,0 +1,17 @@ +// https://github.com/rust-lang/rust/issues/124490 + +mod a { + pub mod b { + pub mod c {} + } +} + +use a::*; + +use b::c; +//~^ ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import +//~| ERROR: unresolved import `b::c` +use c as b; + +fn main() {} diff --git a/tests/ui/imports/shadow-glob-module-resolution-1.stderr b/tests/ui/imports/shadow-glob-module-resolution-1.stderr new file mode 100644 index 000000000000..f9135963fe99 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-1.stderr @@ -0,0 +1,23 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-1.rs:11:5 + | +LL | use b::c; + | ^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-1.rs:11:5 + | +LL | use b::c; + | ^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0432]: unresolved import `b::c` + --> $DIR/shadow-glob-module-resolution-1.rs:11:5 + | +LL | use b::c; + | ^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.rs b/tests/ui/imports/shadow-glob-module-resolution-2.rs new file mode 100644 index 000000000000..36bd72658ae8 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-2.rs @@ -0,0 +1,19 @@ +// https://github.com/rust-lang/rust/issues/125013 + +mod a { + pub mod b { + pub mod c { + pub trait D {} + } + } +} + +use a::*; + +use e as b; +//~^ ERROR: unresolved import `e` +use b::c::D as e; +//~^ ERROR: cannot determine resolution for the import +//~| ERROR: cannot determine resolution for the import + +fn main() { } diff --git a/tests/ui/imports/shadow-glob-module-resolution-2.stderr b/tests/ui/imports/shadow-glob-module-resolution-2.stderr new file mode 100644 index 000000000000..644fcb841628 --- /dev/null +++ b/tests/ui/imports/shadow-glob-module-resolution-2.stderr @@ -0,0 +1,26 @@ +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-2.rs:15:5 + | +LL | use b::c::D as e; + | ^^^^^^^^^^^^ + +error: cannot determine resolution for the import + --> $DIR/shadow-glob-module-resolution-2.rs:15:5 + | +LL | use b::c::D as e; + | ^^^^^^^^^^^^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0432]: unresolved import `e` + --> $DIR/shadow-glob-module-resolution-2.rs:13:5 + | +LL | use e as b; + | -^^^^^ + | | + | no `e` in the root + | help: a similar name exists in the module: `a` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0432`. From 9b2e41a21800bcd56c5ce3307ab7e484f83d51b3 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Thu, 30 May 2024 15:22:12 +0200 Subject: [PATCH 048/154] Pass function for `Thread` as `Send` to `Thread::imp` --- library/std/src/thread/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 22215873933d..83e27dfb746c 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -561,7 +561,8 @@ impl Builder { let main = Box::new(main); // SAFETY: dynamic size and alignment of the Box remain the same. See below for why the // lifetime change is justified. - let main = unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + 'static)) }; + let main = + unsafe { Box::from_raw(Box::into_raw(main) as *mut (dyn FnOnce() + Send + 'static)) }; Ok(JoinInner { // SAFETY: @@ -1544,7 +1545,7 @@ struct Packet<'scope, T> { // The type `T` should already always be Send (otherwise the thread could not // have been created) and the Packet is Sync because all access to the // `UnsafeCell` synchronized (by the `join()` boundary), and `ScopeData` is Sync. -unsafe impl<'scope, T: Sync> Sync for Packet<'scope, T> {} +unsafe impl<'scope, T: Send> Sync for Packet<'scope, T> {} impl<'scope, T> Drop for Packet<'scope, T> { fn drop(&mut self) { From b8c6008fbcb0a1f9f8af1ad7b6b196c950351b67 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Thu, 30 May 2024 15:50:44 +0200 Subject: [PATCH 049/154] Store `Task::p` as `dyn FnOnce() + Send` --- library/std/src/sys/pal/sgx/thread.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index d70c6e31fb73..2d936b09c708 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -28,14 +28,14 @@ mod task_queue { } pub(super) struct Task { - p: Box, + p: Box, done: JoinNotifier, } unsafe impl Send for Task {} impl Task { - pub(super) fn new(p: Box) -> (Task, JoinHandle) { + pub(super) fn new(p: Box) -> (Task, JoinHandle) { let (done, recv) = wait_notify::new(); let done = JoinNotifier(Some(done)); (Task { p, done }, recv) @@ -97,7 +97,7 @@ pub mod wait_notify { impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements - pub unsafe fn new(_stack: usize, p: Box) -> io::Result { + pub unsafe fn new(_stack: usize, p: Box) -> io::Result { let mut queue_lock = task_queue::lock(); unsafe { usercalls::launch_thread()? }; let (task, handle) = task_queue::Task::new(p); From 8db363c44b1512b5ba30b10ac3ad915228276375 Mon Sep 17 00:00:00 2001 From: Raoul Strackx Date: Thu, 30 May 2024 15:50:59 +0200 Subject: [PATCH 050/154] Let compiler auto impl `Send` for `Task` --- library/std/src/sys/pal/sgx/thread.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/std/src/sys/pal/sgx/thread.rs b/library/std/src/sys/pal/sgx/thread.rs index 2d936b09c708..446cdd18b7e4 100644 --- a/library/std/src/sys/pal/sgx/thread.rs +++ b/library/std/src/sys/pal/sgx/thread.rs @@ -32,8 +32,6 @@ mod task_queue { done: JoinNotifier, } - unsafe impl Send for Task {} - impl Task { pub(super) fn new(p: Box) -> (Task, JoinHandle) { let (done, recv) = wait_notify::new(); From 8f677e8fb20f0ad6d93b39d8b736ee7bc0939973 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Sun, 19 May 2024 11:42:34 +0300 Subject: [PATCH 051/154] bootstrap: implement new feature `bootstrap-self-test` Some of the bootstrap logics should be ignored during unit tests because they either make the tests take longer or cause them to fail. Therefore we need to be able to exclude them from the bootstrap when it's called by unit tests. This change introduces a new feature called `bootstrap-self-test`, which is enabled on bootstrap unit tests by default. This allows us to keep the logic separate between compiler builds and bootstrap tests without needing messy workarounds (like checking if target names match those in the unit tests). Signed-off-by: onur-ozkan --- src/bootstrap/Cargo.toml | 1 + src/bootstrap/src/core/build_steps/test.rs | 1 + src/bootstrap/src/core/config/config.rs | 19 +++++++++------ src/bootstrap/src/core/config/tests.rs | 28 ++++------------------ src/bootstrap/src/core/download.rs | 22 +++++++++++++++-- src/bootstrap/src/core/sanity.rs | 16 ++++++++----- 6 files changed, 49 insertions(+), 38 deletions(-) diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index ca0d1fa5bd0c..32dd3efa7a6e 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -7,6 +7,7 @@ default-run = "bootstrap" [features] build-metrics = ["sysinfo"] +bootstrap-self-test = [] # enabled in the bootstrap unit tests [lib] path = "src/lib.rs" diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 29b3d1669b4b..aaedee65ed75 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -3053,6 +3053,7 @@ impl Step for Bootstrap { let mut cmd = Command::new(&builder.initial_cargo); cmd.arg("test") + .args(["--features", "bootstrap-self-test"]) .current_dir(builder.src.join("src/bootstrap")) .env("RUSTFLAGS", "-Cdebuginfo=2") .env("CARGO_TARGET_DIR", builder.out.join("bootstrap")) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 70d32f2f6d95..17e37c1ecd23 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -22,8 +22,6 @@ use crate::utils::cache::{Interned, INTERNER}; use crate::utils::channel::{self, GitInfo}; use crate::utils::helpers::{exe, output, t}; use build_helper::exit; -use build_helper::util::fail; -use semver::Version; use serde::{Deserialize, Deserializer}; use serde_derive::Deserialize; @@ -2382,8 +2380,14 @@ impl Config { } } - // check rustc/cargo version is same or lower with 1 apart from the building one + #[cfg(feature = "bootstrap-self-test")] + pub fn check_stage0_version(&self, _program_path: &Path, _component_name: &'static str) {} + + /// check rustc/cargo version is same or lower with 1 apart from the building one + #[cfg(not(feature = "bootstrap-self-test"))] pub fn check_stage0_version(&self, program_path: &Path, component_name: &'static str) { + use build_helper::util::fail; + if self.dry_run() { return; } @@ -2400,11 +2404,12 @@ impl Config { } let stage0_version = - Version::parse(stage0_output.next().unwrap().split('-').next().unwrap().trim()) - .unwrap(); - let source_version = - Version::parse(fs::read_to_string(self.src.join("src/version")).unwrap().trim()) + semver::Version::parse(stage0_output.next().unwrap().split('-').next().unwrap().trim()) .unwrap(); + let source_version = semver::Version::parse( + fs::read_to_string(self.src.join("src/version")).unwrap().trim(), + ) + .unwrap(); if !(source_version == stage0_version || (source_version.major == stage0_version.major && (source_version.minor == stage0_version.minor diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs index c4073910623a..bfb2c02860d2 100644 --- a/src/bootstrap/src/core/config/tests.rs +++ b/src/bootstrap/src/core/config/tests.rs @@ -14,16 +14,9 @@ use std::{ }; fn parse(config: &str) -> Config { - Config::parse_inner( - &[ - "check".to_string(), - "--set=build.rustc=/does/not/exist".to_string(), - "--set=build.cargo=/does/not/exist".to_string(), - "--config=/does/not/exist".to_string(), - "--skip-stage0-validation".to_string(), - ], - |&_| toml::from_str(&config).unwrap(), - ) + Config::parse_inner(&["check".to_string(), "--config=/does/not/exist".to_string()], |&_| { + toml::from_str(&config).unwrap() + }) } #[test] @@ -212,10 +205,7 @@ fn override_toml_duplicate() { Config::parse_inner( &[ "check".to_owned(), - "--set=build.rustc=/does/not/exist".to_string(), - "--set=build.cargo=/does/not/exist".to_string(), - "--config=/does/not/exist".to_owned(), - "--skip-stage0-validation".to_owned(), + "--config=/does/not/exist".to_string(), "--set=change-id=1".to_owned(), "--set=change-id=2".to_owned(), ], @@ -238,15 +228,7 @@ fn profile_user_dist() { .and_then(|table: toml::Value| TomlConfig::deserialize(table)) .unwrap() } - Config::parse_inner( - &[ - "check".to_owned(), - "--set=build.rustc=/does/not/exist".to_string(), - "--set=build.cargo=/does/not/exist".to_string(), - "--skip-stage0-validation".to_string(), - ], - get_toml, - ); + Config::parse_inner(&["check".to_owned()], get_toml); } #[test] diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs index 60f48c5923e1..2b11b8c3d4f2 100644 --- a/src/bootstrap/src/core/download.rs +++ b/src/bootstrap/src/core/download.rs @@ -9,11 +9,10 @@ use std::{ }; use build_helper::ci::CiEnv; -use build_helper::stage0_parser::VersionMetadata; use xz2::bufread::XzDecoder; +use crate::utils::helpers::hex_encode; use crate::utils::helpers::{check_run, exe, move_file, program_out_of_date}; -use crate::{core::build_steps::llvm::detect_llvm_sha, utils::helpers::hex_encode}; use crate::{t, Config}; static SHOULD_FIX_BINS_AND_DYLIBS: OnceLock = OnceLock::new(); @@ -405,9 +404,17 @@ impl Config { cargo_clippy } + #[cfg(feature = "bootstrap-self-test")] + pub(crate) fn maybe_download_rustfmt(&self) -> Option { + None + } + /// NOTE: rustfmt is a completely different toolchain than the bootstrap compiler, so it can't /// reuse target directories or artifacts + #[cfg(not(feature = "bootstrap-self-test"))] pub(crate) fn maybe_download_rustfmt(&self) -> Option { + use build_helper::stage0_parser::VersionMetadata; + let VersionMetadata { date, version } = self.stage0_metadata.rustfmt.as_ref()?; let channel = format!("{version}-{date}"); @@ -487,6 +494,10 @@ impl Config { ); } + #[cfg(feature = "bootstrap-self-test")] + pub(crate) fn download_beta_toolchain(&self) {} + + #[cfg(not(feature = "bootstrap-self-test"))] pub(crate) fn download_beta_toolchain(&self) { self.verbose(|| println!("downloading stage0 beta artifacts")); @@ -665,7 +676,13 @@ download-rustc = false self.unpack(&tarball, &bin_root, prefix); } + #[cfg(feature = "bootstrap-self-test")] + pub(crate) fn maybe_download_ci_llvm(&self) {} + + #[cfg(not(feature = "bootstrap-self-test"))] pub(crate) fn maybe_download_ci_llvm(&self) { + use crate::core::build_steps::llvm::detect_llvm_sha; + if !self.llvm_from_ci { return; } @@ -707,6 +724,7 @@ download-rustc = false } } + #[cfg(not(feature = "bootstrap-self-test"))] fn download_ci_llvm(&self, llvm_sha: &str) { let llvm_assertions = self.llvm_assertions; diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 8ffa97ab78b5..ead38ebc6d5e 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -8,13 +8,15 @@ //! In theory if we get past this phase it's a bug if a build fails, but in //! practice that's likely not true! -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::env; use std::ffi::{OsStr, OsString}; use std::fs; use std::path::PathBuf; use std::process::Command; -use walkdir::WalkDir; + +#[cfg(not(feature = "bootstrap-self-test"))] +use std::collections::HashSet; use crate::builder::Kind; use crate::core::config::Target; @@ -31,6 +33,7 @@ pub struct Finder { // it might not yet be included in stage0. In such cases, we handle the targets missing from stage0 in this list. // // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap). +#[cfg(not(feature = "bootstrap-self-test"))] const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined ]; @@ -167,6 +170,7 @@ than building it. .map(|p| cmd_finder.must_have(p)) .or_else(|| cmd_finder.maybe_have("reuse")); + #[cfg(not(feature = "bootstrap-self-test"))] let stage0_supported_target_list: HashSet = output(Command::new(&build.config.initial_rustc).args(["--print", "target-list"])) .lines() @@ -193,11 +197,11 @@ than building it. continue; } - let target_str = target.to_string(); - // Ignore fake targets that are only used for unit tests in bootstrap. - if !["A-A", "B-B", "C-C"].contains(&target_str.as_str()) { + #[cfg(not(feature = "bootstrap-self-test"))] + { let mut has_target = false; + let target_str = target.to_string(); let missing_targets_hashset: HashSet<_> = STAGE0_MISSING_TARGETS.iter().map(|t| t.to_string()).collect(); @@ -226,7 +230,7 @@ than building it. target_filename.push(".json"); // Recursively traverse through nested directories. - let walker = WalkDir::new(custom_target_path).into_iter(); + let walker = walkdir::WalkDir::new(custom_target_path).into_iter(); for entry in walker.filter_map(|e| e.ok()) { has_target |= entry.file_name() == target_filename; } From 2949195d9a9728b388cc606cb03d7ee3e00f5e7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Mon, 3 Jun 2024 01:57:27 +0000 Subject: [PATCH 052/154] compiler-builtins: don't clear env vars for cargo invocation --- tests/run-make/compiler-builtins/rmake.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/run-make/compiler-builtins/rmake.rs b/tests/run-make/compiler-builtins/rmake.rs index f5da50ebb043..55962fa4ebc4 100644 --- a/tests/run-make/compiler-builtins/rmake.rs +++ b/tests/run-make/compiler-builtins/rmake.rs @@ -56,7 +56,6 @@ fn main() { "--target", &target, ]) - .env_clear() .env("PATH", path) .env("RUSTC", rustc) .env("RUSTFLAGS", "-Copt-level=0 -Cdebug-assertions=yes") From 6a84995fae01eb0ae18ef6bfc41b2979ca760447 Mon Sep 17 00:00:00 2001 From: Ross MacArthur Date: Tue, 4 Jun 2024 10:51:05 +0200 Subject: [PATCH 053/154] Add function `core::iter::chain` The addition of `core::iter::zip` (#82917) set a precedent for adding plain functions for iterator adaptors. Adding `chain` makes it a little easier to `chain` two iterators. ``` for (x, y) in chain(xs, ys) {} // vs. for (x, y) in xs.into_iter().chain(ys) {} ``` --- library/core/src/iter/adapters/chain.rs | 37 +++++++++++++++++++++-- library/core/src/iter/adapters/mod.rs | 3 ++ library/core/src/iter/mod.rs | 2 ++ library/core/tests/iter/adapters/chain.rs | 8 +++++ library/core/tests/lib.rs | 1 + 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs index bcaac2f42cf0..dad3d79acb18 100644 --- a/library/core/src/iter/adapters/chain.rs +++ b/library/core/src/iter/adapters/chain.rs @@ -4,8 +4,8 @@ use crate::ops::Try; /// An iterator that links two iterators together, in a chain. /// -/// This `struct` is created by [`Iterator::chain`]. See its documentation -/// for more. +/// This `struct` is created by [`chain`] or [`Iterator::chain`]. See their +/// documentation for more. /// /// # Examples /// @@ -38,6 +38,39 @@ impl Chain { } } +/// Converts the arguments to iterators and links them together, in a chain. +/// +/// See the documentation of [`Iterator::chain`] for more. +/// +/// # Examples +/// +/// ``` +/// #![feature(iter_chain)] +/// +/// use std::iter::chain; +/// +/// let a = [1, 2, 3]; +/// let b = [4, 5, 6]; +/// +/// let mut iter = chain(a, b); +/// +/// assert_eq!(iter.next(), Some(1)); +/// assert_eq!(iter.next(), Some(2)); +/// assert_eq!(iter.next(), Some(3)); +/// assert_eq!(iter.next(), Some(4)); +/// assert_eq!(iter.next(), Some(5)); +/// assert_eq!(iter.next(), Some(6)); +/// assert_eq!(iter.next(), None); +/// ``` +#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")] +pub fn chain(a: A, b: B) -> Chain +where + A: IntoIterator, + B: IntoIterator, +{ + Chain::new(a.into_iter(), b.into_iter()) +} + #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for Chain where diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index cc514bd914f1..05a5f2689056 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -41,6 +41,9 @@ pub use self::array_chunks::ArrayChunks; #[unstable(feature = "std_internals", issue = "none")] pub use self::by_ref_sized::ByRefSized; +#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")] +pub use self::chain::chain; + #[stable(feature = "iter_cloned", since = "1.1.0")] pub use self::cloned::Cloned; diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index 44fef3e145b7..921c75c85f16 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -428,6 +428,8 @@ pub use self::traits::{ DoubleEndedIterator, ExactSizeIterator, Extend, FromIterator, IntoIterator, Product, Sum, }; +#[unstable(feature = "iter_chain", reason = "recently added", issue = "125964")] +pub use self::adapters::chain; #[stable(feature = "iter_zip", since = "1.59.0")] pub use self::adapters::zip; #[unstable(feature = "iter_array_chunks", reason = "recently added", issue = "100450")] diff --git a/library/core/tests/iter/adapters/chain.rs b/library/core/tests/iter/adapters/chain.rs index b2429588de12..c93510df524c 100644 --- a/library/core/tests/iter/adapters/chain.rs +++ b/library/core/tests/iter/adapters/chain.rs @@ -2,6 +2,14 @@ use super::*; use core::iter::*; use core::num::NonZero; +#[test] +fn test_chain() { + let xs = [0, 1, 2, 3, 4, 5]; + let ys = [30, 40, 50, 60]; + let expected = [0, 1, 2, 3, 4, 5, 30, 40, 50, 60]; + assert_eq!(Vec::from_iter(chain(xs, ys)), expected); +} + #[test] fn test_iterator_chain() { let xs = [0, 1, 2, 3, 4, 5]; diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index e0f82c916635..20ff6fd7687f 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -75,6 +75,7 @@ #![feature(ip)] #![feature(iter_advance_by)] #![feature(iter_array_chunks)] +#![feature(iter_chain)] #![feature(iter_collect_into)] #![feature(iter_partition_in_place)] #![feature(iter_intersperse)] From 617e64c9e7233ec1f936b8e14c30037fc3f6a1be Mon Sep 17 00:00:00 2001 From: Sergi-Ferrez Date: Tue, 4 Jun 2024 13:49:39 +0200 Subject: [PATCH 054/154] Update code format and tests --- src/librustdoc/html/format.rs | 4 ++-- tests/rustdoc/async-fn.rs | 2 +- tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html | 3 +-- tests/rustdoc/decl-trailing-whitespace.declaration.html | 4 ++-- tests/rustdoc/inline_cross/impl_trait.rs | 2 +- tests/rustdoc/line-breaks.rs | 2 +- tests/rustdoc/reexports-priv.rs | 2 +- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index de92fb80b938..ff49f65ed08f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1431,7 +1431,7 @@ impl clean::FnDecl { cx: &Context<'_>, ) -> fmt::Result { let amp = if f.alternate() { "&" } else { "&" }; - + write!(f, "(")?; if let Some(n) = line_wrapping_indent && !self.inputs.values.is_empty() @@ -1483,7 +1483,7 @@ impl clean::FnDecl { if self.c_variadic { match line_wrapping_indent { - None => write!(f, "...")?, + None => write!(f, ", ...")?, Some(n) => write!(f, "{}...\n", Indent(n + 4))?, }; } diff --git a/tests/rustdoc/async-fn.rs b/tests/rustdoc/async-fn.rs index 010263f6ad31..4de5d8575b03 100644 --- a/tests/rustdoc/async-fn.rs +++ b/tests/rustdoc/async-fn.rs @@ -79,7 +79,7 @@ struct AsyncFdReadyGuard<'a, T> { x: &'a T } impl Foo { // @has async_fn/struct.Foo.html - // @has - '//*[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar ) -> impl Iterator' + // @has - '//*[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar, ) -> impl Iterator' pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator { [0].iter() } diff --git a/tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html b/tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html index 29c08c5bd5de..12c6bc214a72 100644 --- a/tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html +++ b/tests/rustdoc/decl-line-wrapping-empty-arg-list.decl.html @@ -1,2 +1 @@ -

pub fn create(
-) -> Padding00000000000000000000000000000000000000000000000000000000000000000000000000000000
\ No newline at end of file +
pub fn create() -> Padding00000000000000000000000000000000000000000000000000000000000000000000000000000000
\ No newline at end of file diff --git a/tests/rustdoc/decl-trailing-whitespace.declaration.html b/tests/rustdoc/decl-trailing-whitespace.declaration.html index 59c318c16f3b..0cc3f0fa244e 100644 --- a/tests/rustdoc/decl-trailing-whitespace.declaration.html +++ b/tests/rustdoc/decl-trailing-whitespace.declaration.html @@ -3,7 +3,7 @@ fn poll_write( self, cx: &mut Option<String>, - buf: &mut [usize] + buf: &mut [usize], ) -> Option<Result<usize, Error>>; fn poll_flush(self, cx: &mut Option<String>) -> Option<Result<(), Error>>; fn poll_close(self, cx: &mut Option<String>) -> Option<Result<(), Error>>; @@ -12,6 +12,6 @@ fn poll_write_vectored( self, cx: &mut Option<String>, - bufs: &[usize] + bufs: &[usize], ) -> Option<Result<usize, Error>> { ... } } \ No newline at end of file diff --git a/tests/rustdoc/inline_cross/impl_trait.rs b/tests/rustdoc/inline_cross/impl_trait.rs index 47e2c9dc76bc..19d1673f2eb9 100644 --- a/tests/rustdoc/inline_cross/impl_trait.rs +++ b/tests/rustdoc/inline_cross/impl_trait.rs @@ -11,7 +11,7 @@ pub use impl_trait_aux::func; // @has impl_trait/fn.func2.html // @has - '//pre[@class="rust item-decl"]' "func2(" // @has - '//pre[@class="rust item-decl"]' "_x: impl Deref> + Iterator," -// @has - '//pre[@class="rust item-decl"]' "_y: impl Iterator )" +// @has - '//pre[@class="rust item-decl"]' "_y: impl Iterator, )" // @!has - '//pre[@class="rust item-decl"]' 'where' pub use impl_trait_aux::func2; diff --git a/tests/rustdoc/line-breaks.rs b/tests/rustdoc/line-breaks.rs index 21aa3a03ce43..0f760d51973c 100644 --- a/tests/rustdoc/line-breaks.rs +++ b/tests/rustdoc/line-breaks.rs @@ -6,7 +6,7 @@ use std::ops::Add; // @matches foo/fn.function_with_a_really_long_name.html '//*[@class="rust item-decl"]//code' "\ // function_with_a_really_long_name\(\n\ // \ parameter_one: i32,\n\ -// \ parameter_two: i32\n\ +// \ parameter_two: i32,\n\ // \) -> Option$" pub fn function_with_a_really_long_name(parameter_one: i32, parameter_two: i32) -> Option { Some(parameter_one + parameter_two) diff --git a/tests/rustdoc/reexports-priv.rs b/tests/rustdoc/reexports-priv.rs index 1eee262d2330..97318a014105 100644 --- a/tests/rustdoc/reexports-priv.rs +++ b/tests/rustdoc/reexports-priv.rs @@ -98,7 +98,7 @@ pub mod outer { pub use reexports::foo; // @has 'foo/outer/inner/fn.foo_crate.html' '//pre[@class="rust item-decl"]' 'pub(crate) fn foo_crate()' pub(crate) use reexports::foo_crate; - // @has 'foo/outer/inner/fn.foo_super.html' '//pre[@class="rust item-decl"]' 'pub(in outer) fn foo_super( )' + // @has 'foo/outer/inner/fn.foo_super.html' '//pre[@class="rust item-decl"]' 'pub(in outer) fn foo_super()' pub(super) use::reexports::foo_super; // @!has 'foo/outer/inner/fn.foo_self.html' pub(self) use reexports::foo_self; From 744dc8c503debec5ce39f9529de80300ee1f7a2a Mon Sep 17 00:00:00 2001 From: Sergi-Ferrez Date: Tue, 4 Jun 2024 16:05:51 +0200 Subject: [PATCH 055/154] Use checked_sub --- src/librustdoc/html/format.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index ff49f65ed08f..4268fadd6c59 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -1439,7 +1439,7 @@ impl clean::FnDecl { write!(f, "\n{}", Indent(n + 4))?; } - let last_input_index = self.inputs.values.len() - 1; + let last_input_index = self.inputs.values.len().checked_sub(1); for (i, input) in self.inputs.values.iter().enumerate() { if let Some(selfty) = input.to_self() { match selfty { @@ -1473,11 +1473,12 @@ impl clean::FnDecl { write!(f, "{}: ", input.name)?; input.type_.print(cx).fmt(f)?; } - match line_wrapping_indent { - None if i == last_input_index => (), - None => write!(f, ", ")?, - Some(_n) if i == last_input_index => write!(f, ",\n")?, - Some(n) => write!(f, ",\n{}", Indent(n + 4))?, + match (line_wrapping_indent, last_input_index) { + (_, None) => (), + (None, Some(last_i)) if i != last_i => write!(f, ", ")?, + (None, Some(_)) => (), + (Some(n), Some(last_i)) if i != last_i => write!(f, ",\n{}", Indent(n + 4))?, + (Some(_), Some(_)) => write!(f, ",\n")?, } } From c7491a988597d52c4b59e3e98e1965ae4648d357 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 4 Jun 2024 19:55:29 +1000 Subject: [PATCH 056/154] Remove `tests/run-make-fulldeps/pretty-expanded` This was an ancient regression test for #12685, caused by `-Zunpretty=expanded` crashing on certain code produced by `#[derive(RustcEncodable)]`. --- .../pretty-expanded/Makefile | 4 --- .../pretty-expanded/input.rs | 25 ------------------- 2 files changed, 29 deletions(-) delete mode 100644 tests/run-make-fulldeps/pretty-expanded/Makefile delete mode 100644 tests/run-make-fulldeps/pretty-expanded/input.rs diff --git a/tests/run-make-fulldeps/pretty-expanded/Makefile b/tests/run-make-fulldeps/pretty-expanded/Makefile deleted file mode 100644 index 48199179ecef..000000000000 --- a/tests/run-make-fulldeps/pretty-expanded/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -include ../../run-make/tools.mk - -all: - $(RUSTC) -o $(TMPDIR)/input.expanded.rs -Zunpretty=expanded input.rs diff --git a/tests/run-make-fulldeps/pretty-expanded/input.rs b/tests/run-make-fulldeps/pretty-expanded/input.rs deleted file mode 100644 index 64ed97572ee9..000000000000 --- a/tests/run-make-fulldeps/pretty-expanded/input.rs +++ /dev/null @@ -1,25 +0,0 @@ -// #13544 - -#[derive(Debug)] -pub struct A; - -#[derive(Debug)] -pub struct B(isize); - -#[derive(Debug)] -pub struct C { - x: isize, -} - -#[derive(Debug)] -pub enum D {} - -#[derive(Debug)] -pub enum E { - y, -} - -#[derive(Debug)] -pub enum F { - z(isize), -} From 5e8df95dbb445b2891610a9e46ce31c2b615bc09 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 27 May 2024 13:01:16 +0000 Subject: [PATCH 057/154] Manual rustfmt --- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 58eb0c281798..5f73b3b618f5 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1419,8 +1419,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.dcx().span_delayed_bug( span, format!( - "instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?", - ), + "instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?", + ), ); } } From 14f9c63759b67ad725dbecb003bcb7752fc92d69 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 06:32:35 +0000 Subject: [PATCH 058/154] Show that it will pick up the entirely wrong function as a private candidate --- src/tools/tidy/src/ui_tests.rs | 2 +- ...3498.stderr => issue-53498.different_name.stderr} | 2 +- tests/ui/issues/issue-53498.rs | 9 ++++++++- tests/ui/issues/issue-53498.same_name.stderr | 12 ++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) rename tests/ui/issues/{issue-53498.stderr => issue-53498.different_name.stderr} (91%) create mode 100644 tests/ui/issues/issue-53498.same_name.stderr diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index cce0fb2c1a25..37ce335c9a3d 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: u32 = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1674; +const ISSUES_ENTRY_LIMIT: u32 = 1675; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/issues/issue-53498.stderr b/tests/ui/issues/issue-53498.different_name.stderr similarity index 91% rename from tests/ui/issues/issue-53498.stderr rename to tests/ui/issues/issue-53498.different_name.stderr index 61a1aedf5082..45ee858ac921 100644 --- a/tests/ui/issues/issue-53498.stderr +++ b/tests/ui/issues/issue-53498.different_name.stderr @@ -1,5 +1,5 @@ error[E0624]: associated function `foo` is private - --> $DIR/issue-53498.rs:16:27 + --> $DIR/issue-53498.rs:21:27 | LL | fn foo() {} | -------- private associated function defined here diff --git a/tests/ui/issues/issue-53498.rs b/tests/ui/issues/issue-53498.rs index 9e0437c46f4b..816d3f9e448f 100644 --- a/tests/ui/issues/issue-53498.rs +++ b/tests/ui/issues/issue-53498.rs @@ -1,3 +1,5 @@ +//@ revisions: same_name different_name + pub mod test { pub struct A; pub struct B; @@ -8,10 +10,15 @@ pub mod test { } impl Foo { + #[cfg(same_name)] fn foo() {} + #[cfg(different_name)] + fn bar() {} } } fn main() { - test::Foo::::foo(); //~ ERROR associated function `foo` is private + test::Foo::::foo(); + //[same_name]~^ ERROR associated function `foo` is private + //[different_name]~^^ ERROR associated function `foo` is private } diff --git a/tests/ui/issues/issue-53498.same_name.stderr b/tests/ui/issues/issue-53498.same_name.stderr new file mode 100644 index 000000000000..45ee858ac921 --- /dev/null +++ b/tests/ui/issues/issue-53498.same_name.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated function `foo` is private + --> $DIR/issue-53498.rs:21:27 + | +LL | fn foo() {} + | -------- private associated function defined here +... +LL | test::Foo::::foo(); + | ^^^ private associated function + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0624`. From 7d151fa3b015ad1dbac18933c58db3413a964534 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 27 May 2024 15:51:21 +0000 Subject: [PATCH 059/154] Turn a delayed bug back into a normal bug by winnowing private method candidates instead of assuming any candidate of the right name will apply. --- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 4 +-- compiler/rustc_hir_typeck/src/method/probe.rs | 28 ++++++++++++++----- .../issues/issue-53498.different_name.stderr | 13 +++++---- tests/ui/issues/issue-53498.rs | 2 +- 4 files changed, 32 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 5f73b3b618f5..4bd73dc6c942 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1072,7 +1072,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::ImplContainer => { if segments.len() == 1 { // `::assoc` will end up here, and so - // can `T::assoc`. It this came from an + // can `T::assoc`. If this came from an // inherent impl, we need to record the // `T` for posterity (see `UserSelfTy` for // details). @@ -1416,7 +1416,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { - self.dcx().span_delayed_bug( + self.dcx().span_bug( span, format!( "instantiate_value_path: (UFCS) {self_ty:?} was a subtype of {impl_ty:?} but now is not?", diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 12ced49f92ff..ab0f16bd87d0 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -41,6 +41,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{ use rustc_trait_selection::traits::query::CanonicalTyGoal; use rustc_trait_selection::traits::ObligationCtxt; use rustc_trait_selection::traits::{self, ObligationCause}; +use std::cell::Cell; use std::cell::RefCell; use std::cmp::max; use std::iter; @@ -76,8 +77,12 @@ pub(crate) struct ProbeContext<'a, 'tcx> { /// requested name (by edit distance) allow_similar_names: bool, + /// List of potential private candidates. Will be trimmed to ones that + /// actually apply and then the result inserted into `private_candidate` + private_candidates: Vec>, + /// Some(candidate) if there is a private candidate - private_candidate: Option<(DefKind, DefId)>, + private_candidate: Cell>, /// Collects near misses when the candidate functions are missing a `self` keyword and is only /// used for error reporting @@ -581,7 +586,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { orig_steps_var_values, steps, allow_similar_names: false, - private_candidate: None, + private_candidates: Vec::new(), + private_candidate: Cell::new(None), static_candidates: RefCell::new(Vec::new()), unsatisfied_predicates: RefCell::new(Vec::new()), scope_expr_id, @@ -593,7 +599,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.inherent_candidates.clear(); self.extension_candidates.clear(); self.impl_dups.clear(); - self.private_candidate = None; + self.private_candidates.clear(); + self.private_candidate.set(None); self.static_candidates.borrow_mut().clear(); self.unsatisfied_predicates.borrow_mut().clear(); } @@ -617,9 +624,8 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } else { self.extension_candidates.push(candidate); } - } else if self.private_candidate.is_none() { - self.private_candidate = - Some((candidate.item.kind.as_def_kind(), candidate.item.def_id)); + } else { + self.private_candidates.push(candidate); } } @@ -1171,7 +1177,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let mut possibly_unsatisfied_predicates = Vec::new(); for (kind, candidates) in - &[("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)] + [("inherent", &self.inherent_candidates), ("extension", &self.extension_candidates)] { debug!("searching {} candidates", kind); let res = self.consider_candidates( @@ -1185,6 +1191,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } + if self.private_candidate.get().is_none() { + if let Some(Ok(pick)) = + self.consider_candidates(self_ty, &self.private_candidates, &mut vec![], None) + { + self.private_candidate.set(Some((pick.item.kind.as_def_kind(), pick.item.def_id))); + } + } + // `pick_method` may be called twice for the same self_ty if no stable methods // match. Only extend once. if unstable_candidates.is_some() { diff --git a/tests/ui/issues/issue-53498.different_name.stderr b/tests/ui/issues/issue-53498.different_name.stderr index 45ee858ac921..fc765f2e75d3 100644 --- a/tests/ui/issues/issue-53498.different_name.stderr +++ b/tests/ui/issues/issue-53498.different_name.stderr @@ -1,12 +1,15 @@ -error[E0624]: associated function `foo` is private +error[E0599]: no function or associated item named `foo` found for struct `Foo` in the current scope --> $DIR/issue-53498.rs:21:27 | -LL | fn foo() {} - | -------- private associated function defined here +LL | pub struct Foo(T); + | ----------------- function or associated item `foo` not found for this struct ... LL | test::Foo::::foo(); - | ^^^ private associated function + | ^^^ function or associated item not found in `Foo` + | + = note: the function or associated item was found for + - `Foo` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0624`. +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/issues/issue-53498.rs b/tests/ui/issues/issue-53498.rs index 816d3f9e448f..64eb3a0c5fd4 100644 --- a/tests/ui/issues/issue-53498.rs +++ b/tests/ui/issues/issue-53498.rs @@ -20,5 +20,5 @@ pub mod test { fn main() { test::Foo::::foo(); //[same_name]~^ ERROR associated function `foo` is private - //[different_name]~^^ ERROR associated function `foo` is private + //[different_name]~^^ ERROR no function or associated item named `foo` found for struct `Foo` } From 7894a1148371e4d0fa665c183615a76f9e2ec656 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 09:26:40 +0000 Subject: [PATCH 060/154] Move tests to a more appropriate directory --- src/tools/tidy/src/ui_tests.rs | 2 +- tests/ui/{issues => privacy}/issue-53498.different_name.stderr | 0 tests/ui/{issues => privacy}/issue-53498.rs | 0 tests/ui/{issues => privacy}/issue-53498.same_name.stderr | 0 4 files changed, 1 insertion(+), 1 deletion(-) rename tests/ui/{issues => privacy}/issue-53498.different_name.stderr (100%) rename tests/ui/{issues => privacy}/issue-53498.rs (100%) rename tests/ui/{issues => privacy}/issue-53498.same_name.stderr (100%) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 37ce335c9a3d..f2eeda339d80 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -15,7 +15,7 @@ use std::path::{Path, PathBuf}; const ENTRY_LIMIT: u32 = 900; // FIXME: The following limits should be reduced eventually. -const ISSUES_ENTRY_LIMIT: u32 = 1675; +const ISSUES_ENTRY_LIMIT: u32 = 1672; const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[ "rs", // test source files diff --git a/tests/ui/issues/issue-53498.different_name.stderr b/tests/ui/privacy/issue-53498.different_name.stderr similarity index 100% rename from tests/ui/issues/issue-53498.different_name.stderr rename to tests/ui/privacy/issue-53498.different_name.stderr diff --git a/tests/ui/issues/issue-53498.rs b/tests/ui/privacy/issue-53498.rs similarity index 100% rename from tests/ui/issues/issue-53498.rs rename to tests/ui/privacy/issue-53498.rs diff --git a/tests/ui/issues/issue-53498.same_name.stderr b/tests/ui/privacy/issue-53498.same_name.stderr similarity index 100% rename from tests/ui/issues/issue-53498.same_name.stderr rename to tests/ui/privacy/issue-53498.same_name.stderr From 81895065bb541b9e79f402d2446c1c83243b37d0 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 09:32:53 +0000 Subject: [PATCH 061/154] Give test a more useful name --- src/tools/tidy/src/issues.txt | 1 - ...ferent_name.stderr => ufc-method-call.different_name.stderr} | 2 +- tests/ui/privacy/{issue-53498.rs => ufc-method-call.rs} | 0 ...-53498.same_name.stderr => ufc-method-call.same_name.stderr} | 2 +- 4 files changed, 2 insertions(+), 3 deletions(-) rename tests/ui/privacy/{issue-53498.different_name.stderr => ufc-method-call.different_name.stderr} (93%) rename tests/ui/privacy/{issue-53498.rs => ufc-method-call.rs} (100%) rename tests/ui/privacy/{issue-53498.same_name.stderr => ufc-method-call.same_name.stderr} (90%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 398a6fd0fbaa..a6ba8959f0c5 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -2445,7 +2445,6 @@ ui/issues/issue-53300.rs ui/issues/issue-53333.rs ui/issues/issue-53348.rs ui/issues/issue-53419.rs -ui/issues/issue-53498.rs ui/issues/issue-53568.rs ui/issues/issue-5358-1.rs ui/issues/issue-53728.rs diff --git a/tests/ui/privacy/issue-53498.different_name.stderr b/tests/ui/privacy/ufc-method-call.different_name.stderr similarity index 93% rename from tests/ui/privacy/issue-53498.different_name.stderr rename to tests/ui/privacy/ufc-method-call.different_name.stderr index fc765f2e75d3..80321b1c11cb 100644 --- a/tests/ui/privacy/issue-53498.different_name.stderr +++ b/tests/ui/privacy/ufc-method-call.different_name.stderr @@ -1,5 +1,5 @@ error[E0599]: no function or associated item named `foo` found for struct `Foo` in the current scope - --> $DIR/issue-53498.rs:21:27 + --> $DIR/ufc-method-call.rs:21:27 | LL | pub struct Foo(T); | ----------------- function or associated item `foo` not found for this struct diff --git a/tests/ui/privacy/issue-53498.rs b/tests/ui/privacy/ufc-method-call.rs similarity index 100% rename from tests/ui/privacy/issue-53498.rs rename to tests/ui/privacy/ufc-method-call.rs diff --git a/tests/ui/privacy/issue-53498.same_name.stderr b/tests/ui/privacy/ufc-method-call.same_name.stderr similarity index 90% rename from tests/ui/privacy/issue-53498.same_name.stderr rename to tests/ui/privacy/ufc-method-call.same_name.stderr index 45ee858ac921..c66ae0a6b252 100644 --- a/tests/ui/privacy/issue-53498.same_name.stderr +++ b/tests/ui/privacy/ufc-method-call.same_name.stderr @@ -1,5 +1,5 @@ error[E0624]: associated function `foo` is private - --> $DIR/issue-53498.rs:21:27 + --> $DIR/ufc-method-call.rs:21:27 | LL | fn foo() {} | -------- private associated function defined here From ffb1b2c14809ae5d15a078a9cce5299865d7dd73 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 28 May 2024 09:34:16 +0000 Subject: [PATCH 062/154] Add test description --- tests/ui/privacy/ufc-method-call.different_name.stderr | 2 +- tests/ui/privacy/ufc-method-call.rs | 6 ++++++ tests/ui/privacy/ufc-method-call.same_name.stderr | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/ui/privacy/ufc-method-call.different_name.stderr b/tests/ui/privacy/ufc-method-call.different_name.stderr index 80321b1c11cb..16496c480dd1 100644 --- a/tests/ui/privacy/ufc-method-call.different_name.stderr +++ b/tests/ui/privacy/ufc-method-call.different_name.stderr @@ -1,5 +1,5 @@ error[E0599]: no function or associated item named `foo` found for struct `Foo` in the current scope - --> $DIR/ufc-method-call.rs:21:27 + --> $DIR/ufc-method-call.rs:27:27 | LL | pub struct Foo(T); | ----------------- function or associated item `foo` not found for this struct diff --git a/tests/ui/privacy/ufc-method-call.rs b/tests/ui/privacy/ufc-method-call.rs index 64eb3a0c5fd4..525d9a9eee90 100644 --- a/tests/ui/privacy/ufc-method-call.rs +++ b/tests/ui/privacy/ufc-method-call.rs @@ -1,3 +1,9 @@ +//! This test used to report that the method call cannot +//! call the private method `Foo::foo`, even though the user +//! explicitly selected `Foo::foo`. This is because we only +//! looked for methods of the right name, without properly checking +//! the `Self` type + //@ revisions: same_name different_name pub mod test { diff --git a/tests/ui/privacy/ufc-method-call.same_name.stderr b/tests/ui/privacy/ufc-method-call.same_name.stderr index c66ae0a6b252..194ba42cbf98 100644 --- a/tests/ui/privacy/ufc-method-call.same_name.stderr +++ b/tests/ui/privacy/ufc-method-call.same_name.stderr @@ -1,5 +1,5 @@ error[E0624]: associated function `foo` is private - --> $DIR/ufc-method-call.rs:21:27 + --> $DIR/ufc-method-call.rs:27:27 | LL | fn foo() {} | -------- private associated function defined here From 2bad3d13926f5de344bb85ec58de6abf5e5d3475 Mon Sep 17 00:00:00 2001 From: Andrei Damian Date: Tue, 4 Jun 2024 18:49:13 +0300 Subject: [PATCH 063/154] Make deleting on LinkedList aware of the allocator --- library/alloc/src/collections/linked_list.rs | 4 +- .../src/collections/linked_list/tests.rs | 39 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 1c90c171a155..01510a614051 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1705,7 +1705,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> { unsafe { self.current = unlinked_node.as_ref().next; self.list.unlink_node(unlinked_node); - let unlinked_node = Box::from_raw(unlinked_node.as_ptr()); + let unlinked_node = Box::from_raw_in(unlinked_node.as_ptr(), &self.list.alloc); Some(unlinked_node.element) } } @@ -1946,7 +1946,7 @@ where if (self.pred)(&mut node.as_mut().element) { // `unlink_node` is okay with aliasing `element` references. self.list.unlink_node(node); - return Some(Box::from_raw(node.as_ptr()).element); + return Some(Box::from_raw_in(node.as_ptr(), &self.list.alloc).element); } } } diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs index 8dcd59d12d92..d3744c5a9d0c 100644 --- a/library/alloc/src/collections/linked_list/tests.rs +++ b/library/alloc/src/collections/linked_list/tests.rs @@ -1164,3 +1164,42 @@ fn test_drop_panic() { assert_eq!(unsafe { DROPS }, 8); } + +#[test] +fn test_allocator() { + use core::alloc::AllocError; + use core::alloc::Allocator; + use core::alloc::Layout; + use core::cell::Cell; + + struct A { + has_allocated: Cell, + has_deallocated: Cell, + } + + unsafe impl Allocator for A { + fn allocate(&self, layout: Layout) -> Result, AllocError> { + assert!(!self.has_allocated.get()); + self.has_allocated.set(true); + + Global.allocate(layout) + } + + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + assert!(!self.has_deallocated.get()); + self.has_deallocated.set(true); + + unsafe { Global.deallocate(ptr, layout) } + } + } + + let alloc = &A { has_allocated: Cell::new(false), has_deallocated: Cell::new(false) }; + { + let mut list = LinkedList::new_in(alloc); + list.push_back(5u32); + list.remove(0); + } + + assert!(alloc.has_allocated.get()); + assert!(alloc.has_deallocated.get()); +} From 874670399c43c58a6e21d46662979fb4fb8a0b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 1 Jun 2024 23:44:59 +0200 Subject: [PATCH 064/154] Orphanck: Consider opaque types to never cover type parameters --- .../src/traits/coherence.rs | 59 ++++++++----------- ...k-opaque-types-not-covering.classic.stderr | 21 +++++++ ...heck-opaque-types-not-covering.next.stderr | 21 +++++++ .../orphan-check-opaque-types-not-covering.rs | 31 ++++++++++ ...erence.stderr => coherence.classic.stderr} | 2 +- .../coherence.next.stderr | 14 +++++ tests/ui/type-alias-impl-trait/coherence.rs | 2 + 7 files changed, 114 insertions(+), 36 deletions(-) create mode 100644 tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr create mode 100644 tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr create mode 100644 tests/ui/coherence/orphan-check-opaque-types-not-covering.rs rename tests/ui/type-alias-impl-trait/{coherence.stderr => coherence.classic.stderr} (95%) create mode 100644 tests/ui/type-alias-impl-trait/coherence.next.stderr diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index ebdb032dc0e2..c81f5ac6e6ef 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -924,11 +924,12 @@ where } } - ty::Alias(kind @ (ty::Projection | ty::Inherent | ty::Weak), ..) => { - if ty.has_type_flags(ty::TypeFlags::HAS_TY_PARAM) { - bug!("unexpected ty param in alias ty"); - } - + // A rigid alias may normalize to anything. + // * If it references an infer var, placeholder or bound ty, it may + // normalize to that, so we have to treat it as an uncovered ty param. + // * Otherwise it may normalize to any non-type-generic type + // be it local or non-local. + ty::Alias(kind, _) => { if ty.has_type_flags( ty::TypeFlags::HAS_TY_PLACEHOLDER | ty::TypeFlags::HAS_TY_BOUND @@ -948,7 +949,24 @@ where } } } else { - ControlFlow::Continue(()) + // Regarding *opaque types* specifically, we choose to treat them as non-local, + // even those that appear within the same crate. This seems somewhat surprising + // at first, but makes sense when you consider that opaque types are supposed + // to hide the underlying type *within the same crate*. When an opaque type is + // used from outside the module where it is declared, it should be impossible to + // observe anything about it other than the traits that it implements. + // + // The alternative would be to look at the underlying type to determine whether + // or not the opaque type itself should be considered local. + // + // However, this could make it a breaking change to switch the underlying hidden + // type from a local type to a remote type. This would violate the rule that + // opaque types should be completely opaque apart from the traits that they + // implement, so we don't use this behavior. + // Addendum: Moreover, revealing the underlying type is likely to cause cycle + // errors as we rely on coherence / the specialization graph during typeck. + + self.found_non_local_ty(ty) } } @@ -990,35 +1008,6 @@ where // auto trait impl applies. There will never be multiple impls, so we can just // act as if it were a local type here. ty::CoroutineWitness(..) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)), - ty::Alias(ty::Opaque, ..) => { - // This merits some explanation. - // Normally, opaque types are not involved when performing - // coherence checking, since it is illegal to directly - // implement a trait on an opaque type. However, we might - // end up looking at an opaque type during coherence checking - // if an opaque type gets used within another type (e.g. as - // the type of a field) when checking for auto trait or `Sized` - // impls. This requires us to decide whether or not an opaque - // type should be considered 'local' or not. - // - // We choose to treat all opaque types as non-local, even - // those that appear within the same crate. This seems - // somewhat surprising at first, but makes sense when - // you consider that opaque types are supposed to hide - // the underlying type *within the same crate*. When an - // opaque type is used from outside the module - // where it is declared, it should be impossible to observe - // anything about it other than the traits that it implements. - // - // The alternative would be to look at the underlying type - // to determine whether or not the opaque type itself should - // be considered local. However, this could make it a breaking change - // to switch the underlying ('defining') type from a local type - // to a remote type. This would violate the rule that opaque - // types should be completely opaque apart from the traits - // that they implement, so we don't use this behavior. - self.found_non_local_ty(ty) - } }; // A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so // the first type we visit is always the self type. diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr new file mode 100644 index 000000000000..44f76f321cf1 --- /dev/null +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.classic.stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 + | +LL | impl foreign::Trait0 for Identity {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 + +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 + | +LL | impl foreign::Trait1 for Opaque {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr new file mode 100644 index 000000000000..44f76f321cf1 --- /dev/null +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.next.stderr @@ -0,0 +1,21 @@ +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:17:6 + | +LL | impl foreign::Trait0 for Identity {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 + +error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + --> $DIR/orphan-check-opaque-types-not-covering.rs:26:6 + | +LL | impl foreign::Trait1 for Opaque {} + | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`) + | + = 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 + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0210`. diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs new file mode 100644 index 000000000000..8dc02b081c51 --- /dev/null +++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs @@ -0,0 +1,31 @@ +// Opaque types never cover type parameters. + +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver + +//@ aux-crate:foreign=parametrized-trait.rs +//@ edition:2021 + +#![feature(type_alias_impl_trait)] + +type Identity = impl Sized; + +fn define_identity(x: T) -> Identity { + x +} + +impl foreign::Trait0 for Identity {} +//~^ ERROR type parameter `T` must be covered by another type + +type Opaque = impl Sized; + +fn define_local() -> Opaque { + Local +} + +impl foreign::Trait1 for Opaque {} +//~^ ERROR type parameter `T` must be covered by another type + +struct Local; + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/coherence.stderr b/tests/ui/type-alias-impl-trait/coherence.classic.stderr similarity index 95% rename from tests/ui/type-alias-impl-trait/coherence.stderr rename to tests/ui/type-alias-impl-trait/coherence.classic.stderr index 266a532a1db1..ff059bc5806d 100644 --- a/tests/ui/type-alias-impl-trait/coherence.stderr +++ b/tests/ui/type-alias-impl-trait/coherence.classic.stderr @@ -1,5 +1,5 @@ error[E0117]: only traits defined in the current crate can be implemented for arbitrary types - --> $DIR/coherence.rs:14:1 + --> $DIR/coherence.rs:16:1 | LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- diff --git a/tests/ui/type-alias-impl-trait/coherence.next.stderr b/tests/ui/type-alias-impl-trait/coherence.next.stderr new file mode 100644 index 000000000000..dab2786c1f0f --- /dev/null +++ b/tests/ui/type-alias-impl-trait/coherence.next.stderr @@ -0,0 +1,14 @@ +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/coherence.rs:16:1 + | +LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------- + | | | + | | `AliasOfForeignType<()>` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0117`. diff --git a/tests/ui/type-alias-impl-trait/coherence.rs b/tests/ui/type-alias-impl-trait/coherence.rs index 641c0fac17a6..760e5210c5b7 100644 --- a/tests/ui/type-alias-impl-trait/coherence.rs +++ b/tests/ui/type-alias-impl-trait/coherence.rs @@ -1,4 +1,6 @@ //@ aux-build:foreign-crate.rs +//@ revisions: classic next +//@[next] compile-flags: -Znext-solver #![feature(type_alias_impl_trait)] extern crate foreign_crate; From 68b0b86c5b703f11e4fa139cf60c9addb30dacb0 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 24 Apr 2024 18:53:56 -0300 Subject: [PATCH 065/154] Add unsafe extern blocks failing tests --- .../rust-2024/unsafe-extern-blocks/extern-items.rs | 12 ++++++++++++ .../unsafe-extern-blocks/extern-items.stderr | 8 ++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/extern-items.stderr diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs new file mode 100644 index 000000000000..de5947fc07b0 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs @@ -0,0 +1,12 @@ +extern "C" { + static TEST1: i32; + fn test1(i: i32); +} + +unsafe extern "C" { + //~^ ERROR: extern block cannot be declared unsafe + static TEST2: i32; + fn test2(i: i32); +} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.stderr new file mode 100644 index 000000000000..d9585ed3db66 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.stderr @@ -0,0 +1,8 @@ +error: extern block cannot be declared unsafe + --> $DIR/extern-items.rs:6:1 + | +LL | unsafe extern "C" { + | ^^^^^^ + +error: aborting due to 1 previous error + From 6d670b74e59de5e2f12e0d19b46b7939e4cd4a31 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 24 Apr 2024 19:10:14 -0300 Subject: [PATCH 066/154] Allow unsafe extern on all editions --- compiler/rustc_ast_passes/src/ast_validation.rs | 5 +---- tests/ui/parser/unsafe-foreign-mod-2.rs | 5 ++--- tests/ui/parser/unsafe-foreign-mod-2.stderr | 12 +++--------- tests/ui/parser/unsafe-foreign-mod.rs | 6 +++--- tests/ui/parser/unsafe-foreign-mod.stderr | 8 -------- .../rust-2024/unsafe-extern-blocks/extern-items.rs | 3 ++- .../unsafe-extern-blocks/extern-items.stderr | 8 -------- 7 files changed, 11 insertions(+), 36 deletions(-) delete mode 100644 tests/ui/parser/unsafe-foreign-mod.stderr delete mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/extern-items.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 435b0b6a9565..c0011fd9c45e 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1016,15 +1016,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. } - ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => { + ItemKind::ForeignMod(ForeignMod { abi, .. }) => { let old_item = mem::replace(&mut self.extern_mod, Some(item)); self.visibility_not_permitted( &item.vis, errors::VisibilityNotPermittedNote::IndividualForeignItems, ); - if let &Safety::Unsafe(span) = safety { - self.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" }); - } if abi.is_none() { self.maybe_lint_missing_abi(item.span, item.id); } diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs index 77856fb67340..c0994090eff4 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.rs +++ b/tests/ui/parser/unsafe-foreign-mod-2.rs @@ -1,8 +1,7 @@ extern "C" unsafe { - //~^ ERROR expected `{`, found keyword `unsafe` - //~| ERROR extern block cannot be declared unsafe + //~^ ERROR expected `{`, found keyword `unsafe` unsafe fn foo(); - //~^ ERROR functions in `extern` blocks cannot have qualifiers + //~^ ERROR functions in `extern` blocks cannot have qualifiers } fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr index fc05184f018f..620d042540ec 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.stderr +++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr @@ -4,20 +4,14 @@ error: expected `{`, found keyword `unsafe` LL | extern "C" unsafe { | ^^^^^^ expected `{` -error: extern block cannot be declared unsafe - --> $DIR/unsafe-foreign-mod-2.rs:1:12 - | -LL | extern "C" unsafe { - | ^^^^^^ - error: functions in `extern` blocks cannot have qualifiers - --> $DIR/unsafe-foreign-mod-2.rs:4:5 + --> $DIR/unsafe-foreign-mod-2.rs:3:5 | LL | extern "C" unsafe { | ----------------- in this `extern` block -... +LL | LL | unsafe fn foo(); | ^^^^^^ help: remove this qualifier -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/unsafe-foreign-mod.rs b/tests/ui/parser/unsafe-foreign-mod.rs index eab134a4a4de..26015a3c4445 100644 --- a/tests/ui/parser/unsafe-foreign-mod.rs +++ b/tests/ui/parser/unsafe-foreign-mod.rs @@ -1,5 +1,5 @@ -unsafe extern "C" { - //~^ ERROR extern block cannot be declared unsafe -} +//@ build-pass + +unsafe extern "C" {} fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr deleted file mode 100644 index 77f6e93be10b..000000000000 --- a/tests/ui/parser/unsafe-foreign-mod.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: extern block cannot be declared unsafe - --> $DIR/unsafe-foreign-mod.rs:1:1 - | -LL | unsafe extern "C" { - | ^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs index de5947fc07b0..fd2cd29fd748 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs @@ -1,10 +1,11 @@ +//@ build-pass + extern "C" { static TEST1: i32; fn test1(i: i32); } unsafe extern "C" { - //~^ ERROR: extern block cannot be declared unsafe static TEST2: i32; fn test2(i: i32); } diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.stderr deleted file mode 100644 index d9585ed3db66..000000000000 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: extern block cannot be declared unsafe - --> $DIR/extern-items.rs:6:1 - | -LL | unsafe extern "C" { - | ^^^^^^ - -error: aborting due to 1 previous error - From 46cd80b691f0e127076b6dcd1bf9285c3e608d4a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 25 Apr 2024 16:14:22 -0300 Subject: [PATCH 067/154] Test that unsafe extern defines unsafe fns --- .../extern-items-unsafe.edition2021.stderr | 11 ++++++++++ .../extern-items-unsafe.edition2024.stderr | 11 ++++++++++ .../extern-items-unsafe.rs | 21 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr new file mode 100644 index 000000000000..a94f8d742360 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block + --> $DIR/extern-items-unsafe.rs:11:5 + | +LL | test1(i); + | ^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr new file mode 100644 index 000000000000..c187dac1152b --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block + --> $DIR/extern-items-unsafe.rs:11:5 + | +LL | test1(i); + | ^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs new file mode 100644 index 000000000000..70f3c0afe7c9 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs @@ -0,0 +1,21 @@ +//@ revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 +//@[edition2024] compile-flags: -Zunstable-options + +unsafe extern "C" { + fn test1(i: i32); +} + +fn test2(i: i32) { + test1(i); + //~^ ERROR: call to unsafe function `test1` is unsafe +} + +fn test3(i: i32) { + unsafe { + test1(i); + } +} + +fn main() {} From 3ba8de0b601ee1eaae710510ee8b0b8a9dbd78d8 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 21 May 2024 12:27:21 -0300 Subject: [PATCH 068/154] Make extern blocks without unsafe warn in edition 2024 --- .../rustc_ast_passes/src/ast_validation.rs | 15 +++++++-- compiler/rustc_lint/messages.ftl | 2 ++ .../rustc_lint/src/context/diagnostics.rs | 3 ++ compiler/rustc_lint/src/lints.rs | 4 +++ compiler/rustc_lint_defs/src/builtin.rs | 31 +++++++++++++++++++ compiler/rustc_lint_defs/src/lib.rs | 1 + .../extern-items.edition2024.stderr | 14 +++++++++ .../unsafe-extern-blocks/extern-items.rs | 7 ++++- tests/ui/unpretty/expanded-exhaustive.rs | 4 +-- tests/ui/unpretty/expanded-exhaustive.stdout | 4 +-- 10 files changed, 78 insertions(+), 7 deletions(-) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index c0011fd9c45e..7e1094da2029 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -15,7 +15,8 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_feature::Features; use rustc_parse::validate_attr; use rustc_session::lint::builtin::{ - DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY, + DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN, + PATTERNS_IN_FNS_WITHOUT_BODY, }; use rustc_session::lint::{BuiltinLintDiag, LintBuffer}; use rustc_session::Session; @@ -1016,12 +1017,22 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; // Avoid visiting again. } - ItemKind::ForeignMod(ForeignMod { abi, .. }) => { + ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => { let old_item = mem::replace(&mut self.extern_mod, Some(item)); self.visibility_not_permitted( &item.vis, errors::VisibilityNotPermittedNote::IndividualForeignItems, ); + + if &Safety::Default == safety { + self.lint_buffer.buffer_lint( + MISSING_UNSAFE_ON_EXTERN, + item.id, + item.span, + BuiltinLintDiag::MissingUnsafeOnExtern, + ); + } + if abi.is_none() { self.maybe_lint_missing_abi(item.span, item.id); } diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index fb71cb601402..bb6ad7c945b2 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -462,6 +462,8 @@ lint_metavariable_wrong_operator = meta-variable repeats with different Kleene o lint_missing_fragment_specifier = missing fragment specifier +lint_missing_unsafe_on_extern = extern blocks should be unsafe + lint_mixed_script_confusables = the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables .includes_note = the usage includes {$includes} diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index 26f34486a3de..f824e02dcf9d 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -205,6 +205,9 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & }; lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag); } + BuiltinLintDiag::MissingUnsafeOnExtern => { + lints::MissingUnsafeOnExtern.decorate_lint(diag); + } BuiltinLintDiag::SingleUseLifetime { param_span, use_span: Some((use_span, elide)), diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 84d46ef3b65d..01b455c588ba 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2738,6 +2738,10 @@ pub enum DeprecatedWhereClauseLocationSugg { }, } +#[derive(LintDiagnostic)] +#[diag(lint_missing_unsafe_on_extern)] +pub struct MissingUnsafeOnExtern; + #[derive(LintDiagnostic)] #[diag(lint_single_use_lifetime)] pub struct SingleUseLifetime { diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a3044489fdce..b4a34b1407da 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -66,6 +66,7 @@ declare_lint_pass! { META_VARIABLE_MISUSE, MISSING_ABI, MISSING_FRAGMENT_SPECIFIER, + MISSING_UNSAFE_ON_EXTERN, MUST_NOT_SUSPEND, NAMED_ARGUMENTS_USED_POSITIONALLY, NEVER_TYPE_FALLBACK_FLOWING_INTO_UNSAFE, @@ -4851,3 +4852,33 @@ declare_lint! { reference: "issue #27970 ", }; } + +declare_lint! { + /// The `missing_unsafe_on_extern` lint detects missing unsafe keyword on extern declarations. + /// + /// ### Example + /// + /// ```rust,edition2024 + /// extern "C" { + /// fn foo(_: i32); + /// } + /// + /// fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Declaring extern items, even without ever using them, can cause Undefined Behavior. We + /// should consider all sources of Undefined Behavior to be unsafe. + /// + /// This is a [future-incompatible] lint to transition this to a + /// hard error in the future. + /// + /// [future-incompatible]: ../index.md#future-incompatible-lints + pub MISSING_UNSAFE_ON_EXTERN, + Allow, + "detects missing unsafe keyword on extern declarations", + @edition Edition2024 => Warn; +} diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index c8a9fb02bf2e..0f13046923eb 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -630,6 +630,7 @@ pub enum BuiltinLintDiag { UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), DeprecatedWhereclauseLocation(Span, Option<(Span, String)>), + MissingUnsafeOnExtern, SingleUseLifetime { /// Span of the parameter which declares this lifetime. param_span: Span, diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr new file mode 100644 index 000000000000..b19369c0a551 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr @@ -0,0 +1,14 @@ +warning: extern blocks should be unsafe + --> $DIR/extern-items.rs:7:1 + | +LL | / extern "C" { +LL | | +LL | | static TEST1: i32; +LL | | fn test1(i: i32); +LL | | } + | |_^ + | + = note: `#[warn(missing_unsafe_on_extern)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs index fd2cd29fd748..dfb851e276d4 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs @@ -1,6 +1,11 @@ -//@ build-pass +//@ revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 +//@[edition2024] compile-flags: -Zunstable-options +//@ check-pass extern "C" { + //[edition2024]~^ WARN extern blocks should be unsafe [missing_unsafe_on_extern] static TEST1: i32; fn test1(i: i32); } diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 6aa032d7ed83..29472df897a1 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -473,8 +473,8 @@ mod items { /// ItemKind::ForeignMod mod item_foreign_mod { - extern "C++" {} - extern {} + unsafe extern "C++" {} + unsafe extern {} } /// ItemKind::GlobalAsm diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 8737063bf3cc..0a09a3f6a423 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -451,8 +451,8 @@ mod items { mod item_mod { } /// ItemKind::ForeignMod mod item_foreign_mod { - extern "C++" {} - extern {} + unsafe extern "C++" {} + unsafe extern {} } /// ItemKind::GlobalAsm mod item_global_asm { From bbddc9b58f3b2fcf1b624c2d0cabd49461f94575 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 26 Apr 2024 18:35:54 -0300 Subject: [PATCH 069/154] Allow using unsafe on functions inside extern blocks --- .../rustc_ast_passes/src/ast_validation.rs | 6 +----- tests/ui/parser/fn-header-semantic-fail.rs | 6 +++--- .../ui/parser/fn-header-semantic-fail.stderr | 20 +----------------- .../ui/parser/no-const-fn-in-extern-block.rs | 1 - .../parser/no-const-fn-in-extern-block.stderr | 11 +--------- tests/ui/parser/unsafe-foreign-mod-2.rs | 1 - tests/ui/parser/unsafe-foreign-mod-2.stderr | 11 +--------- .../unsafe-items.edition2021.stderr | 11 ++++++++++ .../unsafe-items.edition2024.stderr | 11 ++++++++++ .../unsafe-extern-blocks/unsafe-items.rs | 21 +++++++++++++++++++ 10 files changed, 50 insertions(+), 49 deletions(-) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 7e1094da2029..b405e8885611 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -519,7 +519,7 @@ impl<'a> AstValidator<'a> { fn check_foreign_fn_headerless( &self, // Deconstruct to ensure exhaustiveness - FnHeader { safety, coroutine_kind, constness, ext }: FnHeader, + FnHeader { safety: _, coroutine_kind, constness, ext }: FnHeader, ) { let report_err = |span| { self.dcx().emit_err(errors::FnQualifierInExtern { @@ -527,10 +527,6 @@ impl<'a> AstValidator<'a> { block: self.current_extern_span(), }); }; - match safety { - Safety::Unsafe(span) => report_err(span), - Safety::Default => (), - } match coroutine_kind { Some(knd) => report_err(knd.span()), None => (), diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs index 6ed173b6854d..3b98433cdd82 100644 --- a/tests/ui/parser/fn-header-semantic-fail.rs +++ b/tests/ui/parser/fn-header-semantic-fail.rs @@ -44,11 +44,11 @@ fn main() { extern "C" { async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers - unsafe fn fe2(); //~ ERROR functions in `extern` blocks cannot have qualifiers + unsafe fn fe2(); const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers - const async unsafe extern "C" fn fe5(); //~ ERROR functions in `extern` blocks - //~| ERROR functions in `extern` blocks + const async unsafe extern "C" fn fe5(); + //~^ ERROR functions in `extern` blocks //~| ERROR functions in `extern` blocks //~| ERROR functions in `extern` blocks //~| ERROR functions cannot be both `const` and `async` diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index cfc54839eb75..dc2a216754d2 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -78,15 +78,6 @@ LL | extern "C" { LL | async fn fe1(); | ^^^^^ help: remove this qualifier -error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:47:9 - | -LL | extern "C" { - | ---------- in this `extern` block -LL | async fn fe1(); -LL | unsafe fn fe2(); - | ^^^^^^ help: remove this qualifier - error: functions in `extern` blocks cannot have qualifiers --> $DIR/fn-header-semantic-fail.rs:48:9 | @@ -105,15 +96,6 @@ LL | extern "C" { LL | extern "C" fn fe4(); | ^^^^^^^^^^ help: remove this qualifier -error: functions in `extern` blocks cannot have qualifiers - --> $DIR/fn-header-semantic-fail.rs:50:21 - | -LL | extern "C" { - | ---------- in this `extern` block -... -LL | const async unsafe extern "C" fn fe5(); - | ^^^^^^ help: remove this qualifier - error: functions in `extern` blocks cannot have qualifiers --> $DIR/fn-header-semantic-fail.rs:50:15 | @@ -150,6 +132,6 @@ LL | const async unsafe extern "C" fn fe5(); | | `async` because of this | `const` because of this -error: aborting due to 17 previous errors +error: aborting due to 15 previous errors For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/parser/no-const-fn-in-extern-block.rs b/tests/ui/parser/no-const-fn-in-extern-block.rs index d6c578681ccc..1993124edc39 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.rs +++ b/tests/ui/parser/no-const-fn-in-extern-block.rs @@ -3,7 +3,6 @@ extern "C" { //~^ ERROR functions in `extern` blocks cannot have qualifiers const unsafe fn bar(); //~^ ERROR functions in `extern` blocks cannot have qualifiers - //~| ERROR functions in `extern` blocks cannot have qualifiers } fn main() {} diff --git a/tests/ui/parser/no-const-fn-in-extern-block.stderr b/tests/ui/parser/no-const-fn-in-extern-block.stderr index 948ce669112c..2dec6f769310 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.stderr +++ b/tests/ui/parser/no-const-fn-in-extern-block.stderr @@ -6,15 +6,6 @@ LL | extern "C" { LL | const fn foo(); | ^^^^^ help: remove this qualifier -error: functions in `extern` blocks cannot have qualifiers - --> $DIR/no-const-fn-in-extern-block.rs:4:11 - | -LL | extern "C" { - | ---------- in this `extern` block -... -LL | const unsafe fn bar(); - | ^^^^^^ help: remove this qualifier - error: functions in `extern` blocks cannot have qualifiers --> $DIR/no-const-fn-in-extern-block.rs:4:5 | @@ -24,5 +15,5 @@ LL | extern "C" { LL | const unsafe fn bar(); | ^^^^^ help: remove this qualifier -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs index c0994090eff4..6d339cd90881 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.rs +++ b/tests/ui/parser/unsafe-foreign-mod-2.rs @@ -1,7 +1,6 @@ extern "C" unsafe { //~^ ERROR expected `{`, found keyword `unsafe` unsafe fn foo(); - //~^ ERROR functions in `extern` blocks cannot have qualifiers } fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr index 620d042540ec..0625e3362ed7 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.stderr +++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr @@ -4,14 +4,5 @@ error: expected `{`, found keyword `unsafe` LL | extern "C" unsafe { | ^^^^^^ expected `{` -error: functions in `extern` blocks cannot have qualifiers - --> $DIR/unsafe-foreign-mod-2.rs:3:5 - | -LL | extern "C" unsafe { - | ----------------- in this `extern` block -LL | -LL | unsafe fn foo(); - | ^^^^^^ help: remove this qualifier - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr new file mode 100644 index 000000000000..67e582c7c565 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block + --> $DIR/unsafe-items.rs:17:5 + | +LL | test1(i); + | ^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr new file mode 100644 index 000000000000..8a9410f8f135 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr @@ -0,0 +1,11 @@ +error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block + --> $DIR/unsafe-items.rs:17:5 + | +LL | test1(i); + | ^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs new file mode 100644 index 000000000000..4b6d077e9877 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs @@ -0,0 +1,21 @@ +//@ revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 +//@[edition2024] compile-flags: -Zunstable-options + +unsafe extern "C" { + unsafe fn test1(i: i32); +} + +fn test2(i: i32) { + unsafe { + test1(i); + } +} + +fn test3(i: i32) { + test1(i); + //~^ ERROR: call to unsafe function `test1` is unsafe +} + +fn main() {} From 2a377122dd41291747153ac82289e34a72275138 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 23 May 2024 10:01:05 -0300 Subject: [PATCH 070/154] Handle safety keyword for extern block inner items --- compiler/rustc_ast/src/ast.rs | 4 +++ compiler/rustc_ast/src/mut_visit.rs | 8 +++++- compiler/rustc_ast/src/token.rs | 2 ++ compiler/rustc_ast/src/visit.rs | 7 +++++- compiler/rustc_ast_lowering/src/item.rs | 25 +++++++++++++------ compiler/rustc_ast_lowering/src/lib.rs | 2 +- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 1 + .../rustc_ast_pretty/src/pprust/state/item.rs | 8 +++++- compiler/rustc_hir/src/hir.rs | 14 +++++------ compiler/rustc_hir/src/intravisit.rs | 6 +++-- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 9 ++++--- .../src/collect/resolve_bound_vars.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- .../rustc_hir_analysis/src/hir_wf_check.rs | 2 +- compiler/rustc_hir_pretty/src/lib.rs | 7 +++--- compiler/rustc_lint/src/types.rs | 6 ++--- compiler/rustc_middle/src/hir/map/mod.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 21 ++++++++++++++-- compiler/rustc_parse/src/parser/mod.rs | 2 ++ compiler/rustc_resolve/src/def_collector.rs | 9 ++++--- compiler/rustc_span/src/symbol.rs | 1 + src/librustdoc/clean/mod.rs | 8 ++++-- .../clippy/clippy_utils/src/ast_utils.rs | 4 ++- src/tools/rustfmt/src/utils.rs | 1 + tests/pretty/hir-fn-variadic.pp | 2 +- tests/ui/async-await/no-async-const.rs | 2 +- tests/ui/async-await/no-async-const.stderr | 4 +-- tests/ui/coroutine/async_gen_fn.none.stderr | 4 +-- tests/ui/coroutine/async_gen_fn.rs | 2 +- tests/ui/coroutine/gen_fn.none.stderr | 4 +-- tests/ui/coroutine/gen_fn.rs | 2 +- tests/ui/parser/duplicate-visibility.rs | 4 +-- tests/ui/parser/duplicate-visibility.stderr | 4 +-- tests/ui/parser/issues/issue-76437-async.rs | 2 +- .../ui/parser/issues/issue-76437-async.stderr | 4 +-- .../parser/issues/issue-76437-const-async.rs | 2 +- .../issues/issue-76437-const-async.stderr | 4 +-- tests/ui/parser/issues/issue-76437-const.rs | 2 +- .../ui/parser/issues/issue-76437-const.stderr | 4 +-- tests/ui/parser/issues/issue-86895.rs | 2 +- tests/ui/parser/issues/issue-86895.stderr | 4 +-- .../const-async-const.rs | 4 +-- .../const-async-const.stderr | 4 +-- .../issues/issue-87694-duplicated-pub.rs | 4 +-- .../issues/issue-87694-duplicated-pub.stderr | 4 +-- .../issues/issue-87694-misplaced-pub.rs | 4 +-- .../issues/issue-87694-misplaced-pub.stderr | 4 +-- .../unsafe-extern-blocks/safe-items.rs | 15 +++++++++++ 52 files changed, 168 insertions(+), 84 deletions(-) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 7a45d909d077..042c31fc70f7 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2501,6 +2501,8 @@ pub enum IsAuto { pub enum Safety { /// `unsafe` an item is explicitly marked as `unsafe`. Unsafe(Span), + /// `safe` an item is explicitly marked as `safe`. + Safe(Span), /// Default means no value was provided, it will take a default value given the context in /// which is used. Default, @@ -3171,6 +3173,7 @@ pub struct StaticItem { #[derive(Clone, Encodable, Decodable, Debug)] pub struct StaticForeignItem { pub ty: P, + pub safety: Safety, pub mutability: Mutability, pub expr: Option>, } @@ -3179,6 +3182,7 @@ impl From for StaticForeignItem { fn from(static_item: StaticItem) -> StaticForeignItem { StaticForeignItem { ty: static_item.ty, + safety: Safety::Default, mutability: static_item.mutability, expr: static_item.expr, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 5c581c270e49..c6814df28400 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -862,6 +862,7 @@ fn visit_defaultness(defaultness: &mut Defaultness, vis: &mut T) fn visit_safety(safety: &mut Safety, vis: &mut T) { match safety { Safety::Unsafe(span) => vis.visit_span(span), + Safety::Safe(span) => vis.visit_span(span), Safety::Default => {} } } @@ -1289,7 +1290,12 @@ pub fn noop_flat_map_item( impl NoopVisitItemKind for ForeignItemKind { fn noop_visit(&mut self, visitor: &mut impl MutVisitor) { match self { - ForeignItemKind::Static(box StaticForeignItem { ty, mutability: _, expr }) => { + ForeignItemKind::Static(box StaticForeignItem { + ty, + mutability: _, + expr, + safety: _, + }) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 099a6096d0b5..109c401bb6a2 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -210,6 +210,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: IdentIsRaw) -> boo kw::Unsafe, kw::While, kw::Yield, + kw::Safe, kw::Static, ] .contains(&name) @@ -577,6 +578,7 @@ impl Token { kw::Impl, kw::Unsafe, kw::Const, + kw::Safe, kw::Static, kw::Union, kw::Macro, diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index b2f3b27c77e9..ccf9f99757e3 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -658,7 +658,12 @@ impl WalkItemKind for ForeignItemKind { ) -> V::Result { let &Item { id, span, ident, ref vis, .. } = item; match self { - ForeignItemKind::Static(box StaticForeignItem { ty, mutability: _, expr }) => { + ForeignItemKind::Static(box StaticForeignItem { + ty, + mutability: _, + expr, + safety: _, + }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index a15449409df3..70bf74e5234d 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -388,7 +388,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ImplPolarity::Negative(s) => ImplPolarity::Negative(self.lower_span(*s)), }; hir::ItemKind::Impl(self.arena.alloc(hir::Impl { - safety: self.lower_safety(*safety), + safety: self.lower_safety(*safety, hir::Safety::Safe), polarity, defaultness, defaultness_span, @@ -418,7 +418,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let items = this.arena.alloc_from_iter( items.iter().map(|item| this.lower_trait_item_ref(item)), ); - let safety = this.lower_safety(*safety); + let safety = this.lower_safety(*safety, hir::Safety::Safe); (safety, items, bounds) }, ); @@ -660,13 +660,21 @@ impl<'hir> LoweringContext<'_, 'hir> { this.lower_fn_params_to_names(fdec), ) }); + let safety = self.lower_safety(sig.header.safety, hir::Safety::Unsafe); - hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) + hir::ForeignItemKind::Fn(fn_dec, fn_args, generics, safety) } - ForeignItemKind::Static(box StaticForeignItem { ty, mutability, expr: _ }) => { + ForeignItemKind::Static(box StaticForeignItem { + ty, + mutability, + expr: _, + safety, + }) => { let ty = self .lower_ty(ty, ImplTraitContext::Disallowed(ImplTraitPosition::StaticTy)); - hir::ForeignItemKind::Static(ty, *mutability) + let safety = self.lower_safety(*safety, hir::Safety::Unsafe); + + hir::ForeignItemKind::Static(ty, *mutability, safety) } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::MacCall(_) => panic!("macro shouldn't exist here"), @@ -1360,7 +1368,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::IsAsync::NotAsync }; hir::FnHeader { - safety: self.lower_safety(h.safety), + safety: self.lower_safety(h.safety, hir::Safety::Safe), asyncness: asyncness, constness: self.lower_constness(h.constness), abi: self.lower_extern(h.ext), @@ -1410,10 +1418,11 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - pub(super) fn lower_safety(&mut self, s: Safety) -> hir::Safety { + pub(super) fn lower_safety(&mut self, s: Safety, default: hir::Safety) -> hir::Safety { match s { Safety::Unsafe(_) => hir::Safety::Unsafe, - Safety::Default => hir::Safety::Safe, + Safety::Default => default, + Safety::Safe(_) => hir::Safety::Safe, } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5a80fa803f84..023dc6d52c3e 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1321,7 +1321,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); hir::TyKind::BareFn(self.arena.alloc(hir::BareFnTy { generic_params, - safety: self.lower_safety(f.safety), + safety: self.lower_safety(f.safety, hir::Safety::Safe), abi: self.lower_extern(f.ext), decl: self.lower_fn_decl(&f.decl, t.id, t.span, FnDeclKind::Pointer, None), param_names: self.lower_fn_params_to_names(&f.decl), diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b405e8885611..29097f7f6afd 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1184,7 +1184,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_ty_genericless(generics, where_clauses); self.check_foreign_item_ascii_only(fi.ident); } - ForeignItemKind::Static(box StaticForeignItem { ty: _, mutability: _, expr }) => { + ForeignItemKind::Static(box StaticForeignItem { expr, .. }) => { self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span)); self.check_foreign_item_ascii_only(fi.ident); } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 4c29ca0ca465..ca26b436b82e 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1973,6 +1973,7 @@ impl<'a> State<'a> { fn print_safety(&mut self, s: ast::Safety) { match s { ast::Safety::Default => {} + ast::Safety::Safe(_) => self.word_nbsp("safe"), ast::Safety::Unsafe(_) => self.word_nbsp("unsafe"), } } diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 59d9b0c1a8ec..5855972e8c5a 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -31,7 +31,13 @@ impl<'a> State<'a> { ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => { self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs); } - ast::ForeignItemKind::Static(box ast::StaticForeignItem { ty, mutability, expr }) => { + ast::ForeignItemKind::Static(box ast::StaticForeignItem { + ty, + mutability, + expr, + safety, + }) => { + self.print_safety(*safety); self.print_item_const( ident, Some(*mutability), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index e971d0e3c143..770dfcb98c91 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3475,9 +3475,9 @@ impl ForeignItem<'_> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum ForeignItemKind<'hir> { /// A foreign function. - Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>), + Fn(&'hir FnDecl<'hir>, &'hir [Ident], &'hir Generics<'hir>, Safety), /// A foreign static item (`static ext: u8`). - Static(&'hir Ty<'hir>, Mutability), + Static(&'hir Ty<'hir>, Mutability, Safety), /// A foreign type. Type, } @@ -3545,7 +3545,7 @@ impl<'hir> OwnerNode<'hir> { | OwnerNode::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) | OwnerNode::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl), OwnerNode::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(fn_decl, _, _), + kind: ForeignItemKind::Fn(fn_decl, _, _, _), .. }) => Some(fn_decl), _ => None, @@ -3728,9 +3728,9 @@ impl<'hir> Node<'hir> { | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl), Node::Expr(Expr { kind: ExprKind::Closure(Closure { fn_decl, .. }), .. }) - | Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => { - Some(fn_decl) - } + | Node::ForeignItem(ForeignItem { + kind: ForeignItemKind::Fn(fn_decl, _, _, _), .. + }) => Some(fn_decl), _ => None, } } @@ -3813,7 +3813,7 @@ impl<'hir> Node<'hir> { pub fn generics(self) -> Option<&'hir Generics<'hir>> { match self { Node::ForeignItem(ForeignItem { - kind: ForeignItemKind::Fn(_, _, generics), .. + kind: ForeignItemKind::Fn(_, _, generics, _), .. }) | Node::TraitItem(TraitItem { generics, .. }) | Node::ImplItem(ImplItem { generics, .. }) => Some(generics), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 9bc2bbe0c647..e37473df956d 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -608,12 +608,14 @@ pub fn walk_foreign_item<'v, V: Visitor<'v>>( try_visit!(visitor.visit_ident(foreign_item.ident)); match foreign_item.kind { - ForeignItemKind::Fn(ref function_declaration, param_names, ref generics) => { + ForeignItemKind::Fn(ref function_declaration, param_names, ref generics, _) => { try_visit!(visitor.visit_generics(generics)); try_visit!(visitor.visit_fn_decl(function_declaration)); walk_list!(visitor, visit_ident, param_names.iter().copied()); } - ForeignItemKind::Static(ref typ, _) => try_visit!(visitor.visit_ty(typ)), + ForeignItemKind::Static(ref typ, _, _) => { + try_visit!(visitor.visit_ty(typ)); + } ForeignItemKind::Type => (), } V::Result::output() diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 76b6cbd6e531..8a0623ef93e3 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -801,7 +801,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { let item = tcx.hir().foreign_item(item.id); match &item.kind { - hir::ForeignItemKind::Fn(fn_decl, _, _) => { + hir::ForeignItemKind::Fn(fn_decl, _, _, _) => { require_c_abi_if_c_variadic(tcx, fn_decl, abi, item.span); } hir::ForeignItemKind::Static(..) => { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index f7989aeab41b..13180fa2673b 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -29,7 +29,7 @@ fn equate_intrinsic_type<'tcx>( let (own_counts, span) = match tcx.hir_node_by_def_id(def_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) | hir::Node::ForeignItem(hir::ForeignItem { - kind: hir::ForeignItemKind::Fn(.., generics), + kind: hir::ForeignItemKind::Fn(.., generics, _), .. }) => { let own_counts = tcx.generics_of(def_id).own_counts(); diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 7e7460061484..43e0b945f342 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1321,9 +1321,11 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn icx.lowerer().lower_fn_ty(hir_id, header.safety, header.abi, decl, Some(generics), None) } - ForeignItem(&hir::ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => { + ForeignItem(&hir::ForeignItem { + kind: ForeignItemKind::Fn(fn_decl, _, _, safety), .. + }) => { let abi = tcx.hir().get_foreign_abi(hir_id); - compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi) + compute_sig_of_foreign_fn_decl(tcx, def_id, fn_decl, abi, safety) } Ctor(data) | Variant(hir::Variant { data, .. }) if data.ctor().is_some() => { @@ -1695,11 +1697,12 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( def_id: LocalDefId, decl: &'tcx hir::FnDecl<'tcx>, abi: abi::Abi, + safety: hir::Safety, ) -> ty::PolyFnSig<'tcx> { let safety = if abi == abi::Abi::RustIntrinsic { intrinsic_operation_unsafety(tcx, def_id) } else { - hir::Safety::Unsafe + safety }; let hir_id = tcx.local_def_id_to_hir_id(def_id); let fty = diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index c1850f78f2fb..abc3bb838db3 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -603,7 +603,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) { match item.kind { - hir::ForeignItemKind::Fn(_, _, generics) => { + hir::ForeignItemKind::Fn(_, _, generics, _) => { self.visit_early_late(item.hir_id(), generics, |this| { intravisit::walk_foreign_item(this, item); }) diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 71b08e293769..6811f62de07b 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -464,7 +464,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ let args = ty::GenericArgs::identity_for_item(tcx, def_id); Ty::new_fn_def(tcx, def_id.to_def_id(), args) } - ForeignItemKind::Static(t, _) => icx.lower_ty(t), + ForeignItemKind::Static(t, _, _) => icx.lower_ty(t), ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()), }, diff --git a/compiler/rustc_hir_analysis/src/hir_wf_check.rs b/compiler/rustc_hir_analysis/src/hir_wf_check.rs index 3e15fddf559f..13993a1992b7 100644 --- a/compiler/rustc_hir_analysis/src/hir_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/hir_wf_check.rs @@ -158,7 +158,7 @@ fn diagnostic_hir_wf_check<'tcx>( }, hir::Node::Field(field) => vec![field.ty], hir::Node::ForeignItem(ForeignItem { - kind: ForeignItemKind::Static(ty, _), .. + kind: ForeignItemKind::Static(ty, _, _), .. }) => vec![*ty], hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Type { default: Some(ty), .. }, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index a8e0b3fc0793..6983bbcb052c 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -345,12 +345,12 @@ impl<'a> State<'a> { self.maybe_print_comment(item.span.lo()); self.print_outer_attributes(self.attrs(item.hir_id())); match item.kind { - hir::ForeignItemKind::Fn(decl, arg_names, generics) => { + hir::ForeignItemKind::Fn(decl, arg_names, generics, safety) => { self.head(""); self.print_fn( decl, hir::FnHeader { - safety: hir::Safety::Safe, + safety, constness: hir::Constness::NotConst, abi: Abi::Rust, asyncness: hir::IsAsync::NotAsync, @@ -364,7 +364,8 @@ impl<'a> State<'a> { self.word(";"); self.end() // end the outer fn box } - hir::ForeignItemKind::Static(t, m) => { + hir::ForeignItemKind::Static(t, m, safety) => { + self.print_safety(safety); self.head("static"); if m.is_mut() { self.word_space("mut"); diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 9d3a838666af..f3a904022e9e 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -1741,13 +1741,13 @@ impl<'tcx> LateLintPass<'tcx> for ImproperCTypesDeclarations { let abi = cx.tcx.hir().get_foreign_abi(it.hir_id()); match it.kind { - hir::ForeignItemKind::Fn(decl, _, _) if !vis.is_internal_abi(abi) => { + hir::ForeignItemKind::Fn(decl, _, _, _) if !vis.is_internal_abi(abi) => { vis.check_foreign_fn(it.owner_id.def_id, decl); } - hir::ForeignItemKind::Static(ty, _) if !vis.is_internal_abi(abi) => { + hir::ForeignItemKind::Static(ty, _, _) if !vis.is_internal_abi(abi) => { vis.check_foreign_static(it.owner_id, ty.span); } - hir::ForeignItemKind::Fn(decl, _, _) => vis.check_fn(it.owner_id.def_id, decl), + hir::ForeignItemKind::Fn(decl, _, _, _) => vis.check_fn(it.owner_id.def_id, decl), hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => (), } } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 639c98155e70..c7431f377ac3 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -886,7 +886,7 @@ impl<'hir> Map<'hir> { Node::Variant(variant) => named_span(variant.span, variant.ident, None), Node::ImplItem(item) => named_span(item.span, item.ident, Some(item.generics)), Node::ForeignItem(item) => match item.kind { - ForeignItemKind::Fn(decl, _, _) => until_within(item.span, decl.output.span()), + ForeignItemKind::Fn(decl, _, _, _) => until_within(item.span, decl.output.span()), _ => named_span(item.span, item.ident, None), }, Node::Ctor(_) => return self.span(self.tcx.parent_hir_id(hir_id)), diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index b0c14cdfec93..57c8ba96a20a 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -201,7 +201,7 @@ pub fn provide(providers: &mut Providers) { .. }) | Node::ForeignItem(&ForeignItem { - kind: ForeignItemKind::Fn(_, idents, _), + kind: ForeignItemKind::Fn(_, idents, _, _), .. }) = tcx.hir_node(tcx.local_def_id_to_hir_id(def_id)) { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 53757c38e8b0..4989985bb10c 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1221,6 +1221,7 @@ impl<'a> Parser<'a> { ty, mutability: Mutability::Not, expr, + safety: Safety::Default, })) } _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), @@ -2400,9 +2401,9 @@ impl<'a> Parser<'a> { // `pub` is added in case users got confused with the ordering like `async pub fn`, // only if it wasn't preceded by `default` as `default pub` is invalid. let quals: &[Symbol] = if check_pub { - &[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern] + &[kw::Pub, kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern] } else { - &[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Extern] + &[kw::Gen, kw::Const, kw::Async, kw::Unsafe, kw::Safe, kw::Extern] }; self.check_keyword_case(kw::Fn, case) // Definitely an `fn`. // `$qual fn` or `$qual $qual`: @@ -2537,11 +2538,27 @@ impl<'a> Parser<'a> { } else if self.check_keyword(kw::Unsafe) { match safety { Safety::Unsafe(sp) => Some(WrongKw::Duplicated(sp)), + Safety::Safe(sp) => { + recover_safety = Safety::Unsafe(self.token.span); + Some(WrongKw::Misplaced(sp)) + } Safety::Default => { recover_safety = Safety::Unsafe(self.token.span); Some(WrongKw::Misplaced(ext_start_sp)) } } + } else if self.check_keyword(kw::Safe) { + match safety { + Safety::Safe(sp) => Some(WrongKw::Duplicated(sp)), + Safety::Unsafe(sp) => { + recover_safety = Safety::Safe(self.token.span); + Some(WrongKw::Misplaced(sp)) + } + Safety::Default => { + recover_safety = Safety::Safe(self.token.span); + Some(WrongKw::Misplaced(ext_start_sp)) + } + } } else { None }; diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index bab8b6c06ebe..8f733b4fcbbc 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1221,6 +1221,8 @@ impl<'a> Parser<'a> { fn parse_safety(&mut self, case: Case) -> Safety { if self.eat_keyword_case(kw::Unsafe, case) { Safety::Unsafe(self.prev_token.uninterpolated_span()) + } else if self.eat_keyword_case(kw::Safe, case) { + Safety::Safe(self.prev_token.uninterpolated_span()) } else { Safety::Default } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index cad10571afe6..6d506059ad85 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -211,9 +211,12 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { let def_kind = match fi.kind { - ForeignItemKind::Static(box StaticForeignItem { ty: _, mutability, expr: _ }) => { - DefKind::Static { mutability, nested: false } - } + ForeignItemKind::Static(box StaticForeignItem { + ty: _, + mutability, + expr: _, + safety: _, + }) => DefKind::Static { mutability, nested: false }, ForeignItemKind::Fn(_) => DefKind::Fn, ForeignItemKind::TyAlias(_) => DefKind::ForeignTy, ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 61ca0d54ca49..ede9b852ba84 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -103,6 +103,7 @@ symbols! { MacroRules: "macro_rules", Raw: "raw", Reuse: "reuse", + Safe: "safe", Union: "union", Yeet: "yeet", } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 839bfdf44af1..59e8dc678d0f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3089,7 +3089,9 @@ fn clean_maybe_renamed_foreign_item<'tcx>( let def_id = item.owner_id.to_def_id(); cx.with_param_env(def_id, |cx| { let kind = match item.kind { - hir::ForeignItemKind::Fn(decl, names, generics) => { + // FIXME(missing_unsafe_on_extern) handle safety of foreign fns. + // Safety was added as part of the implementation of unsafe extern blocks PR #124482 + hir::ForeignItemKind::Fn(decl, names, generics, _) => { let (generics, decl) = enter_impl_trait(cx, |cx| { // NOTE: generics must be cleaned before args let generics = clean_generics(generics, cx); @@ -3099,7 +3101,9 @@ fn clean_maybe_renamed_foreign_item<'tcx>( }); ForeignFunctionItem(Box::new(Function { decl, generics })) } - hir::ForeignItemKind::Static(ty, mutability) => { + // FIXME(missing_unsafe_on_extern) handle safety of foreign statics. + // Safety was added as part of the implementation of unsafe extern blocks PR #124482 + hir::ForeignItemKind::Static(ty, mutability, _) => { ForeignStaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: None }) } hir::ForeignItemKind::Type => ForeignTypeItem, diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index bbdde3049dbd..14f9ef8966d6 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -451,13 +451,15 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool { ty: lt, mutability: lm, expr: le, + safety: ls, }), Static(box StaticForeignItem { ty: rt, mutability: rm, expr: re, + safety: rs, }), - ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re) && ls == rs, ( Fn(box ast::Fn { defaultness: ld, diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 09e1dbde1d05..fd59aedadfed 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -111,6 +111,7 @@ pub(crate) fn format_defaultness(defaultness: ast::Defaultness) -> &'static str pub(crate) fn format_safety(unsafety: ast::Safety) -> &'static str { match unsafety { ast::Safety::Unsafe(..) => "unsafe ", + ast::Safety::Safe(..) => "safe ", ast::Safety::Default => "", } } diff --git a/tests/pretty/hir-fn-variadic.pp b/tests/pretty/hir-fn-variadic.pp index 978e65c825bb..dfbaff696440 100644 --- a/tests/pretty/hir-fn-variadic.pp +++ b/tests/pretty/hir-fn-variadic.pp @@ -9,7 +9,7 @@ use ::std::prelude::rust_2015::*; extern crate std; extern "C" { - fn foo(x: i32, va1: ...); + unsafe fn foo(x: i32, va1: ...); } unsafe extern "C" fn bar(_: i32, mut va2: ...) -> usize { va2.arg::() } diff --git a/tests/ui/async-await/no-async-const.rs b/tests/ui/async-await/no-async-const.rs index c5485ebc9b62..38a5df3576bb 100644 --- a/tests/ui/async-await/no-async-const.rs +++ b/tests/ui/async-await/no-async-const.rs @@ -2,5 +2,5 @@ //@ compile-flags: --crate-type lib pub async const fn x() {} -//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const` +//~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const` //~| ERROR functions cannot be both `const` and `async` diff --git a/tests/ui/async-await/no-async-const.stderr b/tests/ui/async-await/no-async-const.stderr index 524d778c09b8..d692ba8f4737 100644 --- a/tests/ui/async-await/no-async-const.stderr +++ b/tests/ui/async-await/no-async-const.stderr @@ -1,10 +1,10 @@ -error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const` +error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const` --> $DIR/no-async-const.rs:4:11 | LL | pub async const fn x() {} | ------^^^^^ | | | - | | expected one of `extern`, `fn`, or `unsafe` + | | expected one of `extern`, `fn`, `safe`, or `unsafe` | help: `const` must come before `async`: `const async` | = note: keyword order for functions declaration is `pub`, `default`, `const`, `async`, `unsafe`, `extern` diff --git a/tests/ui/coroutine/async_gen_fn.none.stderr b/tests/ui/coroutine/async_gen_fn.none.stderr index 7950251a75da..047f4d82486d 100644 --- a/tests/ui/coroutine/async_gen_fn.none.stderr +++ b/tests/ui/coroutine/async_gen_fn.none.stderr @@ -7,11 +7,11 @@ LL | async gen fn foo() {} = help: pass `--edition 2021` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide -error: expected one of `extern`, `fn`, or `unsafe`, found `gen` +error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found `gen` --> $DIR/async_gen_fn.rs:4:7 | LL | async gen fn foo() {} - | ^^^ expected one of `extern`, `fn`, or `unsafe` + | ^^^ expected one of `extern`, `fn`, `safe`, or `unsafe` error: aborting due to 2 previous errors diff --git a/tests/ui/coroutine/async_gen_fn.rs b/tests/ui/coroutine/async_gen_fn.rs index 9e96ecf3ea69..e8be0434b9ef 100644 --- a/tests/ui/coroutine/async_gen_fn.rs +++ b/tests/ui/coroutine/async_gen_fn.rs @@ -3,7 +3,7 @@ async gen fn foo() {} //[none]~^ ERROR: `async fn` is not permitted in Rust 2015 -//[none]~| ERROR: expected one of `extern`, `fn`, or `unsafe`, found `gen` +//[none]~| ERROR: expected one of `extern`, `fn`, `safe`, or `unsafe`, found `gen` //[e2024]~^^^ ERROR: gen blocks are experimental fn main() {} diff --git a/tests/ui/coroutine/gen_fn.none.stderr b/tests/ui/coroutine/gen_fn.none.stderr index c5342ee22e62..590210641aed 100644 --- a/tests/ui/coroutine/gen_fn.none.stderr +++ b/tests/ui/coroutine/gen_fn.none.stderr @@ -1,8 +1,8 @@ -error: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen` +error: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen` --> $DIR/gen_fn.rs:4:1 | LL | gen fn foo() {} - | ^^^ expected one of 9 possible tokens + | ^^^ expected one of 10 possible tokens error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/gen_fn.rs b/tests/ui/coroutine/gen_fn.rs index 3228650f4152..d47b7e576d00 100644 --- a/tests/ui/coroutine/gen_fn.rs +++ b/tests/ui/coroutine/gen_fn.rs @@ -2,7 +2,7 @@ //@[e2024] compile-flags: --edition 2024 -Zunstable-options gen fn foo() {} -//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `unsafe`, or `use`, found `gen` +//[none]~^ ERROR: expected one of `#`, `async`, `const`, `default`, `extern`, `fn`, `pub`, `safe`, `unsafe`, or `use`, found `gen` //[e2024]~^^ ERROR: gen blocks are experimental fn main() {} diff --git a/tests/ui/parser/duplicate-visibility.rs b/tests/ui/parser/duplicate-visibility.rs index 54955944c7d3..f0ee60873da0 100644 --- a/tests/ui/parser/duplicate-visibility.rs +++ b/tests/ui/parser/duplicate-visibility.rs @@ -2,8 +2,8 @@ fn main() {} extern "C" { //~ NOTE while parsing this item list starting here pub pub fn foo(); - //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub` - //~| NOTE expected one of 8 possible tokens + //~^ ERROR expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub` + //~| NOTE expected one of 9 possible tokens //~| HELP there is already a visibility modifier, remove one //~| NOTE explicit visibility first seen here } //~ NOTE the item list ends here diff --git a/tests/ui/parser/duplicate-visibility.stderr b/tests/ui/parser/duplicate-visibility.stderr index b578b1fe26e8..0d1421ee7f4e 100644 --- a/tests/ui/parser/duplicate-visibility.stderr +++ b/tests/ui/parser/duplicate-visibility.stderr @@ -1,4 +1,4 @@ -error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `unsafe`, or `use`, found keyword `pub` +error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `safe`, `unsafe`, or `use`, found keyword `pub` --> $DIR/duplicate-visibility.rs:4:9 | LL | extern "C" { @@ -6,7 +6,7 @@ LL | extern "C" { LL | pub pub fn foo(); | ^^^ | | - | expected one of 8 possible tokens + | expected one of 9 possible tokens | help: there is already a visibility modifier, remove one ... LL | } diff --git a/tests/ui/parser/issues/issue-76437-async.rs b/tests/ui/parser/issues/issue-76437-async.rs index 497e269d634e..3fafaad0277c 100644 --- a/tests/ui/parser/issues/issue-76437-async.rs +++ b/tests/ui/parser/issues/issue-76437-async.rs @@ -2,6 +2,6 @@ mod t { async pub fn t() {} - //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub` + //~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` //~| HELP visibility `pub` must come before `async` } diff --git a/tests/ui/parser/issues/issue-76437-async.stderr b/tests/ui/parser/issues/issue-76437-async.stderr index 7f2df5c87364..483599135f56 100644 --- a/tests/ui/parser/issues/issue-76437-async.stderr +++ b/tests/ui/parser/issues/issue-76437-async.stderr @@ -1,10 +1,10 @@ -error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub` +error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` --> $DIR/issue-76437-async.rs:4:11 | LL | async pub fn t() {} | ------^^^ | | | - | | expected one of `extern`, `fn`, or `unsafe` + | | expected one of `extern`, `fn`, `safe`, or `unsafe` | help: visibility `pub` must come before `async`: `pub async` error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-76437-const-async.rs b/tests/ui/parser/issues/issue-76437-const-async.rs index 45d53c639332..d8eb6cdecf1b 100644 --- a/tests/ui/parser/issues/issue-76437-const-async.rs +++ b/tests/ui/parser/issues/issue-76437-const-async.rs @@ -2,6 +2,6 @@ mod t { const async pub fn t() {} - //~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `pub` + //~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` //~| HELP visibility `pub` must come before `const async` } diff --git a/tests/ui/parser/issues/issue-76437-const-async.stderr b/tests/ui/parser/issues/issue-76437-const-async.stderr index a9acccdce182..81fa8a5f557e 100644 --- a/tests/ui/parser/issues/issue-76437-const-async.stderr +++ b/tests/ui/parser/issues/issue-76437-const-async.stderr @@ -1,10 +1,10 @@ -error: expected one of `extern`, `fn`, or `unsafe`, found keyword `pub` +error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` --> $DIR/issue-76437-const-async.rs:4:17 | LL | const async pub fn t() {} | ------------^^^ | | | - | | expected one of `extern`, `fn`, or `unsafe` + | | expected one of `extern`, `fn`, `safe`, or `unsafe` | help: visibility `pub` must come before `const async`: `pub const async` error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-76437-const.rs b/tests/ui/parser/issues/issue-76437-const.rs index c3431e3567bf..dad63f137c0f 100644 --- a/tests/ui/parser/issues/issue-76437-const.rs +++ b/tests/ui/parser/issues/issue-76437-const.rs @@ -2,6 +2,6 @@ mod t { const pub fn t() {} - //~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + //~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` //~| HELP visibility `pub` must come before `const` } diff --git a/tests/ui/parser/issues/issue-76437-const.stderr b/tests/ui/parser/issues/issue-76437-const.stderr index 4c36d773d60e..005a27b7c249 100644 --- a/tests/ui/parser/issues/issue-76437-const.stderr +++ b/tests/ui/parser/issues/issue-76437-const.stderr @@ -1,10 +1,10 @@ -error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` +error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` --> $DIR/issue-76437-const.rs:4:11 | LL | const pub fn t() {} | ------^^^ | | | - | | expected one of `async`, `extern`, `fn`, or `unsafe` + | | expected one of `async`, `extern`, `fn`, `safe`, or `unsafe` | help: visibility `pub` must come before `const`: `pub const` error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-86895.rs b/tests/ui/parser/issues/issue-86895.rs index 4cd09843107d..3e5dc41e2f4d 100644 --- a/tests/ui/parser/issues/issue-86895.rs +++ b/tests/ui/parser/issues/issue-86895.rs @@ -1,3 +1,3 @@ const pub () {} -//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe` +//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe` pub fn main() {} diff --git a/tests/ui/parser/issues/issue-86895.stderr b/tests/ui/parser/issues/issue-86895.stderr index dcde7242d398..14183ee0a5cf 100644 --- a/tests/ui/parser/issues/issue-86895.stderr +++ b/tests/ui/parser/issues/issue-86895.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` +error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` --> $DIR/issue-86895.rs:1:7 | LL | const pub () {} - | ^^^ expected one of `async`, `extern`, `fn`, or `unsafe` + | ^^^ expected one of `async`, `extern`, `fn`, `safe`, or `unsafe` error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs index 694729376ba8..e6235b1e8923 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.rs @@ -3,8 +3,8 @@ // Test that even when `const` is already present, the proposed fix is to remove the second `const` const async const fn test() {} -//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const` -//~| NOTE expected one of `extern`, `fn`, or `unsafe` +//~^ ERROR expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const` +//~| NOTE expected one of `extern`, `fn`, `safe`, or `unsafe` //~| HELP `const` already used earlier, remove this one //~| NOTE `const` first seen here //~| ERROR functions cannot be both `const` and `async` diff --git a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr index 4c55179ce237..ed2e4d815492 100644 --- a/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr +++ b/tests/ui/parser/issues/issue-87217-keyword-order/const-async-const.stderr @@ -1,10 +1,10 @@ -error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const` +error: expected one of `extern`, `fn`, `safe`, or `unsafe`, found keyword `const` --> $DIR/const-async-const.rs:5:13 | LL | const async const fn test() {} | ^^^^^ | | - | expected one of `extern`, `fn`, or `unsafe` + | expected one of `extern`, `fn`, `safe`, or `unsafe` | help: `const` already used earlier, remove this one | note: `const` first seen here diff --git a/tests/ui/parser/issues/issue-87694-duplicated-pub.rs b/tests/ui/parser/issues/issue-87694-duplicated-pub.rs index e3ea61dc4ada..816c8ff2a9f5 100644 --- a/tests/ui/parser/issues/issue-87694-duplicated-pub.rs +++ b/tests/ui/parser/issues/issue-87694-duplicated-pub.rs @@ -1,5 +1,5 @@ pub const pub fn test() {} -//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` -//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe` +//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` +//~| NOTE expected one of `async`, `extern`, `fn`, `safe`, or `unsafe` //~| HELP there is already a visibility modifier, remove one //~| NOTE explicit visibility first seen here diff --git a/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr b/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr index a210238652ab..dd75f32f68ff 100644 --- a/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr +++ b/tests/ui/parser/issues/issue-87694-duplicated-pub.stderr @@ -1,10 +1,10 @@ -error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` +error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` --> $DIR/issue-87694-duplicated-pub.rs:1:11 | LL | pub const pub fn test() {} | ^^^ | | - | expected one of `async`, `extern`, `fn`, or `unsafe` + | expected one of `async`, `extern`, `fn`, `safe`, or `unsafe` | help: there is already a visibility modifier, remove one | note: explicit visibility first seen here diff --git a/tests/ui/parser/issues/issue-87694-misplaced-pub.rs b/tests/ui/parser/issues/issue-87694-misplaced-pub.rs index 3f824617cade..b5b0bc5b2fc9 100644 --- a/tests/ui/parser/issues/issue-87694-misplaced-pub.rs +++ b/tests/ui/parser/issues/issue-87694-misplaced-pub.rs @@ -1,5 +1,5 @@ const pub fn test() {} -//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` -//~| NOTE expected one of `async`, `extern`, `fn`, or `unsafe` +//~^ ERROR expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` +//~| NOTE expected one of `async`, `extern`, `fn`, `safe`, or `unsafe` //~| HELP visibility `pub` must come before `const` //~| SUGGESTION pub const diff --git a/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr b/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr index 6f686a7e5043..d35e09dceaf7 100644 --- a/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr +++ b/tests/ui/parser/issues/issue-87694-misplaced-pub.stderr @@ -1,10 +1,10 @@ -error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` +error: expected one of `async`, `extern`, `fn`, `safe`, or `unsafe`, found keyword `pub` --> $DIR/issue-87694-misplaced-pub.rs:1:7 | LL | const pub fn test() {} | ------^^^ | | | - | | expected one of `async`, `extern`, `fn`, or `unsafe` + | | expected one of `async`, `extern`, `fn`, `safe`, or `unsafe` | help: visibility `pub` must come before `const`: `pub const` error: aborting due to 1 previous error diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs new file mode 100644 index 000000000000..c26503a8d1d1 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs @@ -0,0 +1,15 @@ +//@ revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 +//@[edition2024] compile-flags: -Zunstable-options +//@ check-pass + +unsafe extern "C" { + safe fn test1(i: i32); +} + +fn test2(i: i32) { + test1(i); +} + +fn main() {} From b4cbdb7246c633ab0ebc6ae4bbe4883cde79e787 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 27 May 2024 15:35:34 -0300 Subject: [PATCH 071/154] Fail when using safe/unsafe items inside unadorned extern blocks --- compiler/rustc_ast_passes/messages.ftl | 3 + .../rustc_ast_passes/src/ast_validation.rs | 66 +++++++++++++------ compiler/rustc_ast_passes/src/errors.rs | 9 +++ tests/ui/parser/fn-header-semantic-fail.rs | 3 +- .../ui/parser/fn-header-semantic-fail.stderr | 20 +++++- .../ui/parser/no-const-fn-in-extern-block.rs | 1 + .../parser/no-const-fn-in-extern-block.stderr | 11 +++- .../safe-unsafe-on-unadorned-extern-block.rs | 10 +++ ...fe-unsafe-on-unadorned-extern-block.stderr | 10 +++ 9 files changed, 111 insertions(+), 22 deletions(-) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 3a4c95b250c3..b90b502c22b8 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -67,6 +67,9 @@ ast_passes_extern_fn_qualifiers = functions in `extern` blocks cannot have quali .label = in this `extern` block .suggestion = remove this qualifier +ast_passes_extern_invalid_safety = items in unadorned `extern` blocks cannot have safety qualifiers + .suggestion = add unsafe to this `extern` block + ast_passes_extern_item_ascii = items in `extern` blocks cannot use non-ascii identifiers .label = in this `extern` block .note = this limitation may be lifted in the future; see issue #83942 for more information diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 29097f7f6afd..a9f06230fafc 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -87,6 +87,9 @@ struct AstValidator<'a> { /// or `Foo::Bar` is_impl_trait_banned: bool, + /// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe. + extern_mod_safety: Option, + lint_buffer: &'a mut LintBuffer, } @@ -117,6 +120,12 @@ impl<'a> AstValidator<'a> { self.outer_trait_or_trait_impl = old; } + fn with_in_extern_mod(&mut self, extern_mod_safety: Safety, f: impl FnOnce(&mut Self)) { + let old = mem::replace(&mut self.extern_mod_safety, Some(extern_mod_safety)); + f(self); + self.extern_mod_safety = old; + } + fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) { let old = mem::replace(&mut self.is_impl_trait_banned, true); f(self); @@ -430,6 +439,20 @@ impl<'a> AstValidator<'a> { } } + fn check_foreign_item_safety(&self, item_span: Span, safety: Safety) { + match safety { + Safety::Unsafe(_) | Safety::Safe(_) + if self.extern_mod_safety == Some(Safety::Default) => + { + self.dcx().emit_err(errors::InvalidSafetyOnExtern { + item_span, + block: self.current_extern_span(), + }); + } + _ => {} + } + } + fn check_defaultness(&self, span: Span, defaultness: Defaultness) { if let Defaultness::Default(def_span) = defaultness { let span = self.session.source_map().guess_head_span(span); @@ -1014,26 +1037,28 @@ impl<'a> Visitor<'a> for AstValidator<'a> { return; // Avoid visiting again. } ItemKind::ForeignMod(ForeignMod { abi, safety, .. }) => { - let old_item = mem::replace(&mut self.extern_mod, Some(item)); - self.visibility_not_permitted( - &item.vis, - errors::VisibilityNotPermittedNote::IndividualForeignItems, - ); - - if &Safety::Default == safety { - self.lint_buffer.buffer_lint( - MISSING_UNSAFE_ON_EXTERN, - item.id, - item.span, - BuiltinLintDiag::MissingUnsafeOnExtern, + self.with_in_extern_mod(*safety, |this| { + let old_item = mem::replace(&mut this.extern_mod, Some(item)); + this.visibility_not_permitted( + &item.vis, + errors::VisibilityNotPermittedNote::IndividualForeignItems, ); - } - if abi.is_none() { - self.maybe_lint_missing_abi(item.span, item.id); - } - visit::walk_item(self, item); - self.extern_mod = old_item; + if &Safety::Default == safety { + this.lint_buffer.buffer_lint( + MISSING_UNSAFE_ON_EXTERN, + item.id, + item.span, + BuiltinLintDiag::MissingUnsafeOnExtern, + ); + } + + if abi.is_none() { + this.maybe_lint_missing_abi(item.span, item.id); + } + visit::walk_item(this, item); + this.extern_mod = old_item; + }); return; // Avoid visiting again. } ItemKind::Enum(def, _) => { @@ -1165,6 +1190,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { match &fi.kind { ForeignItemKind::Fn(box Fn { defaultness, sig, body, .. }) => { + self.check_foreign_item_safety(fi.span, sig.header.safety); self.check_defaultness(fi.span, *defaultness); self.check_foreign_fn_bodyless(fi.ident, body.as_deref()); self.check_foreign_fn_headerless(sig.header); @@ -1184,7 +1210,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_ty_genericless(generics, where_clauses); self.check_foreign_item_ascii_only(fi.ident); } - ForeignItemKind::Static(box StaticForeignItem { expr, .. }) => { + ForeignItemKind::Static(box StaticForeignItem { expr, safety, .. }) => { + self.check_foreign_item_safety(fi.span, *safety); self.check_foreign_kind_bodyless(fi.ident, "static", expr.as_ref().map(|b| b.span)); self.check_foreign_item_ascii_only(fi.ident); } @@ -1740,6 +1767,7 @@ pub fn check_crate( outer_impl_trait: None, disallow_tilde_const: Some(DisallowTildeConstContext::Item), is_impl_trait_banned: false, + extern_mod_safety: None, lint_buffer: lints, }; visit::walk_crate(&mut validator, krate); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index c07fbe5b0166..05e99a3d6361 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -216,6 +216,15 @@ pub enum ExternBlockSuggestion { }, } +#[derive(Diagnostic)] +#[diag(ast_passes_extern_invalid_safety)] +pub struct InvalidSafetyOnExtern { + #[primary_span] + pub item_span: Span, + #[suggestion(code = "", applicability = "maybe-incorrect")] + pub block: Span, +} + #[derive(Diagnostic)] #[diag(ast_passes_bound_in_context)] pub struct BoundInContext<'a> { diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs index 3b98433cdd82..5907ac052604 100644 --- a/tests/ui/parser/fn-header-semantic-fail.rs +++ b/tests/ui/parser/fn-header-semantic-fail.rs @@ -44,7 +44,7 @@ fn main() { extern "C" { async fn fe1(); //~ ERROR functions in `extern` blocks cannot have qualifiers - unsafe fn fe2(); + unsafe fn fe2(); //~ ERROR items in unadorned `extern` blocks cannot have safety qualifiers const fn fe3(); //~ ERROR functions in `extern` blocks cannot have qualifiers extern "C" fn fe4(); //~ ERROR functions in `extern` blocks cannot have qualifiers const async unsafe extern "C" fn fe5(); @@ -52,5 +52,6 @@ fn main() { //~| ERROR functions in `extern` blocks //~| ERROR functions in `extern` blocks //~| ERROR functions cannot be both `const` and `async` + //~| ERROR items in unadorned `extern` blocks cannot have safety qualifiers } } diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index dc2a216754d2..abaa6527b0aa 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -78,6 +78,15 @@ LL | extern "C" { LL | async fn fe1(); | ^^^^^ help: remove this qualifier +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/fn-header-semantic-fail.rs:47:9 + | +LL | extern "C" { + | ---------- help: add unsafe to this `extern` block +LL | async fn fe1(); +LL | unsafe fn fe2(); + | ^^^^^^^^^^^^^^^^ + error: functions in `extern` blocks cannot have qualifiers --> $DIR/fn-header-semantic-fail.rs:48:9 | @@ -96,6 +105,15 @@ LL | extern "C" { LL | extern "C" fn fe4(); | ^^^^^^^^^^ help: remove this qualifier +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/fn-header-semantic-fail.rs:50:9 + | +LL | extern "C" { + | ---------- help: add unsafe to this `extern` block +... +LL | const async unsafe extern "C" fn fe5(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + error: functions in `extern` blocks cannot have qualifiers --> $DIR/fn-header-semantic-fail.rs:50:15 | @@ -132,6 +150,6 @@ LL | const async unsafe extern "C" fn fe5(); | | `async` because of this | `const` because of this -error: aborting due to 15 previous errors +error: aborting due to 17 previous errors For more information about this error, try `rustc --explain E0379`. diff --git a/tests/ui/parser/no-const-fn-in-extern-block.rs b/tests/ui/parser/no-const-fn-in-extern-block.rs index 1993124edc39..3ad9ba006d3d 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.rs +++ b/tests/ui/parser/no-const-fn-in-extern-block.rs @@ -3,6 +3,7 @@ extern "C" { //~^ ERROR functions in `extern` blocks cannot have qualifiers const unsafe fn bar(); //~^ ERROR functions in `extern` blocks cannot have qualifiers + //~| ERROR items in unadorned `extern` blocks cannot have safety qualifiers } fn main() {} diff --git a/tests/ui/parser/no-const-fn-in-extern-block.stderr b/tests/ui/parser/no-const-fn-in-extern-block.stderr index 2dec6f769310..892024ce8934 100644 --- a/tests/ui/parser/no-const-fn-in-extern-block.stderr +++ b/tests/ui/parser/no-const-fn-in-extern-block.stderr @@ -6,6 +6,15 @@ LL | extern "C" { LL | const fn foo(); | ^^^^^ help: remove this qualifier +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/no-const-fn-in-extern-block.rs:4:5 + | +LL | extern "C" { + | ---------- help: add unsafe to this `extern` block +... +LL | const unsafe fn bar(); + | ^^^^^^^^^^^^^^^^^^^^^^ + error: functions in `extern` blocks cannot have qualifiers --> $DIR/no-const-fn-in-extern-block.rs:4:5 | @@ -15,5 +24,5 @@ LL | extern "C" { LL | const unsafe fn bar(); | ^^^^^ help: remove this qualifier -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs new file mode 100644 index 000000000000..7c184d092f0d --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs @@ -0,0 +1,10 @@ +extern "C" { + safe fn test1(i: i32); + //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers +} + +fn test2(i: i32) { + test1(i); +} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr new file mode 100644 index 000000000000..d96757a17c23 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr @@ -0,0 +1,10 @@ +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:2:5 + | +LL | extern "C" { + | ---------- help: add unsafe to this `extern` block +LL | safe fn test1(i: i32); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From bac72cf7cf823bbf10e7d093a8225490bf8d1350 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 7 May 2024 14:43:23 +0200 Subject: [PATCH 072/154] Add safe/unsafe to static inside extern blocks --- compiler/rustc_ast/src/ast.rs | 4 +++- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 2 +- .../rustc_ast_pretty/src/pprust/state/item.rs | 3 ++- .../rustc_const_eval/src/interpret/intern.rs | 2 +- .../rustc_const_eval/src/interpret/validity.rs | 4 +++- compiler/rustc_expand/src/build.rs | 5 ++++- compiler/rustc_hir/src/def.rs | 2 ++ compiler/rustc_hir_analysis/src/check/errs.rs | 3 ++- compiler/rustc_metadata/src/rmeta/table.rs | 12 ++++++++---- compiler/rustc_middle/src/hir/map/mod.rs | 4 +++- compiler/rustc_middle/src/mir/pretty.rs | 4 ++-- compiler/rustc_mir_build/src/check_unsafety.rs | 6 +++++- compiler/rustc_parse/src/parser/item.rs | 18 +++++++++++++----- compiler/rustc_resolve/src/def_collector.rs | 18 +++++++++++++++--- .../passes/collect_intra_doc_links.rs | 8 ++++++-- src/tools/clippy/clippy_utils/src/ast_utils.rs | 4 +++- .../extern-items-unsafe.edition2021.stderr | 16 ++++++++++++---- .../extern-items-unsafe.edition2024.stderr | 16 ++++++++++++---- .../extern-items-unsafe.rs | 10 ++++++---- .../unsafe-extern-blocks/safe-items.rs | 5 +++-- .../safe-unsafe-on-unadorned-extern-block.rs | 6 ++++-- ...afe-unsafe-on-unadorned-extern-block.stderr | 11 ++++++++++- .../unsafe-items.edition2021.stderr | 16 ++++++++++++---- .../unsafe-items.edition2024.stderr | 16 ++++++++++++---- .../unsafe-extern-blocks/unsafe-items.rs | 10 ++++++---- 27 files changed, 152 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 042c31fc70f7..910fbb876974 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -3164,6 +3164,7 @@ pub struct DelegationMac { #[derive(Clone, Encodable, Decodable, Debug)] pub struct StaticItem { pub ty: P, + pub safety: Safety, pub mutability: Mutability, pub expr: Option>, } @@ -3182,7 +3183,7 @@ impl From for StaticForeignItem { fn from(static_item: StaticItem) -> StaticForeignItem { StaticForeignItem { ty: static_item.ty, - safety: Safety::Default, + safety: static_item.safety, mutability: static_item.mutability, expr: static_item.expr, } @@ -3193,6 +3194,7 @@ impl From for StaticItem { fn from(static_item: StaticForeignItem) -> StaticItem { StaticItem { ty: static_item.ty, + safety: static_item.safety, mutability: static_item.mutability, expr: static_item.expr, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index c6814df28400..a04c648ac731 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1080,7 +1080,7 @@ impl NoopVisitItemKind for ItemKind { match self { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => { + ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => { vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ccf9f99757e3..de285aed1656 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -334,7 +334,7 @@ impl WalkItemKind for ItemKind { match self { ItemKind::ExternCrate(_) => {} ItemKind::Use(use_tree) => try_visit!(visitor.visit_use_tree(use_tree, item.id, false)), - ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => { + ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => { try_visit!(visitor.visit_ty(ty)); visit_opt!(visitor, visit_expr, expr); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 70bf74e5234d..8c963e9f8907 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -181,7 +181,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_use_tree(use_tree, &prefix, id, vis_span, ident, attrs) } - ItemKind::Static(box ast::StaticItem { ty: t, mutability: m, expr: e }) => { + ItemKind::Static(box ast::StaticItem { ty: t, safety: _, mutability: m, expr: e }) => { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref(), ImplTraitPosition::StaticTy); hir::ItemKind::Static(ty, *m, body_id) diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 5855972e8c5a..474741fb0677 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -171,7 +171,8 @@ impl<'a> State<'a> { self.print_use_tree(tree); self.word(";"); } - ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => { + ast::ItemKind::Static(box StaticItem { ty, safety, mutability: mutbl, expr: body }) => { + self.print_safety(*safety); self.print_item_const( item.ident, Some(*mutbl), diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs index 8d0b267e1a9c..3066e0933d94 100644 --- a/compiler/rustc_const_eval/src/interpret/intern.rs +++ b/compiler/rustc_const_eval/src/interpret/intern.rs @@ -102,7 +102,7 @@ fn intern_as_new_static<'tcx>( let feed = tcx.create_def( static_id, sym::nested, - DefKind::Static { mutability: alloc.0.mutability, nested: true }, + DefKind::Static { safety: hir::Safety::Safe, mutability: alloc.0.mutability, nested: true }, ); tcx.set_nested_alloc_id_static(alloc_id, feed.def_id()); diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index e35ce9ef28d6..3407c7b8c792 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -711,7 +711,9 @@ fn mutability<'tcx>(ecx: &InterpCx<'tcx, impl Machine<'tcx>>, alloc_id: AllocId) // We're not using `try_global_alloc` since dangling pointers have already been handled. match ecx.tcx.global_alloc(alloc_id) { GlobalAlloc::Static(did) => { - let DefKind::Static { mutability, nested } = ecx.tcx.def_kind(did) else { bug!() }; + let DefKind::Static { safety: _, mutability, nested } = ecx.tcx.def_kind(did) else { + bug!() + }; if nested { assert!( ecx.memory.alloc_map.get(alloc_id).is_none(), diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 1b6e191c2eb0..b3d41908260e 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -631,7 +631,10 @@ impl<'a> ExtCtxt<'a> { span, name, AttrVec::new(), - ast::ItemKind::Static(ast::StaticItem { ty, mutability, expr: Some(expr) }.into()), + ast::ItemKind::Static( + ast::StaticItem { ty, safety: ast::Safety::Default, mutability, expr: Some(expr) } + .into(), + ), ) } diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 649a08b6972f..b1854923247f 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -76,6 +76,8 @@ pub enum DefKind { /// Constant generic parameter: `struct Foo { ... }` ConstParam, Static { + /// Whether it's a `unsafe static`, `safe static` (inside extern only) or just a `static`. + safety: hir::Safety, /// Whether it's a `static mut` or just a `static`. mutability: ast::Mutability, /// Whether it's an anonymous static generated for nested allocations. diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index a49626eed35a..2cdcc06f53c0 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -41,7 +41,8 @@ fn path_if_static_mut(tcx: TyCtxt<'_>, expr: &hir::Expr<'_>) -> Option { if let hir::ExprKind::Path(qpath) = expr.kind && let hir::QPath::Resolved(_, path) = qpath && let hir::def::Res::Def(def_kind, _) = path.res - && let hir::def::DefKind::Static { mutability: Mutability::Mut, nested: false } = def_kind + && let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } = + def_kind { return Some(qpath_to_string(&tcx, &qpath)); } diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 23a6ceb4d3e5..dcbddad2dbca 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -156,10 +156,14 @@ fixed_size_enum! { ( Impl { of_trait: false } ) ( Impl { of_trait: true } ) ( Closure ) - ( Static { mutability: ast::Mutability::Not, nested: false } ) - ( Static { mutability: ast::Mutability::Mut, nested: false } ) - ( Static { mutability: ast::Mutability::Not, nested: true } ) - ( Static { mutability: ast::Mutability::Mut, nested: true } ) + ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: false } ) + ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: false } ) + ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: false } ) + ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: false } ) + ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Not, nested: true } ) + ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Not, nested: true } ) + ( Static { safety: hir::Safety::Unsafe, mutability: ast::Mutability::Mut, nested: true } ) + ( Static { safety: hir::Safety::Safe, mutability: ast::Mutability::Mut, nested: true } ) ( Ctor(CtorOf::Struct, CtorKind::Fn) ) ( Ctor(CtorOf::Struct, CtorKind::Const) ) ( Ctor(CtorOf::Variant, CtorKind::Fn) ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index c7431f377ac3..0b3423fc1bc0 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -305,7 +305,9 @@ impl<'hir> Map<'hir> { DefKind::InlineConst => BodyOwnerKind::Const { inline: true }, DefKind::Ctor(..) | DefKind::Fn | DefKind::AssocFn => BodyOwnerKind::Fn, DefKind::Closure => BodyOwnerKind::Closure, - DefKind::Static { mutability, nested: false } => BodyOwnerKind::Static(mutability), + DefKind::Static { safety: _, mutability, nested: false } => { + BodyOwnerKind::Static(mutability) + } dk => bug!("{:?} is not a body node: {:?}", def_id, dk), } } diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index f1c79c0b0391..978c15f4d73c 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -559,10 +559,10 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io: match (kind, body.source.promoted) { (_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts (DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?, - (DefKind::Static { mutability: hir::Mutability::Not, nested: false }, _) => { + (DefKind::Static { safety: _, mutability: hir::Mutability::Not, nested: false }, _) => { write!(w, "static ")? } - (DefKind::Static { mutability: hir::Mutability::Mut, nested: false }, _) => { + (DefKind::Static { safety: _, mutability: hir::Mutability::Mut, nested: false }, _) => { write!(w, "static mut ")? } (_, _) if is_function => write!(w, "fn ")?, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 659ae1724603..5517fc3fd942 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -2,6 +2,7 @@ use crate::build::ExprCategory; use crate::errors::*; use rustc_errors::DiagArgValue; +use rustc_hir::def::DefKind; use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability}; use rustc_middle::mir::BorrowKind; use rustc_middle::span_bug; @@ -456,7 +457,10 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { if self.tcx.is_mutable_static(def_id) { self.requires_unsafe(expr.span, UseOfMutableStatic); } else if self.tcx.is_foreign_item(def_id) { - self.requires_unsafe(expr.span, UseOfExternStatic); + match self.tcx.def_kind(def_id) { + DefKind::Static { safety: hir::Safety::Safe, .. } => {} + _ => self.requires_unsafe(expr.span, UseOfExternStatic), + } } } else if self.thir[arg].ty.is_unsafe_ptr() { self.requires_unsafe(expr.span, DerefOfRawPointer); diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 4989985bb10c..37c99958fc88 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -226,10 +226,11 @@ impl<'a> Parser<'a> { self.expect_keyword(kw::Extern)?; self.parse_item_foreign_mod(attrs, safety)? } else if self.is_static_global() { + let safety = self.parse_safety(Case::Sensitive); // STATIC ITEM self.bump(); // `static` let mutability = self.parse_mutability(); - let (ident, item) = self.parse_static_item(mutability)?; + let (ident, item) = self.parse_static_item(safety, mutability)?; (ident, ItemKind::Static(Box::new(item))) } else if let Const::Yes(const_span) = self.parse_constness(Case::Sensitive) { // CONST ITEM @@ -952,7 +953,7 @@ impl<'a> Parser<'a> { let kind = match AssocItemKind::try_from(kind) { Ok(kind) => kind, Err(kind) => match kind { - ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => { + ItemKind::Static(box StaticItem { ty, safety: _, mutability: _, expr }) => { self.dcx().emit_err(errors::AssociatedStaticItemNotAllowed { span }); AssocItemKind::Const(Box::new(ConstItem { defaultness: Defaultness::Final, @@ -1259,7 +1260,10 @@ impl<'a> Parser<'a> { matches!(token.kind, token::BinOp(token::Or) | token::OrOr) }) } else { - false + let quals: &[Symbol] = &[kw::Unsafe, kw::Safe]; + // `$qual static` + quals.iter().any(|&kw| self.check_keyword(kw)) + && self.look_ahead(1, |t| t.is_keyword(kw::Static)) } } @@ -1320,7 +1324,11 @@ impl<'a> Parser<'a> { /// ```ebnf /// Static = "static" "mut"? $ident ":" $ty (= $expr)? ";" ; /// ``` - fn parse_static_item(&mut self, mutability: Mutability) -> PResult<'a, (Ident, StaticItem)> { + fn parse_static_item( + &mut self, + safety: Safety, + mutability: Mutability, + ) -> PResult<'a, (Ident, StaticItem)> { let ident = self.parse_ident()?; if self.token.kind == TokenKind::Lt && self.may_recover() { @@ -1341,7 +1349,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; - Ok((ident, StaticItem { ty, mutability, expr })) + Ok((ident, StaticItem { ty, safety, mutability, expr })) } /// Parse a constant item with the prefix `"const"` already parsed. diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 6d506059ad85..d7416ead325d 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -2,6 +2,7 @@ use crate::{ImplTraitContext, Resolver}; use rustc_ast::visit::FnKind; use rustc_ast::*; use rustc_expand::expand::AstFragment; +use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind}; use rustc_hir::def_id::LocalDefId; use rustc_span::hygiene::LocalExpnId; @@ -128,7 +129,11 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ItemKind::Union(..) => DefKind::Union, ItemKind::ExternCrate(..) => DefKind::ExternCrate, ItemKind::TyAlias(..) => DefKind::TyAlias, - ItemKind::Static(s) => DefKind::Static { mutability: s.mutability, nested: false }, + ItemKind::Static(s) => DefKind::Static { + safety: hir::Safety::Safe, + mutability: s.mutability, + nested: false, + }, ItemKind::Const(..) => DefKind::Const, ItemKind::Fn(..) | ItemKind::Delegation(..) => DefKind::Fn, ItemKind::MacroDef(..) => { @@ -215,8 +220,15 @@ impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { ty: _, mutability, expr: _, - safety: _, - }) => DefKind::Static { mutability, nested: false }, + safety, + }) => { + let safety = match safety { + ast::Safety::Unsafe(_) | ast::Safety::Default => hir::Safety::Unsafe, + ast::Safety::Safe(_) => hir::Safety::Safe, + }; + + DefKind::Static { safety, mutability, nested: false } + } ForeignItemKind::Fn(_) => DefKind::Fn, ForeignItemKind::TyAlias(_) => DefKind::ForeignTy, ForeignItemKind::MacCall(_) => return self.visit_macro_invoc(fi.id), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 8ab24a8c12e5..440b02a1fa75 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -12,7 +12,7 @@ use rustc_errors::{Applicability, Diag, DiagMessage}; use rustc_hir::def::Namespace::*; use rustc_hir::def::{DefKind, Namespace, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_ID}; -use rustc_hir::Mutability; +use rustc_hir::{Mutability, Safety}; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_middle::{bug, span_bug, ty}; use rustc_resolve::rustdoc::{has_primitive_or_keyword_docs, prepare_to_doc_link_resolution}; @@ -1517,7 +1517,11 @@ impl Disambiguator { "union" => Kind(DefKind::Union), "module" | "mod" => Kind(DefKind::Mod), "const" | "constant" => Kind(DefKind::Const), - "static" => Kind(DefKind::Static { mutability: Mutability::Not, nested: false }), + "static" => Kind(DefKind::Static { + mutability: Mutability::Not, + nested: false, + safety: Safety::Safe, + }), "function" | "fn" | "method" => Kind(DefKind::Fn), "derive" => Kind(DefKind::Macro(MacroKind::Derive)), "type" => NS(Namespace::TypeNS), diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 14f9ef8966d6..c70f5c2df842 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -308,13 +308,15 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { ty: lt, mutability: lm, expr: le, + safety: ls, }), Static(box StaticItem { ty: rt, mutability: rm, expr: re, + safety: rs, }), - ) => lm == rm && eq_ty(lt, rt) && eq_expr_opt(le, re), + ) => lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le, re), ( Const(box ConstItem { defaultness: ld, diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr index a94f8d742360..77554da10e60 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr @@ -1,11 +1,19 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:11:5 + --> $DIR/extern-items-unsafe.rs:12:5 | -LL | test1(i); - | ^^^^^^^^ call to unsafe function +LL | test1(TEST1); + | ^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to 1 previous error +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/extern-items-unsafe.rs:12:11 + | +LL | test1(TEST1); + | ^^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr index c187dac1152b..33b752782d59 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr @@ -1,11 +1,19 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:11:5 + --> $DIR/extern-items-unsafe.rs:12:5 | -LL | test1(i); - | ^^^^^^^^ call to unsafe function +LL | test1(TEST1); + | ^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to 1 previous error +error[E0133]: use of extern static is unsafe and requires unsafe block + --> $DIR/extern-items-unsafe.rs:12:11 + | +LL | test1(TEST1); + | ^^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs index 70f3c0afe7c9..721e07acca58 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs @@ -4,17 +4,19 @@ //@[edition2024] compile-flags: -Zunstable-options unsafe extern "C" { + static TEST1: i32; fn test1(i: i32); } -fn test2(i: i32) { - test1(i); +fn test2() { + test1(TEST1); //~^ ERROR: call to unsafe function `test1` is unsafe + //~| ERROR: use of extern static is unsafe } -fn test3(i: i32) { +fn test3() { unsafe { - test1(i); + test1(TEST1); } } diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs index c26503a8d1d1..b0b8a8b012a6 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs @@ -5,11 +5,12 @@ //@ check-pass unsafe extern "C" { + safe static TEST1: i32; safe fn test1(i: i32); } -fn test2(i: i32) { - test1(i); +fn test2() { + test1(TEST1); } fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs index 7c184d092f0d..d37a7be452da 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs @@ -1,10 +1,12 @@ extern "C" { + safe static TEST1: i32; + //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers safe fn test1(i: i32); //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers } -fn test2(i: i32) { - test1(i); +fn test2() { + test1(TEST1); } fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr index d96757a17c23..66624f1fcb16 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr @@ -3,8 +3,17 @@ error: items in unadorned `extern` blocks cannot have safety qualifiers | LL | extern "C" { | ---------- help: add unsafe to this `extern` block +LL | safe static TEST1: i32; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:4:5 + | +LL | extern "C" { + | ---------- help: add unsafe to this `extern` block +... LL | safe fn test1(i: i32); | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error +error: aborting due to 2 previous errors diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr index 67e582c7c565..e3626bb497e4 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr @@ -1,11 +1,19 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:17:5 + --> $DIR/unsafe-items.rs:18:5 | -LL | test1(i); - | ^^^^^^^^ call to unsafe function +LL | test1(TEST1); + | ^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to 1 previous error +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/unsafe-items.rs:18:11 + | +LL | test1(TEST1); + | ^^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr index 8a9410f8f135..89bc501b7b5a 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr @@ -1,11 +1,19 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:17:5 + --> $DIR/unsafe-items.rs:18:5 | -LL | test1(i); - | ^^^^^^^^ call to unsafe function +LL | test1(TEST1); + | ^^^^^^^^^^^^ call to unsafe function | = note: consult the function's documentation for information on how to avoid undefined behavior -error: aborting due to 1 previous error +error[E0133]: use of extern static is unsafe and requires unsafe block + --> $DIR/unsafe-items.rs:18:11 + | +LL | test1(TEST1); + | ^^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs index 4b6d077e9877..dc2bae892a98 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs @@ -4,18 +4,20 @@ //@[edition2024] compile-flags: -Zunstable-options unsafe extern "C" { + unsafe static TEST1: i32; unsafe fn test1(i: i32); } -fn test2(i: i32) { +fn test2() { unsafe { - test1(i); + test1(TEST1); } } -fn test3(i: i32) { - test1(i); +fn test3() { + test1(TEST1); //~^ ERROR: call to unsafe function `test1` is unsafe + //~| ERROR: use of extern static is unsafe } fn main() {} From 7e993b24d52367407d52fbc15a194d24f3889476 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 3 Jun 2024 10:28:52 +0200 Subject: [PATCH 073/154] Create `run-make` `env_var` and `env_var_os` helpers --- src/tools/run-make-support/src/cc.rs | 9 +++--- src/tools/run-make-support/src/clang.rs | 6 ++-- src/tools/run-make-support/src/lib.rs | 31 ++++++++++++++----- .../run-make-support/src/llvm_readobj.rs | 6 ++-- src/tools/run-make-support/src/run.rs | 14 ++++----- src/tools/run-make-support/src/rustc.rs | 5 ++- src/tools/run-make-support/src/rustdoc.rs | 7 ++--- tests/run-make/compiler-builtins/rmake.rs | 10 +++--- .../windows-binary-no-external-deps/rmake.rs | 5 ++- 9 files changed, 51 insertions(+), 42 deletions(-) diff --git a/src/tools/run-make-support/src/cc.rs b/src/tools/run-make-support/src/cc.rs index 0012e7b66af3..1472a39305e3 100644 --- a/src/tools/run-make-support/src/cc.rs +++ b/src/tools/run-make-support/src/cc.rs @@ -1,8 +1,9 @@ -use std::env; use std::path::Path; use std::process::Command; -use crate::{bin_name, cygpath_windows, handle_failed_output, is_msvc, is_windows, tmp_dir, uname}; +use crate::{ + bin_name, cygpath_windows, env_var, handle_failed_output, is_msvc, is_windows, tmp_dir, uname, +}; /// Construct a new platform-specific C compiler invocation. /// @@ -27,11 +28,11 @@ impl Cc { /// WARNING: This means that what flags are accepted by the underlying C compile is /// platform- AND compiler-specific. Consult the relevant docs for `gcc`, `clang` and `mvsc`. pub fn new() -> Self { - let compiler = env::var("CC").unwrap(); + let compiler = env_var("CC"); let mut cmd = Command::new(compiler); - let default_cflags = env::var("CC_DEFAULT_FLAGS").unwrap(); + let default_cflags = env_var("CC_DEFAULT_FLAGS"); for flag in default_cflags.split(char::is_whitespace) { cmd.arg(flag); } diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/clang.rs index 6ccce67b250d..63c5af17c1db 100644 --- a/src/tools/run-make-support/src/clang.rs +++ b/src/tools/run-make-support/src/clang.rs @@ -1,8 +1,7 @@ -use std::env; use std::path::Path; use std::process::Command; -use crate::{bin_name, handle_failed_output, tmp_dir}; +use crate::{bin_name, env_var, handle_failed_output, tmp_dir}; /// Construct a new `clang` invocation. `clang` is not always available for all targets. pub fn clang() -> Clang { @@ -20,8 +19,7 @@ crate::impl_common_helpers!(Clang); impl Clang { /// Construct a new `clang` invocation. `clang` is not always available for all targets. pub fn new() -> Self { - let clang = - env::var("CLANG").expect("`CLANG` not specified, but this is required to find `clang`"); + let clang = env_var("CLANG"); let cmd = Command::new(clang); Self { cmd } } diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index 323fc40e6481..d4b2f88fecfc 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -12,6 +12,7 @@ pub mod rustc; pub mod rustdoc; use std::env; +use std::ffi::OsString; use std::fs; use std::io; use std::path::{Path, PathBuf}; @@ -30,14 +31,28 @@ pub use run::{run, run_fail}; pub use rustc::{aux_build, rustc, Rustc}; pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc}; +pub fn env_var(name: &str) -> String { + match env::var(name) { + Ok(v) => v, + Err(err) => panic!("failed to retrieve environment variable {name:?}: {err:?}"), + } +} + +pub fn env_var_os(name: &str) -> OsString { + match env::var_os(name) { + Some(v) => v, + None => panic!("failed to retrieve environment variable {name:?}"), + } +} + /// Path of `TMPDIR` (a temporary build directory, not under `/tmp`). pub fn tmp_dir() -> PathBuf { - env::var_os("TMPDIR").unwrap().into() + env_var_os("TMPDIR").into() } /// `TARGET` pub fn target() -> String { - env::var("TARGET").unwrap() + env_var("TARGET") } /// Check if target is windows-like. @@ -62,7 +77,7 @@ pub fn static_lib(name: &str) -> PathBuf { } pub fn python_command() -> Command { - let python_path = std::env::var("PYTHON").expect("PYTHON environment variable does not exist"); + let python_path = env_var("PYTHON"); Command::new(python_path) } @@ -73,7 +88,7 @@ pub fn htmldocck() -> Command { } pub fn source_path() -> PathBuf { - std::env::var("S").expect("S variable does not exist").into() + env_var("S").into() } /// Construct the static library name based on the platform. @@ -208,12 +223,12 @@ fn handle_failed_output(cmd: &Command, output: Output, caller_line_number: u32) /// Set the runtime library path as needed for running the host rustc/rustdoc/etc. pub fn set_host_rpath(cmd: &mut Command) { - let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap(); + let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR"); cmd.env(&ld_lib_path_envvar, { let mut paths = vec![]; - paths.push(PathBuf::from(env::var("TMPDIR").unwrap())); - paths.push(PathBuf::from(env::var("HOST_RPATH_DIR").unwrap())); - for p in env::split_paths(&env::var(&ld_lib_path_envvar).unwrap()) { + paths.push(PathBuf::from(env_var("TMPDIR"))); + paths.push(PathBuf::from(env_var("HOST_RPATH_DIR"))); + for p in env::split_paths(&env_var(&ld_lib_path_envvar)) { paths.push(p.to_path_buf()); } env::join_paths(paths.iter()).unwrap() diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs index f114aacfa3fc..77aaadfe18c4 100644 --- a/src/tools/run-make-support/src/llvm_readobj.rs +++ b/src/tools/run-make-support/src/llvm_readobj.rs @@ -1,8 +1,7 @@ -use std::env; use std::path::{Path, PathBuf}; use std::process::Command; -use crate::handle_failed_output; +use crate::{env_var, handle_failed_output}; /// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available /// at `$LLVM_BIN_DIR/llvm-readobj`. @@ -22,8 +21,7 @@ impl LlvmReadobj { /// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available /// at `$LLVM_BIN_DIR/llvm-readobj`. pub fn new() -> Self { - let llvm_bin_dir = env::var("LLVM_BIN_DIR") - .expect("`LLVM_BIN_DIR` not specified, but this is required to find `llvm-readobj`"); + let llvm_bin_dir = env_var("LLVM_BIN_DIR"); let llvm_bin_dir = PathBuf::from(llvm_bin_dir); let llvm_readobj = llvm_bin_dir.join("llvm-readobj"); let cmd = Command::new(llvm_readobj); diff --git a/src/tools/run-make-support/src/run.rs b/src/tools/run-make-support/src/run.rs index da4f265efc3b..8d8eafba99b7 100644 --- a/src/tools/run-make-support/src/run.rs +++ b/src/tools/run-make-support/src/run.rs @@ -2,23 +2,23 @@ use std::env; use std::path::{Path, PathBuf}; use std::process::{Command, Output}; -use crate::is_windows; +use crate::{env_var, is_windows}; use super::handle_failed_output; fn run_common(name: &str) -> (Command, Output) { let mut bin_path = PathBuf::new(); - bin_path.push(env::var("TMPDIR").unwrap()); + bin_path.push(env_var("TMPDIR")); bin_path.push(name); - let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap(); + let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR"); let mut cmd = Command::new(bin_path); cmd.env(&ld_lib_path_envvar, { let mut paths = vec![]; - paths.push(PathBuf::from(env::var("TMPDIR").unwrap())); - for p in env::split_paths(&env::var("TARGET_RPATH_ENV").unwrap()) { + paths.push(PathBuf::from(env_var("TMPDIR"))); + for p in env::split_paths(&env_var("TARGET_RPATH_ENV")) { paths.push(p.to_path_buf()); } - for p in env::split_paths(&env::var(&ld_lib_path_envvar).unwrap()) { + for p in env::split_paths(&env_var(&ld_lib_path_envvar)) { paths.push(p.to_path_buf()); } env::join_paths(paths.iter()).unwrap() @@ -29,7 +29,7 @@ fn run_common(name: &str) -> (Command, Output) { for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) { paths.push(p.to_path_buf()); } - paths.push(Path::new(&std::env::var("TARGET_RPATH_DIR").unwrap()).to_path_buf()); + paths.push(Path::new(&env_var("TARGET_RPATH_DIR")).to_path_buf()); cmd.env("PATH", env::join_paths(paths.iter()).unwrap()); } diff --git a/src/tools/run-make-support/src/rustc.rs b/src/tools/run-make-support/src/rustc.rs index 8b0252b8f04c..607f68d12d00 100644 --- a/src/tools/run-make-support/src/rustc.rs +++ b/src/tools/run-make-support/src/rustc.rs @@ -1,10 +1,9 @@ -use std::env; use std::ffi::{OsStr, OsString}; use std::io::Write; use std::path::Path; use std::process::{Command, Output, Stdio}; -use crate::{handle_failed_output, set_host_rpath, tmp_dir}; +use crate::{env_var, handle_failed_output, set_host_rpath, tmp_dir}; /// Construct a new `rustc` invocation. pub fn rustc() -> Rustc { @@ -26,7 +25,7 @@ pub struct Rustc { crate::impl_common_helpers!(Rustc); fn setup_common() -> Command { - let rustc = env::var("RUSTC").unwrap(); + let rustc = env_var("RUSTC"); let mut cmd = Command::new(rustc); set_host_rpath(&mut cmd); cmd.arg("--out-dir").arg(tmp_dir()).arg("-L").arg(tmp_dir()); diff --git a/src/tools/run-make-support/src/rustdoc.rs b/src/tools/run-make-support/src/rustdoc.rs index 61d7448a6bfe..34d32992e65e 100644 --- a/src/tools/run-make-support/src/rustdoc.rs +++ b/src/tools/run-make-support/src/rustdoc.rs @@ -1,10 +1,9 @@ -use std::env; use std::ffi::OsStr; use std::io::Write; use std::path::Path; use std::process::{Command, Output, Stdio}; -use crate::{handle_failed_output, set_host_rpath}; +use crate::{env_var, env_var_os, handle_failed_output, set_host_rpath}; /// Construct a plain `rustdoc` invocation with no flags set. pub fn bare_rustdoc() -> Rustdoc { @@ -25,7 +24,7 @@ pub struct Rustdoc { crate::impl_common_helpers!(Rustdoc); fn setup_common() -> Command { - let rustdoc = env::var("RUSTDOC").unwrap(); + let rustdoc = env_var("RUSTDOC"); let mut cmd = Command::new(rustdoc); set_host_rpath(&mut cmd); cmd @@ -41,7 +40,7 @@ impl Rustdoc { /// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set. pub fn new() -> Self { let mut cmd = setup_common(); - let target_rpath_dir = env::var_os("TARGET_RPATH_DIR").unwrap(); + let target_rpath_dir = env_var_os("TARGET_RPATH_DIR"); cmd.arg(format!("-L{}", target_rpath_dir.to_string_lossy())); Self { cmd, stdin: None } } diff --git a/tests/run-make/compiler-builtins/rmake.rs b/tests/run-make/compiler-builtins/rmake.rs index f5da50ebb043..f7e73e3506f5 100644 --- a/tests/run-make/compiler-builtins/rmake.rs +++ b/tests/run-make/compiler-builtins/rmake.rs @@ -14,7 +14,6 @@ #![deny(warnings)] -use run_make_support::object; use run_make_support::object::read::archive::ArchiveFile; use run_make_support::object::read::Object; use run_make_support::object::ObjectSection; @@ -22,6 +21,7 @@ use run_make_support::object::ObjectSymbol; use run_make_support::object::RelocationTarget; use run_make_support::set_host_rpath; use run_make_support::tmp_dir; +use run_make_support::{env_var, object}; use std::collections::HashSet; const MANIFEST: &str = r#" @@ -35,7 +35,7 @@ path = "lib.rs""#; fn main() { let target_dir = tmp_dir().join("target"); - let target = std::env::var("TARGET").unwrap(); + let target = env_var("TARGET"); println!("Testing compiler_builtins for {}", target); @@ -44,9 +44,9 @@ fn main() { std::fs::write(&manifest_path, MANIFEST.as_bytes()).unwrap(); std::fs::write(tmp_dir().join("lib.rs"), b"#![no_std]").unwrap(); - let path = std::env::var("PATH").unwrap(); - let rustc = std::env::var("RUSTC").unwrap(); - let bootstrap_cargo = std::env::var("BOOTSTRAP_CARGO").unwrap(); + let path = env_var("PATH"); + let rustc = env_var("RUSTC"); + let bootstrap_cargo = env_var("BOOTSTRAP_CARGO"); let mut cmd = std::process::Command::new(bootstrap_cargo); cmd.args([ "build", diff --git a/tests/run-make/windows-binary-no-external-deps/rmake.rs b/tests/run-make/windows-binary-no-external-deps/rmake.rs index 6704fe041483..ccf2d64c8539 100644 --- a/tests/run-make/windows-binary-no-external-deps/rmake.rs +++ b/tests/run-make/windows-binary-no-external-deps/rmake.rs @@ -2,15 +2,14 @@ //! a "hello world" application by setting `PATH` to `C:\Windows\System32`. //@ only-windows -use run_make_support::{rustc, tmp_dir}; -use std::env; +use run_make_support::{env_var, rustc, tmp_dir}; use std::path::PathBuf; use std::process::Command; fn main() { rustc().input("hello.rs").run(); - let windows_dir = env::var("SystemRoot").unwrap(); + let windows_dir = env_var("SystemRoot"); let system32: PathBuf = [&windows_dir, "System32"].iter().collect(); // Note: This does not use the support wrappers so that we can precisely control the PATH let exe = tmp_dir().join("hello.exe"); From 59e2074c79aaea17ed1b4e16081983e5f03c6bd2 Mon Sep 17 00:00:00 2001 From: Oneirical Date: Tue, 28 May 2024 15:54:09 -0400 Subject: [PATCH 074/154] rewrite suspicious-library in rmake --- src/tools/compiletest/src/header.rs | 1 + .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../incr-prev-body-beyond-eof/rmake.rs | 31 ++++++++----------- tests/run-make/resolve-rename/rmake.rs | 3 +- tests/run-make/suspicious-library/Makefile | 8 ----- tests/run-make/suspicious-library/rmake.rs | 14 +++++++++ 6 files changed, 30 insertions(+), 28 deletions(-) delete mode 100644 tests/run-make/suspicious-library/Makefile create mode 100644 tests/run-make/suspicious-library/rmake.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index c7c807d3e684..a8c2962f779c 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -798,6 +798,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "ignore-none", "ignore-nto", "ignore-nvptx64", + "ignore-nvptx64-nvidia-cuda", "ignore-openbsd", "ignore-pass", "ignore-remote", diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 4e69d67057a7..252ce2c65383 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -246,7 +246,6 @@ run-make/static-pie/Makefile run-make/staticlib-blank-lib/Makefile run-make/staticlib-dylib-linkage/Makefile run-make/std-core-cycle/Makefile -run-make/suspicious-library/Makefile run-make/symbol-mangling-hashed/Makefile run-make/symbol-visibility/Makefile run-make/symbols-include-type-name/Makefile diff --git a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs index 43f137fea20e..8aa3893727f6 100644 --- a/tests/run-make/incr-prev-body-beyond-eof/rmake.rs +++ b/tests/run-make/incr-prev-body-beyond-eof/rmake.rs @@ -7,26 +7,21 @@ // was hashed by rustc in addition to the span length, and the fix still // works. -// FIXME: Ignore flags temporarily disabled for the test. -// ignore-none -// ignore-nvptx64-nvidia-cuda +//@ ignore-none +// reason: no-std is not supported -use run_make_support::{rustc, target, tmp_dir}; +//@ ignore-nvptx64-nvidia-cuda +// FIXME: can't find crate for `std` + +use run_make_support::{rustc, tmp_dir}; use std::fs; fn main() { - fs::create_dir(tmp_dir().join("src")); - fs::create_dir(tmp_dir().join("incr")); - fs::copy("a.rs", tmp_dir().join("main.rs")); - rustc() - .incremental(tmp_dir().join("incr")) - .input(tmp_dir().join("src/main.rs")) - .target(target()) - .run(); - fs::copy("b.rs", tmp_dir().join("main.rs")); - rustc() - .incremental(tmp_dir().join("incr")) - .input(tmp_dir().join("src/main.rs")) - .target(target()) - .run(); + // FIXME(Oneirical): Use run_make_support::fs_wrapper here. + fs::create_dir(tmp_dir().join("src")).unwrap(); + fs::create_dir(tmp_dir().join("incr")).unwrap(); + fs::copy("a.rs", tmp_dir().join("src/main.rs")).unwrap(); + rustc().incremental(tmp_dir().join("incr")).input(tmp_dir().join("src/main.rs")).run(); + fs::copy("b.rs", tmp_dir().join("src/main.rs")).unwrap(); + rustc().incremental(tmp_dir().join("incr")).input(tmp_dir().join("src/main.rs")).run(); } diff --git a/tests/run-make/resolve-rename/rmake.rs b/tests/run-make/resolve-rename/rmake.rs index 7539d367758e..8c6e3c24714e 100644 --- a/tests/run-make/resolve-rename/rmake.rs +++ b/tests/run-make/resolve-rename/rmake.rs @@ -10,6 +10,7 @@ use std::fs; fn main() { rustc().extra_filename("-hash").input("foo.rs").run(); rustc().input("bar.rs").run(); - fs::rename(tmp_dir().join("libfoo-hash.rlib"), tmp_dir().join("libfoo-another-hash.rlib")); + fs::rename(tmp_dir().join("libfoo-hash.rlib"), tmp_dir().join("libfoo-another-hash.rlib")) + .unwrap(); rustc().input("baz.rs").run(); } diff --git a/tests/run-make/suspicious-library/Makefile b/tests/run-make/suspicious-library/Makefile deleted file mode 100644 index 3b5ab3c53a56..000000000000 --- a/tests/run-make/suspicious-library/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# ignore-cross-compile -include ../tools.mk - -all: - $(RUSTC) foo.rs -C prefer-dynamic - touch $(call DYLIB,foo-something-special) - touch $(call DYLIB,foo-something-special2) - $(RUSTC) bar.rs diff --git a/tests/run-make/suspicious-library/rmake.rs b/tests/run-make/suspicious-library/rmake.rs new file mode 100644 index 000000000000..9e91de70bfce --- /dev/null +++ b/tests/run-make/suspicious-library/rmake.rs @@ -0,0 +1,14 @@ +// This test creates some fake dynamic libraries with nothing inside, +// and checks if rustc avoids them and successfully compiles as a result. + +//@ ignore-cross-compile + +use run_make_support::{dynamic_lib, rustc}; +use std::fs::File; + +fn main() { + rustc().input("foo.rs").arg("-Cprefer-dynamic").run(); + File::create(dynamic_lib("foo-something-special")).unwrap(); + File::create(dynamic_lib("foo-something-special2")).unwrap(); + rustc().input("bar.rs").run(); +} From f7c51a2d2f67a118db7de5e810f5acb096659137 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Wed, 22 May 2024 15:18:29 +0200 Subject: [PATCH 075/154] Directly add extension instead of using `Path::with_extension` `Path::with_extension` has a nice footgun when the original path doesn't contain an extension: Anything after the last dot gets removed. --- compiler/rustc_codegen_llvm/src/back/archive.rs | 9 ++------- tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs | 4 ++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/archive.rs b/compiler/rustc_codegen_llvm/src/back/archive.rs index fa7e7e5377a2..a354f3d35361 100644 --- a/compiler/rustc_codegen_llvm/src/back/archive.rs +++ b/compiler/rustc_codegen_llvm/src/back/archive.rs @@ -128,11 +128,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { is_direct_dependency: bool, ) -> PathBuf { let name_suffix = if is_direct_dependency { "_imports" } else { "_imports_indirect" }; - let output_path = { - let mut output_path: PathBuf = tmpdir.to_path_buf(); - output_path.push(format!("{lib_name}{name_suffix}")); - output_path.with_extension("lib") - }; + let output_path = tmpdir.join(format!("{lib_name}{name_suffix}.lib")); let target = &sess.target; let mingw_gnu_toolchain = common::is_mingw_gnu_toolchain(target); @@ -157,8 +153,7 @@ impl ArchiveBuilderBuilder for LlvmArchiveBuilderBuilder { // that loaded but crashed with an AV upon calling one of the imported // functions. Therefore, use binutils to create the import library instead, // by writing a .DEF file to the temp dir and calling binutils's dlltool. - let def_file_path = - tmpdir.join(format!("{lib_name}{name_suffix}")).with_extension("def"); + let def_file_path = tmpdir.join(format!("{lib_name}{name_suffix}.def")); let def_file_content = format!( "EXPORTS\n{}", diff --git a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs index 402efaf50271..ea9d48e7859d 100644 --- a/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs +++ b/tests/ui/rfcs/rfc-2627-raw-dylib/dlltool-failed.rs @@ -3,8 +3,8 @@ //@ needs-dlltool //@ compile-flags: --crate-type lib --emit link //@ normalize-stderr-test: "[^ ']*/dlltool.exe" -> "$$DLLTOOL" -//@ normalize-stderr-test: "[^ ]*/foo.def" -> "$$DEF_FILE" -//@ normalize-stderr-test: "[^ ]*/foo.lib" -> "$$LIB_FILE" +//@ normalize-stderr-test: "[^ ]*/foo.dll_imports.def" -> "$$DEF_FILE" +//@ normalize-stderr-test: "[^ ]*/foo.dll_imports.lib" -> "$$LIB_FILE" //@ normalize-stderr-test: "-m [^ ]*" -> "$$TARGET_MACHINE" //@ normalize-stderr-test: "-f [^ ]*" -> "$$ASM_FLAGS" //@ normalize-stderr-test: "--temp-prefix [^ ]*/foo.dll" -> "$$TEMP_PREFIX" From e7ad2da7f134c66779625a09b134b85ed1c7c7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 4 Jun 2024 19:09:15 +0000 Subject: [PATCH 076/154] When `derive`ing, account for HRTB on `BareFn` fields When given ```rust trait SomeTrait { type SomeType<'a>; } struct Foo { x: for<'a> fn(T::SomeType<'a>) } ``` expand to ```rust impl ::core::clone::Clone for Foo where for<'a> T::SomeType<'a>: ::core::clone::Clone { #[inline] fn clone(&self) -> Foo { Foo { x: ::core::clone::Clone::clone(&self.x) } } } ``` instead of the previous invalid ``` impl ::core::clone::Clone for Foo where T::SomeType<'a>: ::core::clone::Clone { #[inline] fn clone(&self) -> Foo { Foo { x: ::core::clone::Clone::clone(&self.x) } } } ``` Fix #122622. --- .../src/deriving/generic/mod.rs | 12 +++++++++++- .../derive-hrtb-for-bare-fn-field-with-lifetime.rs | 13 +++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 217fa5ff9f1e..ba289f9552e2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -412,6 +412,15 @@ fn find_type_parameters( impl<'a, 'b> visit::Visitor<'a> for Visitor<'a, 'b> { fn visit_ty(&mut self, ty: &'a ast::Ty) { + let stack_len = self.bound_generic_params_stack.len(); + if let ast::TyKind::BareFn(bare_fn) = &ty.kind + && !bare_fn.generic_params.is_empty() + { + // Given a field `x: for<'a> fn(T::SomeType<'a>)`, we wan't to account for `'a` so + // that we generate `where for<'a> T::SomeType<'a>: ::core::clone::Clone`. #122622 + self.bound_generic_params_stack.extend(bare_fn.generic_params.iter().cloned()); + } + if let ast::TyKind::Path(_, path) = &ty.kind && let Some(segment) = path.segments.first() && self.ty_param_names.contains(&segment.ident.name) @@ -422,7 +431,8 @@ fn find_type_parameters( }); } - visit::walk_ty(self, ty) + visit::walk_ty(self, ty); + self.bound_generic_params_stack.truncate(stack_len); } // Place bound generic params on a stack, to extract them when a type is encountered. diff --git a/tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs b/tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs new file mode 100644 index 000000000000..b8a42be6832d --- /dev/null +++ b/tests/ui/derives/derive-hrtb-for-bare-fn-field-with-lifetime.rs @@ -0,0 +1,13 @@ +//@ run-pass +// Issue #122622: `#[derive(Clone)]` should work for HRTB function type taking an associated type +#![allow(dead_code)] +trait SomeTrait { + type SomeType<'a>; +} + +#[derive(Clone)] +struct Foo { + x: for<'a> fn(T::SomeType<'a>) +} + +fn main() {} From 5d26f58423f72e300ef48df591c08e3d446b51aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 4 Jun 2024 00:00:00 +0000 Subject: [PATCH 077/154] Closures are recursively reachable --- compiler/rustc_passes/src/reachable.rs | 1 + tests/ui/cross-crate/auxiliary/static_init_aux.rs | 6 ++++++ tests/ui/cross-crate/static-init.rs | 2 ++ 3 files changed, 9 insertions(+) diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index ab1dd2485566..954a1ab6560f 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -157,6 +157,7 @@ impl<'tcx> ReachableContext<'tcx> { } hir::ImplItemKind::Type(_) => false, }, + Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(..), .. }) => true, _ => false, } } diff --git a/tests/ui/cross-crate/auxiliary/static_init_aux.rs b/tests/ui/cross-crate/auxiliary/static_init_aux.rs index dca708733b92..832cee8d4d4e 100644 --- a/tests/ui/cross-crate/auxiliary/static_init_aux.rs +++ b/tests/ui/cross-crate/auxiliary/static_init_aux.rs @@ -3,6 +3,12 @@ pub static F: fn() = f; pub static G: fn() = G0; pub static H: &(dyn Fn() + Sync) = &h; pub static I: fn() = Helper(j).mk(); +pub static K: fn() -> fn() = { + #[inline(never)] + fn k() {} + #[inline(always)] + || -> fn() { k } +}; static X: u32 = 42; static G0: fn() = g; diff --git a/tests/ui/cross-crate/static-init.rs b/tests/ui/cross-crate/static-init.rs index c4697a1d010c..f8003856c5c4 100644 --- a/tests/ui/cross-crate/static-init.rs +++ b/tests/ui/cross-crate/static-init.rs @@ -8,6 +8,7 @@ static F: fn() = aux::F; static G: fn() = aux::G; static H: &(dyn Fn() + Sync) = aux::H; static I: fn() = aux::I; +static K: fn() -> fn() = aux::K; fn v() -> *const u32 { V @@ -19,4 +20,5 @@ fn main() { G(); H(); I(); + K()(); } From ac96fa44faa786ad5682e6ed7359842d0e6a4b53 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sun, 12 May 2024 21:31:13 -0700 Subject: [PATCH 078/154] Use inline const instead of unsafe to construct arrays in `MaybeUninit` examples. --- library/core/src/mem/maybe_uninit.rs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 026e21586d40..56af7fa9c89c 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -120,12 +120,8 @@ use crate::slice; /// use std::mem::{self, MaybeUninit}; /// /// let data = { -/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is -/// // safe because the type we are claiming to have initialized here is a -/// // bunch of `MaybeUninit`s, which do not require initialization. -/// let mut data: [MaybeUninit>; 1000] = unsafe { -/// MaybeUninit::uninit().assume_init() -/// }; +/// // Create an uninitialized array of `MaybeUninit`. +/// let mut data: [MaybeUninit>; 1000] = [const { MaybeUninit::uninit() }; 1000]; /// /// // Dropping a `MaybeUninit` does nothing, so if there is a panic during this loop, /// // we have a memory leak, but there is no memory safety issue. @@ -147,10 +143,8 @@ use crate::slice; /// ``` /// use std::mem::MaybeUninit; /// -/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is -/// // safe because the type we are claiming to have initialized here is a -/// // bunch of `MaybeUninit`s, which do not require initialization. -/// let mut data: [MaybeUninit; 1000] = unsafe { MaybeUninit::uninit().assume_init() }; +/// // Create an uninitialized array of `MaybeUninit`. +/// let mut data: [MaybeUninit; 1000] = [const { MaybeUninit::uninit() }; 1000]; /// // Count the number of elements we have assigned. /// let mut data_len: usize = 0; /// From ec8fa177190f1f0279fade487dfa4cef23dd1101 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sun, 12 May 2024 21:36:09 -0700 Subject: [PATCH 079/154] Use inline const instead of unsafe to implement `MaybeUninit::uninit_array()`. --- library/core/src/mem/maybe_uninit.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 56af7fa9c89c..4175d4a33294 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -342,8 +342,7 @@ impl MaybeUninit { #[must_use] #[inline(always)] pub const fn uninit_array() -> [Self; N] { - // SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid. - unsafe { MaybeUninit::<[MaybeUninit; N]>::uninit().assume_init() } + [const { MaybeUninit::uninit() }; N] } /// Creates a new `MaybeUninit` in an uninitialized state, with the memory being From 2a219372376fef987ddc79332cd682f17f3ca281 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Tue, 4 Jun 2024 17:50:06 -0600 Subject: [PATCH 080/154] Add a co-maintainer for the two ARMv4T targets --- src/doc/rustc/src/platform-support/armv4t-none-eabi.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md index ab8b4caaadff..0c5129d0efbb 100644 --- a/src/doc/rustc/src/platform-support/armv4t-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv4t-none-eabi.md @@ -12,6 +12,7 @@ overall performance. ## Target Maintainers * [@Lokathor](https://github.com/lokathor) +* [@corwinkuiper](https://github.com/corwinkuiper) ## Testing From e1ae0fa055bf358cec14d41e7ddd96cd8964eb9d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 29 May 2024 16:20:19 +1000 Subject: [PATCH 081/154] `UNICODE_ARRAY` and `ASCII_ARRAY` fixes. - Avoid unnecessary escaping of single quotes within string literals. - Add a missing blank line between two `UNICODE_ARRAY` sections. --- .../rustc_parse/src/lexer/unicode_chars.rs | 75 ++++++++++--------- 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index c9470151a7ba..8eb299108d10 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -129,42 +129,42 @@ pub(super) const UNICODE_ARRAY: &[(char, &str, &str)] = &[ ('。', "Ideographic Full Stop", "."), ('︒', "Presentation Form For Vertical Ideographic Full Stop", "."), - ('՝', "Armenian Comma", "\'"), - (''', "Fullwidth Apostrophe", "\'"), - ('‘', "Left Single Quotation Mark", "\'"), - ('’', "Right Single Quotation Mark", "\'"), - ('‛', "Single High-Reversed-9 Quotation Mark", "\'"), - ('′', "Prime", "\'"), - ('‵', "Reversed Prime", "\'"), - ('՚', "Armenian Apostrophe", "\'"), - ('׳', "Hebrew Punctuation Geresh", "\'"), - ('`', "Grave Accent", "\'"), - ('`', "Greek Varia", "\'"), - ('`', "Fullwidth Grave Accent", "\'"), - ('´', "Acute Accent", "\'"), - ('΄', "Greek Tonos", "\'"), - ('´', "Greek Oxia", "\'"), - ('᾽', "Greek Koronis", "\'"), - ('᾿', "Greek Psili", "\'"), - ('῾', "Greek Dasia", "\'"), - ('ʹ', "Modifier Letter Prime", "\'"), - ('ʹ', "Greek Numeral Sign", "\'"), - ('ˈ', "Modifier Letter Vertical Line", "\'"), - ('ˊ', "Modifier Letter Acute Accent", "\'"), - ('ˋ', "Modifier Letter Grave Accent", "\'"), - ('˴', "Modifier Letter Middle Grave Accent", "\'"), - ('ʻ', "Modifier Letter Turned Comma", "\'"), - ('ʽ', "Modifier Letter Reversed Comma", "\'"), - ('ʼ', "Modifier Letter Apostrophe", "\'"), - ('ʾ', "Modifier Letter Right Half Ring", "\'"), - ('ꞌ', "Latin Small Letter Saltillo", "\'"), - ('י', "Hebrew Letter Yod", "\'"), - ('ߴ', "Nko High Tone Apostrophe", "\'"), - ('ߵ', "Nko Low Tone Apostrophe", "\'"), - ('ᑊ', "Canadian Syllabics West-Cree P", "\'"), - ('ᛌ', "Runic Letter Short-Twig-Sol S", "\'"), - ('𖽑', "Miao Sign Aspiration", "\'"), - ('𖽒', "Miao Sign Reformed Voicing", "\'"), + ('՝', "Armenian Comma", "'"), + (''', "Fullwidth Apostrophe", "'"), + ('‘', "Left Single Quotation Mark", "'"), + ('’', "Right Single Quotation Mark", "'"), + ('‛', "Single High-Reversed-9 Quotation Mark", "'"), + ('′', "Prime", "'"), + ('‵', "Reversed Prime", "'"), + ('՚', "Armenian Apostrophe", "'"), + ('׳', "Hebrew Punctuation Geresh", "'"), + ('`', "Grave Accent", "'"), + ('`', "Greek Varia", "'"), + ('`', "Fullwidth Grave Accent", "'"), + ('´', "Acute Accent", "'"), + ('΄', "Greek Tonos", "'"), + ('´', "Greek Oxia", "'"), + ('᾽', "Greek Koronis", "'"), + ('᾿', "Greek Psili", "'"), + ('῾', "Greek Dasia", "'"), + ('ʹ', "Modifier Letter Prime", "'"), + ('ʹ', "Greek Numeral Sign", "'"), + ('ˈ', "Modifier Letter Vertical Line", "'"), + ('ˊ', "Modifier Letter Acute Accent", "'"), + ('ˋ', "Modifier Letter Grave Accent", "'"), + ('˴', "Modifier Letter Middle Grave Accent", "'"), + ('ʻ', "Modifier Letter Turned Comma", "'"), + ('ʽ', "Modifier Letter Reversed Comma", "'"), + ('ʼ', "Modifier Letter Apostrophe", "'"), + ('ʾ', "Modifier Letter Right Half Ring", "'"), + ('ꞌ', "Latin Small Letter Saltillo", "'"), + ('י', "Hebrew Letter Yod", "'"), + ('ߴ', "Nko High Tone Apostrophe", "'"), + ('ߵ', "Nko Low Tone Apostrophe", "'"), + ('ᑊ', "Canadian Syllabics West-Cree P", "'"), + ('ᛌ', "Runic Letter Short-Twig-Sol S", "'"), + ('𖽑', "Miao Sign Aspiration", "'"), + ('𖽒', "Miao Sign Reformed Voicing", "'"), ('᳓', "Vedic Sign Nihshvasa", "\""), ('"', "Fullwidth Quotation Mark", "\""), @@ -298,6 +298,7 @@ pub(super) const UNICODE_ARRAY: &[(char, &str, &str)] = &[ ('〉', "Right Angle Bracket", ">"), ('》', "Right Double Angle Bracket", ">"), ('>', "Fullwidth Greater-Than Sign", ">"), + ('⩵', "Two Consecutive Equals Signs", "==") ]; @@ -332,7 +333,7 @@ const ASCII_ARRAY: &[(&str, &str, Option)] = &[ (">", "Greater-Than Sign", Some(token::Gt)), // FIXME: Literals are already lexed by this point, so we can't recover gracefully just by // spitting the correct token out. - ("\'", "Single Quote", None), + ("'", "Single Quote", None), ("\"", "Quotation Mark", None), ]; From d1215da26e7848bd925a9fffecdaa7ea51b360c3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 09:23:35 +1000 Subject: [PATCH 082/154] Don't use the word "parse" for lexing operations. Lexing converts source text into a token stream. Parsing converts a token stream into AST fragments. This commit renames several lexing operations that have "parse" in the name. I think these names have been subtly confusing me for years. This is just a `s/parse/lex/` on function names, with one exception: `parse_stream_from_source_str` becomes `source_str_to_stream`, to make it consistent with the existing `source_file_to_stream`. The commit also moves that function's location in the file to be just above `source_file_to_stream`. The commit also cleans up a few comments along the way. --- .../rustc_expand/src/proc_macro_server.rs | 4 +- compiler/rustc_parse/src/lexer/mod.rs | 4 +- compiler/rustc_parse/src/lexer/tokentrees.rs | 47 +++++++++---------- compiler/rustc_parse/src/lib.rs | 24 +++++----- .../passes/lint/check_code_block_syntax.rs | 11 ++--- 5 files changed, 41 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index c2e799abae80..3b167c42e57d 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -13,7 +13,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult}; use rustc_parse::lexer::nfc_normalize; -use rustc_parse::parse_stream_from_source_str; +use rustc_parse::source_str_to_stream; use rustc_session::parse::ParseSess; use rustc_span::def_id::CrateNum; use rustc_span::symbol::{self, sym, Symbol}; @@ -538,7 +538,7 @@ impl server::TokenStream for Rustc<'_, '_> { } fn from_str(&mut self, src: &str) -> Self::TokenStream { - parse_stream_from_source_str( + source_str_to_stream( FileName::proc_macro_source_code(src), src.to_string(), self.psess(), diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index d3a6a0339784..43f4963b27ac 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -42,7 +42,7 @@ pub(crate) struct UnmatchedDelim { pub candidate_span: Option, } -pub(crate) fn parse_token_trees<'psess, 'src>( +pub(crate) fn lex_token_trees<'psess, 'src>( psess: &'psess ParseSess, mut src: &'src str, mut start_pos: BytePos, @@ -66,7 +66,7 @@ pub(crate) fn parse_token_trees<'psess, 'src>( last_lifetime: None, }; let (stream, res, unmatched_delims) = - tokentrees::TokenTreesReader::parse_all_token_trees(string_reader); + tokentrees::TokenTreesReader::lex_all_token_trees(string_reader); match res { Ok(()) if unmatched_delims.is_empty() => Ok(stream), _ => { diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index eabe0226b2fb..fcbfa108d066 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -17,7 +17,7 @@ pub(super) struct TokenTreesReader<'psess, 'src> { } impl<'psess, 'src> TokenTreesReader<'psess, 'src> { - pub(super) fn parse_all_token_trees( + pub(super) fn lex_all_token_trees( string_reader: StringReader<'psess, 'src>, ) -> (TokenStream, Result<(), Vec>>, Vec) { let mut tt_reader = TokenTreesReader { @@ -25,14 +25,13 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { token: Token::dummy(), diag_info: TokenTreeDiagInfo::default(), }; - let (_open_spacing, stream, res) = - tt_reader.parse_token_trees(/* is_delimited */ false); + let (_open_spacing, stream, res) = tt_reader.lex_token_trees(/* is_delimited */ false); (stream, res, tt_reader.diag_info.unmatched_delims) } - // Parse a stream of tokens into a list of `TokenTree`s. The `Spacing` in - // the result is that of the opening delimiter. - fn parse_token_trees( + // Lex into a token stream. The `Spacing` in the result is that of the + // opening delimiter. + fn lex_token_trees( &mut self, is_delimited: bool, ) -> (Spacing, TokenStream, Result<(), Vec>>) { @@ -42,12 +41,10 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { let mut buf = Vec::new(); loop { match self.token.kind { - token::OpenDelim(delim) => { - buf.push(match self.parse_token_tree_open_delim(delim) { - Ok(val) => val, - Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)), - }) - } + token::OpenDelim(delim) => buf.push(match self.lex_token_tree_open_delim(delim) { + Ok(val) => val, + Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)), + }), token::CloseDelim(delim) => { return ( open_spacing, @@ -95,24 +92,24 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { err } - fn parse_token_tree_open_delim( + fn lex_token_tree_open_delim( &mut self, open_delim: Delimiter, ) -> Result>> { - // The span for beginning of the delimited section + // The span for beginning of the delimited section. let pre_span = self.token.span; self.diag_info.open_braces.push((open_delim, self.token.span)); - // Parse the token trees within the delimiters. + // Lex the token trees within the delimiters. // We stop at any delimiter so we can try to recover if the user // uses an incorrect delimiter. - let (open_spacing, tts, res) = self.parse_token_trees(/* is_delimited */ true); + let (open_spacing, tts, res) = self.lex_token_trees(/* is_delimited */ true); if let Err(errs) = res { return Err(self.unclosed_delim_err(tts, errs)); } - // Expand to cover the entire delimited token tree + // Expand to cover the entire delimited token tree. let delim_span = DelimSpan::from_pair(pre_span, self.token.span); let sm = self.string_reader.psess.source_map(); @@ -150,7 +147,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { self.diag_info.last_unclosed_found_span = Some(self.token.span); // This is a conservative error: only report the last unclosed // delimiter. The previous unclosed delimiters could actually be - // closed! The parser just hasn't gotten to them yet. + // closed! The lexer just hasn't gotten to them yet. if let Some(&(_, sp)) = self.diag_info.open_braces.last() { unclosed_delimiter = Some(sp); }; @@ -236,9 +233,9 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { // out instead of complaining about the unclosed delims. let mut parser = crate::stream_to_parser(self.string_reader.psess, tts, None); let mut diff_errs = vec![]; - // Suggest removing a `{` we think appears in an `if`/`while` condition - // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, but - // we have no way of tracking this in the lexer itself, so we piggyback on the parser + // Suggest removing a `{` we think appears in an `if`/`while` condition. + // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, + // but we have no way of tracking this in the lexer itself, so we piggyback on the parser. let mut in_cond = false; while parser.token != token::Eof { if let Err(diff_err) = parser.err_vcs_conflict_marker() { @@ -249,14 +246,15 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { parser.token.kind, token::CloseDelim(Delimiter::Brace) | token::FatArrow ) { - // end of the `if`/`while` body, or the end of a `match` guard + // End of the `if`/`while` body, or the end of a `match` guard. in_cond = false; } else if in_cond && parser.token == token::OpenDelim(Delimiter::Brace) { // Store the `&&` and `let` to use their spans later when creating the diagnostic let maybe_andand = parser.look_ahead(1, |t| t.clone()); let maybe_let = parser.look_ahead(2, |t| t.clone()); if maybe_andand == token::OpenDelim(Delimiter::Brace) { - // This might be the beginning of the `if`/`while` body (i.e., the end of the condition) + // This might be the beginning of the `if`/`while` body (i.e., the end of the + // condition). in_cond = false; } else if maybe_andand == token::AndAnd && maybe_let.is_keyword(kw::Let) { let mut err = parser.dcx().struct_span_err( @@ -288,8 +286,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { } fn close_delim_err(&mut self, delim: Delimiter) -> PErr<'psess> { - // An unexpected closing delimiter (i.e., there is no - // matching opening delimiter). + // An unexpected closing delimiter (i.e., there is no matching opening delimiter). let token_str = token_to_string(&self.token); let msg = format!("unexpected closing delimiter: `{token_str}`"); let mut err = self.string_reader.psess.dcx.struct_span_err(self.token.span, msg); diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 322739be3fb3..b4610447be7b 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -84,15 +84,6 @@ pub fn parse_crate_attrs_from_source_str( new_parser_from_source_str(psess, name, source).parse_inner_attributes() } -pub fn parse_stream_from_source_str( - name: FileName, - source: String, - psess: &ParseSess, - override_span: Option, -) -> TokenStream { - source_file_to_stream(psess, psess.source_map().new_source_file(name, source), override_span) -} - /// Creates a new parser from a source string. pub fn new_parser_from_source_str(psess: &ParseSess, name: FileName, source: String) -> Parser<'_> { panictry_buffer!(maybe_new_parser_from_source_str(psess, name, source)) @@ -142,6 +133,15 @@ fn maybe_source_file_to_parser( // Base abstractions +pub fn source_str_to_stream( + name: FileName, + source: String, + psess: &ParseSess, + override_span: Option, +) -> TokenStream { + source_file_to_stream(psess, psess.source_map().new_source_file(name, source), override_span) +} + /// Given a `source_file`, produces a sequence of token trees. pub fn source_file_to_stream( psess: &ParseSess, @@ -165,7 +165,7 @@ fn maybe_file_to_stream<'psess>( )); }); - lexer::parse_token_trees(psess, src.as_str(), source_file.start_pos, override_span) + lexer::lex_token_trees(psess, src.as_str(), source_file.start_pos, override_span) } /// Given a stream and the `ParseSess`, produces a parser. @@ -195,13 +195,13 @@ pub fn parse_in<'a, T>( pub fn fake_token_stream_for_item(psess: &ParseSess, item: &ast::Item) -> TokenStream { let source = pprust::item_to_string(item); let filename = FileName::macro_expansion_source_code(&source); - parse_stream_from_source_str(filename, source, psess, Some(item.span)) + source_str_to_stream(filename, source, psess, Some(item.span)) } pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> TokenStream { let source = pprust::crate_to_string_for_macros(krate); let filename = FileName::macro_expansion_source_code(&source); - parse_stream_from_source_str(filename, source, psess, Some(krate.spans.inner_span)) + source_str_to_stream(filename, source, psess, Some(krate.spans.inner_span)) } pub fn parse_cfg_attr( diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 39350f4cbbb6..4f044450df27 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -5,7 +5,7 @@ use rustc_errors::{ translation::{to_fluent_args, Translate}, Applicability, DiagCtxt, DiagInner, LazyFallbackBundle, }; -use rustc_parse::parse_stream_from_source_str; +use rustc_parse::source_str_to_stream; use rustc_resolve::rustdoc::source_span_for_markdown_range; use rustc_session::parse::ParseSess; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, Transparency}; @@ -51,13 +51,8 @@ fn check_rust_syntax( let span = DUMMY_SP.apply_mark(expn_id.to_expn_id(), Transparency::Transparent); let is_empty = rustc_driver::catch_fatal_errors(|| { - parse_stream_from_source_str( - FileName::Custom(String::from("doctest")), - source, - &psess, - Some(span), - ) - .is_empty() + source_str_to_stream(FileName::Custom(String::from("doctest")), source, &psess, Some(span)) + .is_empty() }) .unwrap_or(false); let buffer = buffer.borrow(); From f6576249abf9d66b936d55a4d15c44932c800fe2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 10:59:16 +1000 Subject: [PATCH 083/154] Inline and remove `error_malformed_cfg_attr_missing`. It has a single call site. This also means `CFG_ATTR_{GRAMMAR_HELP,NOTE_REF}` can be moved into `parse_cfg_attr`, now that it's the only function that uses them. And the commit removes the line break in the URL. --- compiler/rustc_parse/src/lib.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index b4610447be7b..a3de5db73474 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -208,6 +208,10 @@ pub fn parse_cfg_attr( attr: &Attribute, psess: &ParseSess, ) -> Option<(MetaItem, Vec<(AttrItem, Span)>)> { + const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]"; + const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ + "; + match attr.get_normal_item().args { ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens }) if !tokens.is_empty() => @@ -222,16 +226,12 @@ pub fn parse_cfg_attr( } } } - _ => error_malformed_cfg_attr_missing(attr.span, psess), + _ => { + psess.dcx.emit_err(errors::MalformedCfgAttr { + span: attr.span, + sugg: CFG_ATTR_GRAMMAR_HELP, + }); + } } None } - -const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]"; -const CFG_ATTR_NOTE_REF: &str = "for more information, visit \ - "; - -fn error_malformed_cfg_attr_missing(span: Span, psess: &ParseSess) { - psess.dcx.emit_err(errors::MalformedCfgAttr { span, sugg: CFG_ATTR_GRAMMAR_HELP }); -} From 769ca3f661e3c9ef3b97007f210f73415fb92796 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 11:01:23 +1000 Subject: [PATCH 084/154] Rename `maybe_file_to_stream` as `maybe_source_file_to_stream`. Because it takes an `Lrc`, and for consistency with `source_file_to_stream`. --- compiler/rustc_parse/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index a3de5db73474..a818aae27b10 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -122,7 +122,7 @@ fn maybe_source_file_to_parser( source_file: Lrc, ) -> Result, Vec>> { let end_pos = source_file.end_position(); - let stream = maybe_file_to_stream(psess, source_file, None)?; + let stream = maybe_source_file_to_stream(psess, source_file, None)?; let mut parser = stream_to_parser(psess, stream, None); if parser.token == token::Eof { parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None); @@ -148,12 +148,12 @@ pub fn source_file_to_stream( source_file: Lrc, override_span: Option, ) -> TokenStream { - panictry_buffer!(maybe_file_to_stream(psess, source_file, override_span)) + panictry_buffer!(maybe_source_file_to_stream(psess, source_file, override_span)) } /// Given a source file, produces a sequence of token trees. Returns any buffered errors from /// parsing the token stream. -fn maybe_file_to_stream<'psess>( +fn maybe_source_file_to_stream<'psess>( psess: &'psess ParseSess, source_file: Lrc, override_span: Option, From 3c321b9ea8706ca0b8e05222b82100bad8da805e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 13:32:54 +1000 Subject: [PATCH 085/154] Remove `stream_to_parser`. It's a zero-value wrapper of `Parser::new`. --- compiler/rustc_builtin_macros/src/cfg_eval.rs | 2 +- compiler/rustc_expand/src/base.rs | 6 +++--- compiler/rustc_expand/src/proc_macro.rs | 5 ++--- compiler/rustc_expand/src/proc_macro_server.rs | 7 ++----- compiler/rustc_parse/src/lexer/tokentrees.rs | 3 ++- compiler/rustc_parse/src/lib.rs | 11 +---------- src/tools/rustfmt/src/parse/macros/mod.rs | 4 ++-- 7 files changed, 13 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs index 5f63a8ae0a8c..03aff6f96330 100644 --- a/compiler/rustc_builtin_macros/src/cfg_eval.rs +++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs @@ -196,7 +196,7 @@ impl CfgEval<'_, '_> { // Re-parse the tokens, setting the `capture_cfg` flag to save extra information // to the captured `AttrTokenStream` (specifically, we capture // `AttrTokenTree::AttributesData` for all occurrences of `#[cfg]` and `#[cfg_attr]`) - let mut parser = rustc_parse::stream_to_parser(&self.cfg.sess.psess, orig_tokens, None); + let mut parser = Parser::new(&self.cfg.sess.psess, orig_tokens, None); parser.capture_cfg = true; match parse_annotatable_with(&mut parser) { Ok(a) => annotatable = a, diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 4539129bd0f7..b3f6a35f3a4b 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -15,7 +15,7 @@ use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult}; use rustc_feature::Features; use rustc_lint_defs::{BufferedEarlyLint, RegisteredTools}; -use rustc_parse::{parser, MACRO_ARGUMENTS}; +use rustc_parse::{parser::Parser, MACRO_ARGUMENTS}; use rustc_session::config::CollapseMacroDebuginfo; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; @@ -1149,8 +1149,8 @@ impl<'a> ExtCtxt<'a> { pub fn monotonic_expander<'b>(&'b mut self) -> expand::MacroExpander<'b, 'a> { expand::MacroExpander::new(self, true) } - pub fn new_parser_from_tts(&self, stream: TokenStream) -> parser::Parser<'a> { - rustc_parse::stream_to_parser(&self.sess.psess, stream, MACRO_ARGUMENTS) + pub fn new_parser_from_tts(&self, stream: TokenStream) -> Parser<'a> { + Parser::new(&self.sess.psess, stream, MACRO_ARGUMENTS) } pub fn source_map(&self) -> &'a SourceMap { self.sess.psess.source_map() diff --git a/compiler/rustc_expand/src/proc_macro.rs b/compiler/rustc_expand/src/proc_macro.rs index c11369f505f8..96145affe0ae 100644 --- a/compiler/rustc_expand/src/proc_macro.rs +++ b/compiler/rustc_expand/src/proc_macro.rs @@ -6,7 +6,7 @@ use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; use rustc_errors::ErrorGuaranteed; -use rustc_parse::parser::ForceCollect; +use rustc_parse::parser::{ForceCollect, Parser}; use rustc_session::config::ProcMacroExecutionStrategy; use rustc_span::profiling::SpannedEventArgRecorder; use rustc_span::Span; @@ -154,8 +154,7 @@ impl MultiItemModifier for DeriveProcMacro { }; let error_count_before = ecx.dcx().err_count(); - let mut parser = - rustc_parse::stream_to_parser(&ecx.sess.psess, stream, Some("proc-macro derive")); + let mut parser = Parser::new(&ecx.sess.psess, stream, Some("proc-macro derive")); let mut items = vec![]; loop { diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 3b167c42e57d..9ae9f7c10c01 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -13,6 +13,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult}; use rustc_parse::lexer::nfc_normalize; +use rustc_parse::parser::Parser; use rustc_parse::source_str_to_stream; use rustc_session::parse::ParseSess; use rustc_span::def_id::CrateNum; @@ -553,11 +554,7 @@ impl server::TokenStream for Rustc<'_, '_> { fn expand_expr(&mut self, stream: &Self::TokenStream) -> Result { // Parse the expression from our tokenstream. let expr: PResult<'_, _> = try { - let mut p = rustc_parse::stream_to_parser( - self.psess(), - stream.clone(), - Some("proc_macro expand expr"), - ); + let mut p = Parser::new(self.psess(), stream.clone(), Some("proc_macro expand expr")); let expr = p.parse_expr()?; if p.token != token::Eof { p.unexpected()?; diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index fcbfa108d066..f7645446081a 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -2,6 +2,7 @@ use super::diagnostics::report_suspicious_mismatch_block; use super::diagnostics::same_indentation_level; use super::diagnostics::TokenTreeDiagInfo; use super::{StringReader, UnmatchedDelim}; +use crate::Parser; use rustc_ast::token::{self, Delimiter, Token}; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast_pretty::pprust::token_to_string; @@ -231,7 +232,7 @@ impl<'psess, 'src> TokenTreesReader<'psess, 'src> { ) -> Vec> { // If there are unclosed delims, see if there are diff markers and if so, point them // out instead of complaining about the unclosed delims. - let mut parser = crate::stream_to_parser(self.string_reader.psess, tts, None); + let mut parser = Parser::new(self.string_reader.psess, tts, None); let mut diff_errs = vec![]; // Suggest removing a `{` we think appears in an `if`/`while` condition. // We want to suggest removing a `{` only if we think we're in an `if`/`while` condition, diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index a818aae27b10..5bbbfe1430c3 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -123,7 +123,7 @@ fn maybe_source_file_to_parser( ) -> Result, Vec>> { let end_pos = source_file.end_position(); let stream = maybe_source_file_to_stream(psess, source_file, None)?; - let mut parser = stream_to_parser(psess, stream, None); + let mut parser = Parser::new(psess, stream, None); if parser.token == token::Eof { parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None); } @@ -168,15 +168,6 @@ fn maybe_source_file_to_stream<'psess>( lexer::lex_token_trees(psess, src.as_str(), source_file.start_pos, override_span) } -/// Given a stream and the `ParseSess`, produces a parser. -pub fn stream_to_parser<'a>( - psess: &'a ParseSess, - stream: TokenStream, - subparser_name: Option<&'static str>, -) -> Parser<'a> { - Parser::new(psess, stream, subparser_name) -} - /// Runs the given subparser `f` on the tokens of the given `attr`'s item. pub fn parse_in<'a, T>( psess: &'a ParseSess, diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs index 3cf133c647cc..cbcc0b2d6364 100644 --- a/src/tools/rustfmt/src/parse/macros/mod.rs +++ b/src/tools/rustfmt/src/parse/macros/mod.rs @@ -2,7 +2,7 @@ use rustc_ast::token::{Delimiter, NonterminalKind, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{ast, ptr}; use rustc_parse::parser::{ForceCollect, Parser, Recovery}; -use rustc_parse::{stream_to_parser, MACRO_ARGUMENTS}; +use rustc_parse::MACRO_ARGUMENTS; use rustc_session::parse::ParseSess; use rustc_span::symbol::{self, kw}; use rustc_span::Symbol; @@ -15,7 +15,7 @@ pub(crate) mod cfg_if; pub(crate) mod lazy_static; fn build_stream_parser<'a>(psess: &'a ParseSess, tokens: TokenStream) -> Parser<'a> { - stream_to_parser(psess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden) + Parser::new(psess, tokens, MACRO_ARGUMENTS).recovery(Recovery::Forbidden) } fn build_parser<'a>(context: &RewriteContext<'a>, tokens: TokenStream) -> Parser<'a> { From af13b4892786a3f77d440016409414eeadd7d37e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 13:36:18 +1000 Subject: [PATCH 086/154] Improve `panictry_buffer!`. - Convert it from a macro to a function, which is nicer. - Rename it as `unwrap_or_emit_fatal`, which is clearer. - Fix the comment. In particular, `panictry!` no longer exists. - Remove the unnecessary `use` declaration. --- compiler/rustc_parse/src/lib.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 5bbbfe1430c3..298d02d2e58f 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -39,20 +39,17 @@ rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // uses a HOF to parse anything, and includes file and // `source_str`. -/// A variant of 'panictry!' that works on a `Vec` instead of a single `Diag`. -macro_rules! panictry_buffer { - ($e:expr) => {{ - use std::result::Result::{Err, Ok}; - match $e { - Ok(e) => e, - Err(errs) => { - for e in errs { - e.emit(); - } - FatalError.raise() +// Unwrap the result if `Ok`, otherwise emit the diagnostics and abort. +fn unwrap_or_emit_fatal(expr: Result>>) -> T { + match expr { + Ok(expr) => expr, + Err(errs) => { + for err in errs { + err.emit(); } + FatalError.raise() } - }}; + } } pub fn parse_crate_from_file<'a>(input: &Path, psess: &'a ParseSess) -> PResult<'a, ast::Crate> { @@ -86,7 +83,7 @@ pub fn parse_crate_attrs_from_source_str( /// Creates a new parser from a source string. pub fn new_parser_from_source_str(psess: &ParseSess, name: FileName, source: String) -> Parser<'_> { - panictry_buffer!(maybe_new_parser_from_source_str(psess, name, source)) + unwrap_or_emit_fatal(maybe_new_parser_from_source_str(psess, name, source)) } /// Creates a new parser from a source string. Returns any buffered errors from lexing the initial @@ -112,7 +109,7 @@ pub fn new_parser_from_file<'a>(psess: &'a ParseSess, path: &Path, sp: Option, override_span: Option, ) -> TokenStream { - panictry_buffer!(maybe_source_file_to_stream(psess, source_file, override_span)) + unwrap_or_emit_fatal(maybe_source_file_to_stream(psess, source_file, override_span)) } /// Given a source file, produces a sequence of token trees. Returns any buffered errors from From 29e6e2859be6ea69a486bdc155df9311455f55dc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 13:38:51 +1000 Subject: [PATCH 087/154] Remove low-value comments. The first one is out-of-date -- there are no longer functions expr, item, stmt. And I don't know what a "HOF" is. The second one doesn't really tell you anything. --- compiler/rustc_parse/src/lib.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 298d02d2e58f..2c5a0abc6aca 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -34,11 +34,6 @@ mod errors; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } -// A bunch of utility functions of the form `parse__from_` -// where includes crate, expr, item, stmt, tts, and one that -// uses a HOF to parse anything, and includes file and -// `source_str`. - // Unwrap the result if `Ok`, otherwise emit the diagnostics and abort. fn unwrap_or_emit_fatal(expr: Result>>) -> T { match expr { @@ -128,8 +123,6 @@ fn maybe_source_file_to_parser( Ok(parser) } -// Base abstractions - pub fn source_str_to_stream( name: FileName, source: String, From 191b76ef3116736416c28d39d35102c78cb33a07 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 13:39:24 +1000 Subject: [PATCH 088/154] Rename `maybe_source_file_to_parser` as `maybe_new_parser_from_source_file`. For consistency with `new_parser_from_{file,source_str}` and `maybe_new_parser_from_source_str`. --- compiler/rustc_parse/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 2c5a0abc6aca..1a0535684e8e 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -89,7 +89,7 @@ pub fn maybe_new_parser_from_source_str( name: FileName, source: String, ) -> Result, Vec>> { - maybe_source_file_to_parser(psess, psess.source_map().new_source_file(name, source)) + maybe_new_parser_from_source_file(psess, psess.source_map().new_source_file(name, source)) } /// Creates a new parser, aborting if the file doesn't exist. If a span is given, that is used on @@ -104,12 +104,12 @@ pub fn new_parser_from_file<'a>(psess: &'a ParseSess, path: &Path, sp: Option, ) -> Result, Vec>> { From 8964106e44c39cced6cc039bf512a69513a2bbe5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 13:43:38 +1000 Subject: [PATCH 089/154] Use `source_str_to_stream` in a test file. It does exactly what is required. --- compiler/rustc_parse/src/parser/tests.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index a31e350541ab..b72cfd63d00d 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -1,5 +1,5 @@ use crate::parser::ForceCollect; -use crate::{new_parser_from_source_str, parser::Parser, source_file_to_stream}; +use crate::{new_parser_from_source_str, parser::Parser, source_str_to_stream}; use ast::token::IdentIsRaw; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token}; @@ -82,11 +82,7 @@ where /// Maps a string to tts, using a made-up filename. pub(crate) fn string_to_stream(source_str: String) -> TokenStream { let psess = psess(); - source_file_to_stream( - &psess, - psess.source_map().new_source_file(PathBuf::from("bogofile").into(), source_str), - None, - ) + source_str_to_stream(PathBuf::from("bogofile").into(), source_str, &psess, None) } /// Parses a string, returns a crate. From 25972aec67e900aeefe4014deecf5ef853a4bab4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 13:56:44 +1000 Subject: [PATCH 090/154] Inline and remove `parse_crate{,_attrs}_from_{file,source_str}`. All four functions are simple and have a single call site. This requires making `Parser::parse_inner_attributes` public, which is no big deal. --- compiler/rustc_driver_impl/src/lib.rs | 10 +++++---- compiler/rustc_interface/src/passes.rs | 15 ++++++++----- compiler/rustc_parse/src/lib.rs | 29 ------------------------- compiler/rustc_parse/src/parser/attr.rs | 2 +- 4 files changed, 16 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 627fd74c8d77..236880420fc2 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -32,6 +32,7 @@ use rustc_interface::{interface, Queries}; use rustc_lint::unerased_lint_store; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::locator; +use rustc_parse::{new_parser_from_file, new_parser_from_source_str}; use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType}; use rustc_session::getopts::{self, Matches}; @@ -1264,12 +1265,13 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option(sess: &'a Session) -> PResult<'a, ast::AttrVec> { - match &sess.io.input { - Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.psess), + let mut parser = match &sess.io.input { + Input::File(file) => new_parser_from_file(&sess.psess, file, None), Input::Str { name, input } => { - rustc_parse::parse_crate_attrs_from_source_str(name.clone(), input.clone(), &sess.psess) + new_parser_from_source_str(&sess.psess, name.clone(), input.clone()) } - } + }; + parser.parse_inner_attributes() } /// Runs a closure and catches unwinds triggered by fatal errors. diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index b678582766d5..b3ed66220977 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -19,7 +19,7 @@ use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; -use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr}; +use rustc_parse::{new_parser_from_file, new_parser_from_source_str, validate_attr}; use rustc_passes::{abi_test, hir_stats, layout_test}; use rustc_resolve::Resolver; use rustc_session::code_stats::VTableSizeInfo; @@ -42,11 +42,14 @@ use std::{env, fs, iter}; use tracing::{info, instrument}; pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { - let krate = sess.time("parse_crate", || match &sess.io.input { - Input::File(file) => parse_crate_from_file(file, &sess.psess), - Input::Str { input, name } => { - parse_crate_from_source_str(name.clone(), input.clone(), &sess.psess) - } + let krate = sess.time("parse_crate", || { + let mut parser = match &sess.io.input { + Input::File(file) => new_parser_from_file(&sess.psess, file, None), + Input::Str { input, name } => { + new_parser_from_source_str(&sess.psess, name.clone(), input.clone()) + } + }; + parser.parse_crate_mod() })?; if sess.opts.unstable_opts.input_stats { diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 1a0535684e8e..b804e77e7a4e 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -47,35 +47,6 @@ fn unwrap_or_emit_fatal(expr: Result>>) -> T { } } -pub fn parse_crate_from_file<'a>(input: &Path, psess: &'a ParseSess) -> PResult<'a, ast::Crate> { - let mut parser = new_parser_from_file(psess, input, None); - parser.parse_crate_mod() -} - -pub fn parse_crate_attrs_from_file<'a>( - input: &Path, - psess: &'a ParseSess, -) -> PResult<'a, ast::AttrVec> { - let mut parser = new_parser_from_file(psess, input, None); - parser.parse_inner_attributes() -} - -pub fn parse_crate_from_source_str( - name: FileName, - source: String, - psess: &ParseSess, -) -> PResult<'_, ast::Crate> { - new_parser_from_source_str(psess, name, source).parse_crate_mod() -} - -pub fn parse_crate_attrs_from_source_str( - name: FileName, - source: String, - psess: &ParseSess, -) -> PResult<'_, ast::AttrVec> { - new_parser_from_source_str(psess, name, source).parse_inner_attributes() -} - /// Creates a new parser from a source string. pub fn new_parser_from_source_str(psess: &ParseSess, name: FileName, source: String) -> Parser<'_> { unwrap_or_emit_fatal(maybe_new_parser_from_source_str(psess, name, source)) diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs index a57eb70c7053..4acc610d8c40 100644 --- a/compiler/rustc_parse/src/parser/attr.rs +++ b/compiler/rustc_parse/src/parser/attr.rs @@ -265,7 +265,7 @@ impl<'a> Parser<'a> { /// terminated by a semicolon. /// /// Matches `inner_attrs*`. - pub(crate) fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> { + pub fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> { let mut attrs = ast::AttrVec::new(); loop { let start_pos: u32 = self.num_bump_calls.try_into().unwrap(); From ab192a0c97cd0d03d24e402640576474cb62c972 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 14:33:56 +1000 Subject: [PATCH 091/154] Reorder `source_str_to_stream` arguments. It's the only one of these functions where `psess` isn't the first argument. --- compiler/rustc_expand/src/proc_macro_server.rs | 2 +- compiler/rustc_parse/src/lib.rs | 6 +++--- compiler/rustc_parse/src/parser/tests.rs | 2 +- src/librustdoc/passes/lint/check_code_block_syntax.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 9ae9f7c10c01..330a6c347702 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -540,9 +540,9 @@ impl server::TokenStream for Rustc<'_, '_> { fn from_str(&mut self, src: &str) -> Self::TokenStream { source_str_to_stream( + self.psess(), FileName::proc_macro_source_code(src), src.to_string(), - self.psess(), Some(self.call_site), ) } diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index b804e77e7a4e..5ba6db3b2620 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -95,9 +95,9 @@ fn maybe_new_parser_from_source_file( } pub fn source_str_to_stream( + psess: &ParseSess, name: FileName, source: String, - psess: &ParseSess, override_span: Option, ) -> TokenStream { source_file_to_stream(psess, psess.source_map().new_source_file(name, source), override_span) @@ -147,13 +147,13 @@ pub fn parse_in<'a, T>( pub fn fake_token_stream_for_item(psess: &ParseSess, item: &ast::Item) -> TokenStream { let source = pprust::item_to_string(item); let filename = FileName::macro_expansion_source_code(&source); - source_str_to_stream(filename, source, psess, Some(item.span)) + source_str_to_stream(psess, filename, source, Some(item.span)) } pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> TokenStream { let source = pprust::crate_to_string_for_macros(krate); let filename = FileName::macro_expansion_source_code(&source); - source_str_to_stream(filename, source, psess, Some(krate.spans.inner_span)) + source_str_to_stream(psess, filename, source, Some(krate.spans.inner_span)) } pub fn parse_cfg_attr( diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index b72cfd63d00d..2900d44089ea 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -82,7 +82,7 @@ where /// Maps a string to tts, using a made-up filename. pub(crate) fn string_to_stream(source_str: String) -> TokenStream { let psess = psess(); - source_str_to_stream(PathBuf::from("bogofile").into(), source_str, &psess, None) + source_str_to_stream(&psess, PathBuf::from("bogofile").into(), source_str, None) } /// Parses a string, returns a crate. diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 4f044450df27..409546734cb1 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -51,7 +51,7 @@ fn check_rust_syntax( let span = DUMMY_SP.apply_mark(expn_id.to_expn_id(), Transparency::Transparent); let is_empty = rustc_driver::catch_fatal_errors(|| { - source_str_to_stream(FileName::Custom(String::from("doctest")), source, &psess, Some(span)) + source_str_to_stream(&psess, FileName::Custom(String::from("doctest")), source, Some(span)) .is_empty() }) .unwrap_or(false); From 264dbe4d8145c076557a95a93183b8c1d6e1f564 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 14:38:34 +1000 Subject: [PATCH 092/154] Inline and remove `source_file_to_stream`. It has a single call site. --- compiler/rustc_parse/src/lib.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 5ba6db3b2620..8a061ce8f1b5 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -100,15 +100,7 @@ pub fn source_str_to_stream( source: String, override_span: Option, ) -> TokenStream { - source_file_to_stream(psess, psess.source_map().new_source_file(name, source), override_span) -} - -/// Given a `source_file`, produces a sequence of token trees. -pub fn source_file_to_stream( - psess: &ParseSess, - source_file: Lrc, - override_span: Option, -) -> TokenStream { + let source_file = psess.source_map().new_source_file(name, source); unwrap_or_emit_fatal(maybe_source_file_to_stream(psess, source_file, override_span)) } From b9037339cbc636349b02088486effa21f9ab16aa Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 31 May 2024 15:43:18 +1000 Subject: [PATCH 093/154] Make top-level `rustc_parse` functions fallible. Currently we have an awkward mix of fallible and infallible functions: ``` new_parser_from_source_str maybe_new_parser_from_source_str new_parser_from_file (maybe_new_parser_from_file) // missing (new_parser_from_source_file) // missing maybe_new_parser_from_source_file source_str_to_stream maybe_source_file_to_stream ``` We could add the two missing functions, but instead this commit removes of all the infallible ones and renames the fallible ones leaving us with these which are all fallible: ``` new_parser_from_source_str new_parser_from_file new_parser_from_source_file source_str_to_stream source_file_to_stream ``` This requires making `unwrap_or_emit_fatal` public so callers of formerly infallible functions can still work. This does make some of the call sites slightly more verbose, but I think it's worth it for the simpler API. Also, there are two `catch_unwind` calls and one `catch_fatal_errors` call in this diff that become removable thanks this change. (I will do that in a follow-up PR.) --- .../rustc_builtin_macros/src/cmdline_attrs.rs | 5 +- .../rustc_builtin_macros/src/source_util.rs | 4 +- compiler/rustc_driver_impl/src/lib.rs | 6 +-- compiler/rustc_expand/src/module.rs | 5 +- .../rustc_expand/src/proc_macro_server.rs | 9 ++-- compiler/rustc_interface/src/interface.rs | 6 +-- compiler/rustc_interface/src/passes.rs | 8 +-- compiler/rustc_parse/src/lib.rs | 54 ++++++++++--------- compiler/rustc_parse/src/parser/tests.rs | 22 ++++++-- src/librustdoc/clean/render_macro_matchers.rs | 2 +- src/librustdoc/doctest.rs | 23 ++++---- .../passes/lint/check_code_block_syntax.rs | 11 ++-- .../src/doc/needless_doctest_main.rs | 4 +- src/tools/rustfmt/src/parse/parser.rs | 10 ++-- .../ui-fulldeps/mod_dir_path_canonicalized.rs | 4 +- tests/ui-fulldeps/pprust-expr-roundtrip.rs | 7 +-- 16 files changed, 105 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs index ada82e45712d..e9b63b4abebb 100644 --- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs +++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs @@ -4,16 +4,17 @@ use crate::errors; use rustc_ast::attr::mk_attr; use rustc_ast::token; use rustc_ast::{self as ast, AttrItem, AttrStyle}; +use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_session::parse::ParseSess; use rustc_span::FileName; pub fn inject(krate: &mut ast::Crate, psess: &ParseSess, attrs: &[String]) { for raw_attr in attrs { - let mut parser = rustc_parse::new_parser_from_source_str( + let mut parser = unwrap_or_emit_fatal(new_parser_from_source_str( psess, FileName::cli_crate_attr_source_code(raw_attr), raw_attr.clone(), - ); + )); let start_span = parser.token.span; let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item(false) { diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 29e991525a9b..dc1d82df0c39 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -12,8 +12,8 @@ use rustc_expand::base::{ }; use rustc_expand::module::DirOwnership; use rustc_lint_defs::BuiltinLintDiag; -use rustc_parse::new_parser_from_file; use rustc_parse::parser::{ForceCollect, Parser}; +use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; @@ -126,7 +126,7 @@ pub(crate) fn expand_include<'cx>( return ExpandResult::Ready(DummyResult::any(sp, guar)); } }; - let p = new_parser_from_file(cx.psess(), &file, Some(sp)); + let p = unwrap_or_emit_fatal(new_parser_from_file(cx.psess(), &file, Some(sp))); // If in the included file we have e.g., `mod bar;`, // then the path of `bar.rs` should be relative to the directory of `file`. diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 236880420fc2..93a65290602a 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -32,7 +32,7 @@ use rustc_interface::{interface, Queries}; use rustc_lint::unerased_lint_store; use rustc_metadata::creader::MetadataLoader; use rustc_metadata::locator; -use rustc_parse::{new_parser_from_file, new_parser_from_source_str}; +use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType}; use rustc_session::getopts::{self, Matches}; @@ -1265,12 +1265,12 @@ pub fn handle_options(early_dcx: &EarlyDiagCtxt, args: &[String]) -> Option(sess: &'a Session) -> PResult<'a, ast::AttrVec> { - let mut parser = match &sess.io.input { + let mut parser = unwrap_or_emit_fatal(match &sess.io.input { Input::File(file) => new_parser_from_file(&sess.psess, file, None), Input::Str { name, input } => { new_parser_from_source_str(&sess.psess, name.clone(), input.clone()) } - }; + }); parser.parse_inner_attributes() } diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index c8983619e701..506bd445be35 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -5,8 +5,8 @@ use crate::errors::{ use rustc_ast::ptr::P; use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans}; use rustc_errors::{Diag, ErrorGuaranteed}; -use rustc_parse::new_parser_from_file; use rustc_parse::validate_attr; +use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal}; use rustc_session::parse::ParseSess; use rustc_session::Session; use rustc_span::symbol::{sym, Ident}; @@ -66,7 +66,8 @@ pub(crate) fn parse_external_mod( } // Actually parse the external file as a module. - let mut parser = new_parser_from_file(&sess.psess, &mp.file_path, Some(span)); + let mut parser = + unwrap_or_emit_fatal(new_parser_from_file(&sess.psess, &mp.file_path, Some(span))); let (inner_attrs, items, inner_span) = parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?; attrs.extend(inner_attrs); diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 330a6c347702..93f8682090d7 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -14,7 +14,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{Diag, ErrorGuaranteed, MultiSpan, PResult}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::parser::Parser; -use rustc_parse::source_str_to_stream; +use rustc_parse::{new_parser_from_source_str, source_str_to_stream, unwrap_or_emit_fatal}; use rustc_session::parse::ParseSess; use rustc_span::def_id::CrateNum; use rustc_span::symbol::{self, sym, Symbol}; @@ -467,7 +467,8 @@ impl server::FreeFunctions for Rustc<'_, '_> { fn literal_from_str(&mut self, s: &str) -> Result, ()> { let name = FileName::proc_macro_source_code(s); - let mut parser = rustc_parse::new_parser_from_source_str(self.psess(), name, s.to_owned()); + let mut parser = + unwrap_or_emit_fatal(new_parser_from_source_str(self.psess(), name, s.to_owned())); let first_span = parser.token.span.data(); let minus_present = parser.eat(&token::BinOp(token::Minus)); @@ -539,12 +540,12 @@ impl server::TokenStream for Rustc<'_, '_> { } fn from_str(&mut self, src: &str) -> Self::TokenStream { - source_str_to_stream( + unwrap_or_emit_fatal(source_str_to_stream( self.psess(), FileName::proc_macro_source_code(src), src.to_string(), Some(self.call_site), - ) + )) } fn to_string(&mut self, stream: &Self::TokenStream) -> String { diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 5254a6576f90..c95a10f4e8d2 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -14,7 +14,7 @@ use rustc_lint::LintStore; use rustc_middle::ty; use rustc_middle::ty::CurrentGcx; use rustc_middle::util::Providers; -use rustc_parse::maybe_new_parser_from_source_str; +use rustc_parse::new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; @@ -67,7 +67,7 @@ pub(crate) fn parse_cfg(dcx: &DiagCtxt, cfgs: Vec) -> Cfg { }; } - match maybe_new_parser_from_source_str(&psess, filename, s.to_string()) { + match new_parser_from_source_str(&psess, filename, s.to_string()) { Ok(mut parser) => match parser.parse_meta_item() { Ok(meta_item) if parser.token == token::Eof => { if meta_item.path.segments.len() != 1 { @@ -166,7 +166,7 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec) -> CheckCfg { error!("expected `cfg(name, values(\"value1\", \"value2\", ... \"valueN\"))`") }; - let mut parser = match maybe_new_parser_from_source_str(&psess, filename, s.to_string()) { + let mut parser = match new_parser_from_source_str(&psess, filename, s.to_string()) { Ok(parser) => parser, Err(errs) => { errs.into_iter().for_each(|err| err.cancel()); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index b3ed66220977..a342577cffb8 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -19,7 +19,9 @@ use rustc_middle::arena::Arena; use rustc_middle::dep_graph::DepGraph; use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt}; use rustc_middle::util::Providers; -use rustc_parse::{new_parser_from_file, new_parser_from_source_str, validate_attr}; +use rustc_parse::{ + new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal, validate_attr, +}; use rustc_passes::{abi_test, hir_stats, layout_test}; use rustc_resolve::Resolver; use rustc_session::code_stats::VTableSizeInfo; @@ -43,12 +45,12 @@ use tracing::{info, instrument}; pub fn parse<'a>(sess: &'a Session) -> PResult<'a, ast::Crate> { let krate = sess.time("parse_crate", || { - let mut parser = match &sess.io.input { + let mut parser = unwrap_or_emit_fatal(match &sess.io.input { Input::File(file) => new_parser_from_file(&sess.psess, file, None), Input::Str { input, name } => { new_parser_from_source_str(&sess.psess, name.clone(), input.clone()) } - }; + }); parser.parse_crate_mod() })?; diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 8a061ce8f1b5..b316327a262d 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -35,7 +35,7 @@ mod errors; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } // Unwrap the result if `Ok`, otherwise emit the diagnostics and abort. -fn unwrap_or_emit_fatal(expr: Result>>) -> T { +pub fn unwrap_or_emit_fatal(expr: Result>>) -> T { match expr { Ok(expr) => expr, Err(errs) => { @@ -47,25 +47,28 @@ fn unwrap_or_emit_fatal(expr: Result>>) -> T { } } -/// Creates a new parser from a source string. -pub fn new_parser_from_source_str(psess: &ParseSess, name: FileName, source: String) -> Parser<'_> { - unwrap_or_emit_fatal(maybe_new_parser_from_source_str(psess, name, source)) -} - -/// Creates a new parser from a source string. Returns any buffered errors from lexing the initial -/// token stream; these must be consumed via `emit`, `cancel`, etc., otherwise a panic will occur -/// when they are dropped. -pub fn maybe_new_parser_from_source_str( +/// Creates a new parser from a source string. On failure, the errors must be consumed via +/// `unwrap_or_emit_fatal`, `emit`, `cancel`, etc., otherwise a panic will occur when they are +/// dropped. +pub fn new_parser_from_source_str( psess: &ParseSess, name: FileName, source: String, ) -> Result, Vec>> { - maybe_new_parser_from_source_file(psess, psess.source_map().new_source_file(name, source)) + let source_file = psess.source_map().new_source_file(name, source); + new_parser_from_source_file(psess, source_file) } -/// Creates a new parser, aborting if the file doesn't exist. If a span is given, that is used on -/// an error as the source of the problem. -pub fn new_parser_from_file<'a>(psess: &'a ParseSess, path: &Path, sp: Option) -> Parser<'a> { +/// Creates a new parser from a filename. On failure, the errors must be consumed via +/// `unwrap_or_emit_fatal`, `emit`, `cancel`, etc., otherwise a panic will occur when they are +/// dropped. +/// +/// If a span is given, that is used on an error as the source of the problem. +pub fn new_parser_from_file<'a>( + psess: &'a ParseSess, + path: &Path, + sp: Option, +) -> Result, Vec>> { let source_file = psess.source_map().load_file(path).unwrap_or_else(|e| { let msg = format!("couldn't read {}: {}", path.display(), e); let mut err = psess.dcx.struct_fatal(msg); @@ -74,23 +77,21 @@ pub fn new_parser_from_file<'a>(psess: &'a ParseSess, path: &Path, sp: Option, ) -> Result, Vec>> { let end_pos = source_file.end_position(); - let stream = maybe_source_file_to_stream(psess, source_file, None)?; + let stream = source_file_to_stream(psess, source_file, None)?; let mut parser = Parser::new(psess, stream, None); if parser.token == token::Eof { parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt(), None); } - Ok(parser) } @@ -99,14 +100,14 @@ pub fn source_str_to_stream( name: FileName, source: String, override_span: Option, -) -> TokenStream { +) -> Result>> { let source_file = psess.source_map().new_source_file(name, source); - unwrap_or_emit_fatal(maybe_source_file_to_stream(psess, source_file, override_span)) + source_file_to_stream(psess, source_file, override_span) } /// Given a source file, produces a sequence of token trees. Returns any buffered errors from /// parsing the token stream. -fn maybe_source_file_to_stream<'psess>( +fn source_file_to_stream<'psess>( psess: &'psess ParseSess, source_file: Lrc, override_span: Option, @@ -139,13 +140,18 @@ pub fn parse_in<'a, T>( pub fn fake_token_stream_for_item(psess: &ParseSess, item: &ast::Item) -> TokenStream { let source = pprust::item_to_string(item); let filename = FileName::macro_expansion_source_code(&source); - source_str_to_stream(psess, filename, source, Some(item.span)) + unwrap_or_emit_fatal(source_str_to_stream(psess, filename, source, Some(item.span))) } pub fn fake_token_stream_for_crate(psess: &ParseSess, krate: &ast::Crate) -> TokenStream { let source = pprust::crate_to_string_for_macros(krate); let filename = FileName::macro_expansion_source_code(&source); - source_str_to_stream(psess, filename, source, Some(krate.spans.inner_span)) + unwrap_or_emit_fatal(source_str_to_stream( + psess, + filename, + source, + Some(krate.spans.inner_span), + )) } pub fn parse_cfg_attr( diff --git a/compiler/rustc_parse/src/parser/tests.rs b/compiler/rustc_parse/src/parser/tests.rs index 2900d44089ea..79a6cf1b541e 100644 --- a/compiler/rustc_parse/src/parser/tests.rs +++ b/compiler/rustc_parse/src/parser/tests.rs @@ -1,5 +1,7 @@ use crate::parser::ForceCollect; -use crate::{new_parser_from_source_str, parser::Parser, source_str_to_stream}; +use crate::{ + new_parser_from_source_str, parser::Parser, source_str_to_stream, unwrap_or_emit_fatal, +}; use ast::token::IdentIsRaw; use rustc_ast::ptr::P; use rustc_ast::token::{self, Delimiter, Token}; @@ -29,7 +31,11 @@ fn psess() -> ParseSess { /// Map string to parser (via tts). fn string_to_parser(psess: &ParseSess, source_str: String) -> Parser<'_> { - new_parser_from_source_str(psess, PathBuf::from("bogofile").into(), source_str) + unwrap_or_emit_fatal(new_parser_from_source_str( + psess, + PathBuf::from("bogofile").into(), + source_str, + )) } fn create_test_handler() -> (DiagCtxt, Lrc, Arc>>) { @@ -82,7 +88,12 @@ where /// Maps a string to tts, using a made-up filename. pub(crate) fn string_to_stream(source_str: String) -> TokenStream { let psess = psess(); - source_str_to_stream(&psess, PathBuf::from("bogofile").into(), source_str, None) + unwrap_or_emit_fatal(source_str_to_stream( + &psess, + PathBuf::from("bogofile").into(), + source_str, + None, + )) } /// Parses a string, returns a crate. @@ -1064,7 +1075,8 @@ fn parse_item_from_source_str( source: String, psess: &ParseSess, ) -> PResult<'_, Option>> { - new_parser_from_source_str(psess, name, source).parse_item(ForceCollect::No) + unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)) + .parse_item(ForceCollect::No) } // Produces a `rustc_span::span`. @@ -1345,7 +1357,7 @@ fn ttdelim_span() { source: String, psess: &ParseSess, ) -> PResult<'_, P> { - new_parser_from_source_str(psess, name, source).parse_expr() + unwrap_or_emit_fatal(new_parser_from_source_str(psess, name, source)).parse_expr() } create_default_session_globals_then(|| { diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs index 5ac1b742c386..995919f73f83 100644 --- a/src/librustdoc/clean/render_macro_matchers.rs +++ b/src/librustdoc/clean/render_macro_matchers.rs @@ -65,7 +65,7 @@ fn snippet_equal_to_token(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Option parser, Err(errs) => { errs.into_iter().for_each(|err| err.cancel()); diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index a536a7139219..0d4bad6921db 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -9,7 +9,7 @@ use rustc_interface::interface; use rustc_middle::hir::map::Map; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; -use rustc_parse::maybe_new_parser_from_source_str; +use rustc_parse::new_parser_from_source_str; use rustc_parse::parser::attr::InnerAttrPolicy; use rustc_resolve::rustdoc::span_of_fragments; use rustc_session::config::{self, CrateType, ErrorOutputType}; @@ -638,7 +638,7 @@ pub(crate) fn make_test( let mut found_extern_crate = crate_name.is_none(); let mut found_macro = false; - let mut parser = match maybe_new_parser_from_source_str(&psess, filename, source) { + let mut parser = match new_parser_from_source_str(&psess, filename, source) { Ok(p) => p, Err(errs) => { errs.into_iter().for_each(|err| err.cancel()); @@ -818,16 +818,15 @@ fn check_if_attr_is_complete(source: &str, edition: Edition) -> bool { let dcx = DiagCtxt::new(Box::new(emitter)).disable_warnings(); let psess = ParseSess::with_dcx(dcx, sm); - let mut parser = - match maybe_new_parser_from_source_str(&psess, filename, source.to_owned()) { - Ok(p) => p, - Err(errs) => { - errs.into_iter().for_each(|err| err.cancel()); - // If there is an unclosed delimiter, an error will be returned by the - // tokentrees. - return false; - } - }; + let mut parser = match new_parser_from_source_str(&psess, filename, source.to_owned()) { + Ok(p) => p, + Err(errs) => { + errs.into_iter().for_each(|err| err.cancel()); + // If there is an unclosed delimiter, an error will be returned by the + // tokentrees. + return false; + } + }; // If a parsing error happened, it's very likely that the attribute is incomplete. if let Err(e) = parser.parse_attribute(InnerAttrPolicy::Permitted) { e.cancel(); diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 409546734cb1..c185442fd55d 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -5,7 +5,7 @@ use rustc_errors::{ translation::{to_fluent_args, Translate}, Applicability, DiagCtxt, DiagInner, LazyFallbackBundle, }; -use rustc_parse::source_str_to_stream; +use rustc_parse::{source_str_to_stream, unwrap_or_emit_fatal}; use rustc_resolve::rustdoc::source_span_for_markdown_range; use rustc_session::parse::ParseSess; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, Transparency}; @@ -51,8 +51,13 @@ fn check_rust_syntax( let span = DUMMY_SP.apply_mark(expn_id.to_expn_id(), Transparency::Transparent); let is_empty = rustc_driver::catch_fatal_errors(|| { - source_str_to_stream(&psess, FileName::Custom(String::from("doctest")), source, Some(span)) - .is_empty() + unwrap_or_emit_fatal(source_str_to_stream( + &psess, + FileName::Custom(String::from("doctest")), + source, + Some(span), + )) + .is_empty() }) .unwrap_or(false); let buffer = buffer.borrow(); diff --git a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs index 651f2ebaee6f..c3e3c0431e6b 100644 --- a/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs +++ b/src/tools/clippy/clippy_lints/src/doc/needless_doctest_main.rs @@ -8,7 +8,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::emitter::HumanEmitter; use rustc_errors::{Diag, DiagCtxt}; use rustc_lint::LateContext; -use rustc_parse::maybe_new_parser_from_source_str; +use rustc_parse::new_parser_from_source_str; use rustc_parse::parser::ForceCollect; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; @@ -50,7 +50,7 @@ pub fn check( let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let psess = ParseSess::with_dcx(dcx, sm); - let mut parser = match maybe_new_parser_from_source_str(&psess, filename, code) { + let mut parser = match new_parser_from_source_str(&psess, filename, code) { Ok(p) => p, Err(errs) => { errs.into_iter().for_each(Diag::cancel); diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs index 5dcdca1d9538..7adf339b453a 100644 --- a/src/tools/rustfmt/src/parse/parser.rs +++ b/src/tools/rustfmt/src/parse/parser.rs @@ -4,7 +4,8 @@ use std::path::{Path, PathBuf}; use rustc_ast::token::TokenKind; use rustc_ast::{ast, attr, ptr}; use rustc_errors::Diag; -use rustc_parse::{new_parser_from_file, parser::Parser as RawParser}; +use rustc_parse::parser::Parser as RawParser; +use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal}; use rustc_span::{sym, Span}; use thin_vec::ThinVec; @@ -68,10 +69,10 @@ impl<'a> ParserBuilder<'a> { ) -> Result, Option>>> { match input { Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || { - new_parser_from_file(psess, file, None) + unwrap_or_emit_fatal(new_parser_from_file(psess, file, None)) })) .map_err(|_| None), - Input::Text(text) => rustc_parse::maybe_new_parser_from_source_str( + Input::Text(text) => rustc_parse::new_parser_from_source_str( psess, rustc_span::FileName::Custom("stdin".to_owned()), text, @@ -111,7 +112,8 @@ impl<'a> Parser<'a> { span: Span, ) -> Result<(ast::AttrVec, ThinVec>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { - let mut parser = new_parser_from_file(psess.inner(), path, Some(span)); + let mut parser = + unwrap_or_emit_fatal(new_parser_from_file(psess.inner(), path, Some(span))); match parser.parse_mod(&TokenKind::Eof) { Ok((a, i, spans)) => Some((a, i, spans.inner_span)), Err(e) => { diff --git a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs index ef70e64ed7e9..99cb5fc5aa1c 100644 --- a/tests/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/tests/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -16,7 +16,7 @@ extern crate rustc_span; #[allow(unused_extern_crates)] extern crate rustc_driver; -use rustc_parse::new_parser_from_file; +use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal}; use rustc_session::parse::ParseSess; use std::path::Path; @@ -34,6 +34,6 @@ fn parse() { let path = Path::new(file!()); let path = path.canonicalize().unwrap(); - let mut parser = new_parser_from_file(&psess, &path, None); + let mut parser = unwrap_or_emit_fatal(new_parser_from_file(&psess, &path, None)); let _ = parser.parse_crate_mod(); } diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs index 2b1fec943871..762ad0b79ecc 100644 --- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs @@ -36,7 +36,7 @@ use rustc_ast::mut_visit::{visit_clobber, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::*; use rustc_ast_pretty::pprust; -use rustc_parse::new_parser_from_source_str; +use rustc_parse::{new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_session::parse::ParseSess; use rustc_span::source_map::Spanned; use rustc_span::symbol::Ident; @@ -46,8 +46,9 @@ use thin_vec::{thin_vec, ThinVec}; fn parse_expr(psess: &ParseSess, src: &str) -> Option> { let src_as_string = src.to_string(); - let mut p = - new_parser_from_source_str(psess, FileName::Custom(src_as_string.clone()), src_as_string); + let mut p = unwrap_or_emit_fatal( + new_parser_from_source_str(psess, FileName::Custom(src_as_string.clone()), src_as_string) + ); p.parse_expr().map_err(|e| e.cancel()).ok() } From 2d4e7df14422ec46422e79ddae5af3ed78632bef Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 3 Jun 2024 14:32:03 +1000 Subject: [PATCH 094/154] rustfmt: Remove an unnecessary `catch_unwind` use. The `Input::File` and `Input::Text` cases should be very similar. However, currently the `Input::File` case uses `catch_unwind` because, until recently (#125815) there was a fallible version of `new_parser_from_source_str` but only an infallible version of `new_parser_from_file`. This difference wasn't fundamental, just an overlooked gap in the API of `rustc_parse`. Both of those operations are now fallible, so the `Input::File` and `Input::Text` cases can made more similar, with no need for `catch_unwind`. This also lets us simplify an `Option>` to `Vec`. --- src/tools/rustfmt/src/parse/parser.rs | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs index 7adf339b453a..6051241309d1 100644 --- a/src/tools/rustfmt/src/parse/parser.rs +++ b/src/tools/rustfmt/src/parse/parser.rs @@ -5,7 +5,7 @@ use rustc_ast::token::TokenKind; use rustc_ast::{ast, attr, ptr}; use rustc_errors::Diag; use rustc_parse::parser::Parser as RawParser; -use rustc_parse::{new_parser_from_file, unwrap_or_emit_fatal}; +use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal}; use rustc_span::{sym, Span}; use thin_vec::ThinVec; @@ -51,12 +51,9 @@ impl<'a> ParserBuilder<'a> { let parser = match Self::parser(psess.inner(), input) { Ok(p) => p, - Err(db) => { - if let Some(diagnostics) = db { - psess.emit_diagnostics(diagnostics); - return Err(ParserError::ParserCreationError); - } - return Err(ParserError::ParsePanicError); + Err(diagnostics) => { + psess.emit_diagnostics(diagnostics); + return Err(ParserError::ParserCreationError); } }; @@ -66,18 +63,14 @@ impl<'a> ParserBuilder<'a> { fn parser( psess: &'a rustc_session::parse::ParseSess, input: Input, - ) -> Result, Option>>> { + ) -> Result, Vec>> { match input { - Input::File(ref file) => catch_unwind(AssertUnwindSafe(move || { - unwrap_or_emit_fatal(new_parser_from_file(psess, file, None)) - })) - .map_err(|_| None), - Input::Text(text) => rustc_parse::new_parser_from_source_str( + Input::File(ref file) => new_parser_from_file(psess, file, None), + Input::Text(text) => new_parser_from_source_str( psess, rustc_span::FileName::Custom("stdin".to_owned()), text, - ) - .map_err(Some), + ), } } } From dd6bca56ecb354a80ba4c818c47f92e6a88d611a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 4 Jun 2024 21:06:29 -0400 Subject: [PATCH 095/154] Add another test for hidden types capturing lifetimes that outlive but arent mentioned in substs --- .../tait-hidden-erased-unsoundness-2.rs | 38 +++++++++++++++++++ .../tait-hidden-erased-unsoundness-2.stderr | 15 ++++++++ 2 files changed, 53 insertions(+) create mode 100644 tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs create mode 100644 tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs new file mode 100644 index 000000000000..65e90c1ca53c --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs @@ -0,0 +1,38 @@ +// This test should never pass! + +#![feature(type_alias_impl_trait)] + +pub trait Captures<'a> {} +impl Captures<'_> for T {} + +pub struct MyTy<'a, 'b>(Option<*mut &'a &'b ()>); +unsafe impl Send for MyTy<'_, 'static> {} + +pub mod step1 { + use super::*; + pub type Step1<'a, 'b: 'a> = impl Sized + Captures<'b> + 'a; + pub fn step1<'a, 'b: 'a>() -> Step1<'a, 'b> { + MyTy::<'a, 'b>(None) + } +} + +pub mod step2 { + pub type Step2<'a> = impl Send + 'a; + + // Although `Step2` is WF at the definition site, it's not WF in its + // declaration site (above). We check this in `check_opaque_meets_bounds`, + // which must remain sound. + pub fn step2<'a, 'b: 'a>() -> Step2<'a> + where crate::step1::Step1<'a, 'b>: Send + { + crate::step1::step1::<'a, 'b>() + //~^ ERROR hidden type for `Step2<'a>` captures lifetime that does not appear in bounds + } +} + +fn step3<'a, 'b>() { + fn is_send() {} + is_send::>(); +} + +fn main() {} diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr new file mode 100644 index 000000000000..58d7f9959d34 --- /dev/null +++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr @@ -0,0 +1,15 @@ +error[E0700]: hidden type for `Step2<'a>` captures lifetime that does not appear in bounds + --> $DIR/tait-hidden-erased-unsoundness-2.rs:28:9 + | +LL | pub type Step2<'a> = impl Send + 'a; + | -------------- opaque type defined here +... +LL | pub fn step2<'a, 'b: 'a>() -> Step2<'a> + | -- hidden type `Step1<'a, 'b>` captures the lifetime `'b` as defined here +... +LL | crate::step1::step1::<'a, 'b>() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0700`. From 72be5044b535d4a8dc64916bb33e533f15645b07 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 4 Jun 2024 21:26:40 -0400 Subject: [PATCH 096/154] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 7a6fad0984d2..34a6a87d8a23 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 7a6fad0984d28c8330974636972aa296b67c4513 +Subproject commit 34a6a87d8a2330d8c9d578f927489689328a652d From 54b2e86db7f522294254ae5e4572feba28e0b929 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jun 2024 12:56:38 +1000 Subject: [PATCH 097/154] Port `tests/run-make-fulldeps/issue-19371` to ui-fulldeps --- src/tools/compiletest/src/header.rs | 10 +++++ tests/run-make-fulldeps/issue-19371/Makefile | 9 ----- .../run-compiler-twice.rs} | 38 ++++++++++++------- 3 files changed, 34 insertions(+), 23 deletions(-) delete mode 100644 tests/run-make-fulldeps/issue-19371/Makefile rename tests/{run-make-fulldeps/issue-19371/foo.rs => ui-fulldeps/run-compiler-twice.rs} (65%) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a2cdf800a971..f8400801a3c5 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -1267,6 +1267,8 @@ fn expand_variables(mut value: String, config: &Config) -> String { const CWD: &str = "{{cwd}}"; const SRC_BASE: &str = "{{src-base}}"; const BUILD_BASE: &str = "{{build-base}}"; + const SYSROOT_BASE: &str = "{{sysroot-base}}"; + const TARGET_LINKER: &str = "{{target-linker}}"; if value.contains(CWD) { let cwd = env::current_dir().unwrap(); @@ -1281,6 +1283,14 @@ fn expand_variables(mut value: String, config: &Config) -> String { value = value.replace(BUILD_BASE, &config.build_base.to_string_lossy()); } + if value.contains(SYSROOT_BASE) { + value = value.replace(SYSROOT_BASE, &config.sysroot_base.to_string_lossy()); + } + + if value.contains(TARGET_LINKER) { + value = value.replace(TARGET_LINKER, config.target_linker.as_deref().unwrap_or("")); + } + value } diff --git a/tests/run-make-fulldeps/issue-19371/Makefile b/tests/run-make-fulldeps/issue-19371/Makefile deleted file mode 100644 index edec68f08623..000000000000 --- a/tests/run-make-fulldeps/issue-19371/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -include ../../run-make/tools.mk - -# This test ensures that rustc compile_input can be called twice in one task -# without causing a panic. -# The program needs the path to rustc to get sysroot. - -all: - $(RUSTC) foo.rs - $(call RUN,foo $(TMPDIR) $(RUSTC)) diff --git a/tests/run-make-fulldeps/issue-19371/foo.rs b/tests/ui-fulldeps/run-compiler-twice.rs similarity index 65% rename from tests/run-make-fulldeps/issue-19371/foo.rs rename to tests/ui-fulldeps/run-compiler-twice.rs index 327c99a02c6f..02748626723d 100644 --- a/tests/run-make-fulldeps/issue-19371/foo.rs +++ b/tests/ui-fulldeps/run-compiler-twice.rs @@ -1,3 +1,13 @@ +//@ edition: 2021 +//@ run-pass +//@ run-flags: {{sysroot-base}} {{target-linker}} +//@ ignore-stage1 (requires matching sysroot built with in-tree compiler) + +// Regression test for . +// +// This test ensures that `compile_input` can be called twice in one task +// without causing a panic. + #![feature(rustc_private)] extern crate rustc_driver; @@ -5,12 +15,12 @@ extern crate rustc_interface; extern crate rustc_session; extern crate rustc_span; +use std::path::{Path, PathBuf}; + use rustc_interface::interface; use rustc_session::config::{Input, Options, OutFileName, OutputType, OutputTypes}; use rustc_span::FileName; -use std::path::PathBuf; - fn main() { let src = r#" fn main() {} @@ -18,28 +28,28 @@ fn main() { let args: Vec = std::env::args().collect(); - if args.len() < 4 { - panic!("expected rustc path"); + if args.len() < 2 { + panic!("expected sysroot (and optional linker)"); } - let tmpdir = PathBuf::from(&args[1]); + let sysroot = PathBuf::from(&args[1]); + let linker = args.get(2).map(PathBuf::from); - let mut sysroot = PathBuf::from(&args[3]); - sysroot.pop(); - sysroot.pop(); + // compiletest sets the current dir to `output_base_dir` when running. + let tmpdir = std::env::current_dir().unwrap().join("tmp"); + std::fs::create_dir_all(&tmpdir).unwrap(); - compile(src.to_string(), tmpdir.join("out"), sysroot.clone()); - - compile(src.to_string(), tmpdir.join("out"), sysroot.clone()); + compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref()); + compile(src.to_string(), tmpdir.join("out"), sysroot.clone(), linker.as_deref()); } -fn compile(code: String, output: PathBuf, sysroot: PathBuf) { +fn compile(code: String, output: PathBuf, sysroot: PathBuf, linker: Option<&Path>) { let mut opts = Options::default(); opts.output_types = OutputTypes::new(&[(OutputType::Exe, None)]); opts.maybe_sysroot = Some(sysroot); - if let Ok(linker) = std::env::var("RUSTC_LINKER") { - opts.cg.linker = Some(linker.into()); + if let Some(linker) = linker { + opts.cg.linker = Some(linker.to_owned()); } let name = FileName::anon_source_code(&code); From 40291bce5f93afe25825709d7782e86445086e2f Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Tue, 4 Jun 2024 23:31:52 -0700 Subject: [PATCH 098/154] Silence double-symlink errors while building solaris toolchain --- .../host-x86_64/dist-various-2/build-solaris-toolchain.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh b/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh index 3939b4b7c41c..d046b539036d 100755 --- a/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh +++ b/src/ci/docker/host-x86_64/dist-various-2/build-solaris-toolchain.sh @@ -54,7 +54,7 @@ apt-get clean # This makes all those symlinks. for lib in $(find -name '*.so.*'); do target=${lib%.so.*}.so - [ -e $target ] || ln -s ${lib##*/} $target + ln -s ${lib##*/} $target || echo "warning: silenced error symlinking $lib" done # Remove Solaris 11 functions that are optionally used by libbacktrace. From f9150f6e3688010efba0cc7a88ee67a8e47bc9bd Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 4 Jun 2024 19:06:05 -0700 Subject: [PATCH 099/154] Update nomicon --- src/doc/nomicon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/nomicon b/src/doc/nomicon index 0d5f88475fe2..0ebdacadbda8 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 0d5f88475fe285affa6dbbc806e9e44d730797c0 +Subproject commit 0ebdacadbda8ce2cd8fbf93985e15af61a7ab895 From dc020ae5d8f396b35e0741aaba677b59e3e7f168 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 May 2024 10:13:28 +0000 Subject: [PATCH 100/154] Use a `LocalDefId` for `HirTyLowerer::item_def_id`, since we only ever (can) use it for local items --- compiler/rustc_hir_analysis/src/collect.rs | 4 ++-- .../src/collect/predicates_of.rs | 1 - .../src/hir_ty_lowering/mod.rs | 19 +++++++++---------- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 ++-- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 7e7460061484..afdad6935fc9 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -370,8 +370,8 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { self.tcx } - fn item_def_id(&self) -> DefId { - self.item_def_id.to_def_id() + fn item_def_id(&self) -> LocalDefId { + self.item_def_id } fn allow_infer(&self) -> bool { diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 072bb7279016..0abe4f07e190 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -117,7 +117,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen let mut is_trait = None; let mut is_default_impl_trait = None; - // FIXME: Should ItemCtxt take a LocalDefId? let icx = ItemCtxt::new(tcx, def_id); const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty(); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 2f54349d267a..9f136ff97b76 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -89,8 +89,8 @@ pub enum PredicateFilter { pub trait HirTyLowerer<'tcx> { fn tcx(&self) -> TyCtxt<'tcx>; - /// Returns the [`DefId`] of the overarching item whose constituents get lowered. - fn item_def_id(&self) -> DefId; + /// Returns the [`LocalDefId`] of the overarching item whose constituents get lowered. + fn item_def_id(&self) -> LocalDefId; /// Returns `true` if the current context allows the use of inference variables. fn allow_infer(&self) -> bool; @@ -1493,16 +1493,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let def_id = self.item_def_id(); debug!(item_def_id = ?def_id); - let parent_def_id = def_id - .as_local() - .map(|def_id| tcx.local_def_id_to_hir_id(def_id)) - .map(|hir_id| tcx.hir().get_parent_item(hir_id).to_def_id()); + // FIXME: document why/how this is different from `tcx.local_parent(def_id)` + let parent_def_id = + tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id(); debug!(?parent_def_id); // If the trait in segment is the same as the trait defining the item, // use the `` syntax in the error. - let is_part_of_self_trait_constraints = def_id == trait_def_id; - let is_part_of_fn_in_self_trait = parent_def_id == Some(trait_def_id); + let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id; + let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id; let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait { vec!["Self".to_string()] @@ -1983,7 +1982,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } let sig_generics = self.tcx().generics_of(sig_id); - let parent = self.tcx().parent(self.item_def_id()); + let parent = self.tcx().local_parent(self.item_def_id()); let parent_generics = self.tcx().generics_of(parent); let parent_is_trait = (self.tcx().def_kind(parent) == DefKind::Trait) as usize; @@ -2022,7 +2021,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let sig = self.tcx().fn_sig(sig_id); let sig_generics = self.tcx().generics_of(sig_id); - let parent = self.tcx().parent(self.item_def_id()); + let parent = self.tcx().local_parent(self.item_def_id()); let parent_def_kind = self.tcx().def_kind(parent); let sig = if let DefKind::Impl { .. } = parent_def_kind diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index afba812a8e7b..4d79b3686e2b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -218,8 +218,8 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> { self.tcx } - fn item_def_id(&self) -> DefId { - self.body_id.to_def_id() + fn item_def_id(&self) -> LocalDefId { + self.body_id } fn allow_infer(&self) -> bool { From 9d387d14e00f8211d1c52bc1190311de3947c030 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 31 May 2024 10:52:00 +0000 Subject: [PATCH 101/154] Simplify some code paths and remove an unused field `ct_infer` and `lower_ty` will correctly result in an error constant or type respectively, as they go through a `HirTyLowerer` method (just like `HirTyLowerer::allow_infer` is a method implemented by both implementors --- .../src/hir_ty_lowering/mod.rs | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 9f136ff97b76..055a0f84efc1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -421,7 +421,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { def_id: DefId, generic_args: &'a GenericArgs<'tcx>, span: Span, - inferred_params: Vec, infer_args: bool, incorrect_args: &'a Result<(), GenericArgCountMismatch>, } @@ -450,7 +449,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - let mut handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| { + let handle_ty_args = |has_default, ty: &hir::Ty<'tcx>| { if has_default { tcx.check_optional_stability( param.def_id, @@ -467,12 +466,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }, ); } - if let (hir::TyKind::Infer, false) = (&ty.kind, self.lowerer.allow_infer()) { - self.inferred_params.push(ty.span); - Ty::new_misc_error(tcx).into() - } else { - self.lowerer.lower_ty(ty).into() - } + self.lowerer.lower_ty(ty).into() }; match (¶m.kind, arg) { @@ -496,12 +490,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .type_of(param.def_id) .no_bound_vars() .expect("const parameter types cannot be generic"); - if self.lowerer.allow_infer() { - self.lowerer.ct_infer(ty, Some(param), inf.span).into() - } else { - self.inferred_params.push(inf.span); - ty::Const::new_misc_error(tcx, ty).into() - } + self.lowerer.ct_infer(ty, Some(param), inf.span).into() } (kind, arg) => span_bug!( self.span, @@ -604,7 +593,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { def_id, span, generic_args: segment.args(), - inferred_params: vec![], infer_args: segment.infer_args, incorrect_args: &arg_count.correct, }; From abd308b8863ae43ee96fc98fa4a5e90ecb31f12f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 31 May 2024 13:09:18 +0000 Subject: [PATCH 102/154] Remove an `Option` and instead eagerly create error lifetimes --- compiler/rustc_hir_analysis/src/collect.rs | 25 +++++++++-- .../src/hir_ty_lowering/mod.rs | 43 ++++++------------- .../src/hir_ty_lowering/object_safety.rs | 19 +------- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 9 +++- 5 files changed, 43 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index afdad6935fc9..538d87a300d4 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -18,7 +18,7 @@ use rustc_ast::Recovered; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::UnordMap; -use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey}; +use rustc_errors::{struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey, E0228}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; @@ -378,8 +378,27 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { false } - fn re_infer(&self, _: Option<&ty::GenericParamDef>, _: Span) -> Option> { - None + fn re_infer( + &self, + _: Option<&ty::GenericParamDef>, + span: Span, + object_lifetime_default: bool, + ) -> ty::Region<'tcx> { + if object_lifetime_default { + let e = struct_span_code_err!( + self.tcx().dcx(), + span, + E0228, + "the lifetime bound for this object type cannot be deduced \ + from context; please supply an explicit bound" + ) + .emit(); + self.set_tainted_by_errors(e); + ty::Region::new_error(self.tcx(), e) + } else { + // This indicates an illegal lifetime in a non-assoc-trait position + ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature") + } } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 055a0f84efc1..7076983284c5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -96,8 +96,14 @@ pub trait HirTyLowerer<'tcx> { fn allow_infer(&self) -> bool; /// Returns the region to use when a lifetime is omitted (and not elided). - fn re_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) - -> Option>; + /// + /// The `object_lifetime_default` argument states whether this lifetime is from a reference. + fn re_infer( + &self, + param: Option<&ty::GenericParamDef>, + span: Span, + object_lifetime_default: bool, + ) -> ty::Region<'tcx>; /// Returns the type to use when a type is omitted. fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>; @@ -292,21 +298,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(rbv::ResolvedArg::Error(guar)) => ty::Region::new_error(tcx, guar), - None => { - self.re_infer(def, lifetime.ident.span).unwrap_or_else(|| { - debug!(?lifetime, "unelided lifetime in signature"); - - // This indicates an illegal lifetime - // elision. `resolve_lifetime` should have - // reported an error in this case -- but if - // not, let's error out. - ty::Region::new_error_with_message( - tcx, - lifetime.ident.span, - "unelided lifetime in signature", - ) - }) - } + None => self.re_infer(def, lifetime.ident.span, false), } } @@ -513,20 +505,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } match param.kind { - GenericParamDefKind::Lifetime => self - .lowerer - .re_infer(Some(param), self.span) - .unwrap_or_else(|| { - debug!(?param, "unelided lifetime in signature"); - - // This indicates an illegal lifetime in a non-assoc-trait position - ty::Region::new_error_with_message( - tcx, - self.span, - "unelided lifetime in signature", - ) - }) - .into(), + GenericParamDefKind::Lifetime => { + self.lowerer.re_infer(Some(param), self.span, false).into() + } GenericParamDefKind::Type { has_default, .. } => { if !infer_args && has_default { // No type parameter provided, but a default exists. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index 4f7a39d02503..fef80102b623 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -327,24 +327,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if tcx.named_bound_var(lifetime.hir_id).is_some() { self.lower_lifetime(lifetime, None) } else { - self.re_infer(None, span).unwrap_or_else(|| { - let err = struct_span_code_err!( - tcx.dcx(), - span, - E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound" - ); - let e = if borrowed { - // We will have already emitted an error E0106 complaining about a - // missing named lifetime in `&dyn Trait`, so we elide this one. - err.delay_as_bug() - } else { - err.emit() - }; - self.set_tainted_by_errors(e); - ty::Region::new_error(tcx, e) - }) + self.re_infer(None, span, !borrowed) } }) }; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 58eb0c281798..fb44e542f7ad 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1325,7 +1325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let tcx = self.fcx.tcx(); match param.kind { GenericParamDefKind::Lifetime => { - self.fcx.re_infer(Some(param), self.span).unwrap().into() + self.fcx.re_infer(Some(param), self.span, false).into() } GenericParamDefKind::Type { has_default, .. } => { if !infer_args && has_default { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 4d79b3686e2b..d250dee5113d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -226,12 +226,17 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> { true } - fn re_infer(&self, def: Option<&ty::GenericParamDef>, span: Span) -> Option> { + fn re_infer( + &self, + def: Option<&ty::GenericParamDef>, + span: Span, + _object_lifetime_default: bool, + ) -> ty::Region<'tcx> { let v = match def { Some(def) => infer::RegionParameterDefinition(span, def.name), None => infer::MiscVariable(span), }; - Some(self.next_region_var(v)) + self.next_region_var(v) } fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { From 6a2e15a6f08fa1869cd9aacb89c7b2d033c54e65 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 31 May 2024 13:36:27 +0000 Subject: [PATCH 103/154] Only collect infer vars to error about in case infer vars are actually forbidden --- compiler/rustc_hir_analysis/src/collect.rs | 87 ++++++++++++++++- .../src/hir_ty_lowering/mod.rs | 93 ++----------------- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 16 ++++ 3 files changed, 111 insertions(+), 85 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 538d87a300d4..f6e5aeb53962 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -19,10 +19,10 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::UnordMap; use rustc_errors::{struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey, E0228}; -use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{self, Visitor}; +use rustc_hir::intravisit::{self, walk_generics, Visitor}; +use rustc_hir::{self as hir}; use rustc_hir::{GenericParamKind, Node}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; @@ -529,6 +529,89 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { fn set_tainted_by_errors(&self, err: ErrorGuaranteed) { self.tainted_by_errors.set(Some(err)); } + + fn lower_fn_sig( + &self, + decl: &hir::FnDecl<'tcx>, + generics: Option<&hir::Generics<'_>>, + hir_id: rustc_hir::HirId, + hir_ty: Option<&hir::Ty<'_>>, + ) -> (Vec>, Ty<'tcx>) { + let tcx = self.tcx(); + // We proactively collect all the inferred type params to emit a single error per fn def. + let mut visitor = HirPlaceholderCollector::default(); + let mut infer_replacements = vec![]; + + if let Some(generics) = generics { + walk_generics(&mut visitor, generics); + } + + let input_tys = decl + .inputs + .iter() + .enumerate() + .map(|(i, a)| { + if let hir::TyKind::Infer = a.kind { + if let Some(suggested_ty) = + self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) + { + infer_replacements.push((a.span, suggested_ty.to_string())); + return Ty::new_error_with_message(tcx, a.span, suggested_ty.to_string()); + } + } + + // Only visit the type looking for `_` if we didn't fix the type above + visitor.visit_ty(a); + self.lowerer().lower_arg_ty(a, None) + }) + .collect(); + + let output_ty = match decl.output { + hir::FnRetTy::Return(output) => { + if let hir::TyKind::Infer = output.kind + && let Some(suggested_ty) = + self.lowerer().suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None) + { + infer_replacements.push((output.span, suggested_ty.to_string())); + Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string()) + } else { + visitor.visit_ty(output); + self.lower_ty(output) + } + } + hir::FnRetTy::DefaultReturn(..) => tcx.types.unit, + }; + + if !(visitor.0.is_empty() && infer_replacements.is_empty()) { + // We check for the presence of + // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. + + let mut diag = crate::collect::placeholder_type_error_diag( + tcx, + generics, + visitor.0, + infer_replacements.iter().map(|(s, _)| *s).collect(), + true, + hir_ty, + "function", + ); + + if !infer_replacements.is_empty() { + diag.multipart_suggestion( + format!( + "try replacing `_` with the type{} in the corresponding trait method signature", + rustc_errors::pluralize!(infer_replacements.len()), + ), + infer_replacements, + Applicability::MachineApplicable, + ); + } + + self.set_tainted_by_errors(diag.emit()); + } + + (input_tys, output_ty) + } } /// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present. diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 7076983284c5..8f498fcdf366 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -20,7 +20,6 @@ mod lint; mod object_safety; use crate::bounds::Bounds; -use crate::collect::HirPlaceholderCollector; use crate::errors::{AmbiguousLifetimeBound, WildPatTy}; use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; @@ -34,7 +33,6 @@ use rustc_errors::{ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{walk_generics, Visitor as _}; use rustc_hir::{GenericArg, GenericArgs, HirId}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::ObligationCause; @@ -157,6 +155,14 @@ pub trait HirTyLowerer<'tcx> { poly_trait_ref: ty::PolyTraitRef<'tcx>, ) -> Ty<'tcx>; + fn lower_fn_sig( + &self, + decl: &hir::FnDecl<'tcx>, + generics: Option<&hir::Generics<'_>>, + hir_id: HirId, + hir_ty: Option<&hir::Ty<'_>>, + ) -> (Vec>, Ty<'tcx>); + /// Returns `AdtDef` if `ty` is an ADT. /// /// Note that `ty` might be a alias type that needs normalization. @@ -2306,92 +2312,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let bound_vars = tcx.late_bound_vars(hir_id); debug!(?bound_vars); - // We proactively collect all the inferred type params to emit a single error per fn def. - let mut visitor = HirPlaceholderCollector::default(); - let mut infer_replacements = vec![]; - - if let Some(generics) = generics { - walk_generics(&mut visitor, generics); - } - - let input_tys: Vec<_> = decl - .inputs - .iter() - .enumerate() - .map(|(i, a)| { - if let hir::TyKind::Infer = a.kind - && !self.allow_infer() - { - if let Some(suggested_ty) = - self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, Some(i)) - { - infer_replacements.push((a.span, suggested_ty.to_string())); - return Ty::new_error_with_message( - self.tcx(), - a.span, - suggested_ty.to_string(), - ); - } - } - - // Only visit the type looking for `_` if we didn't fix the type above - visitor.visit_ty(a); - self.lower_arg_ty(a, None) - }) - .collect(); - - let output_ty = match decl.output { - hir::FnRetTy::Return(output) => { - if let hir::TyKind::Infer = output.kind - && !self.allow_infer() - && let Some(suggested_ty) = - self.suggest_trait_fn_ty_for_impl_fn_infer(hir_id, None) - { - infer_replacements.push((output.span, suggested_ty.to_string())); - Ty::new_error_with_message(self.tcx(), output.span, suggested_ty.to_string()) - } else { - visitor.visit_ty(output); - self.lower_ty(output) - } - } - hir::FnRetTy::DefaultReturn(..) => tcx.types.unit, - }; + let (input_tys, output_ty) = self.lower_fn_sig(decl, generics, hir_id, hir_ty); debug!(?output_ty); let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); - if !self.allow_infer() && !(visitor.0.is_empty() && infer_replacements.is_empty()) { - // We always collect the spans for placeholder types when evaluating `fn`s, but we - // only want to emit an error complaining about them if infer types (`_`) are not - // allowed. `allow_infer` gates this behavior. We check for the presence of - // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. - - let mut diag = crate::collect::placeholder_type_error_diag( - tcx, - generics, - visitor.0, - infer_replacements.iter().map(|(s, _)| *s).collect(), - true, - hir_ty, - "function", - ); - - if !infer_replacements.is_empty() { - diag.multipart_suggestion( - format!( - "try replacing `_` with the type{} in the corresponding trait method signature", - rustc_errors::pluralize!(infer_replacements.len()), - ), - infer_replacements, - Applicability::MachineApplicable, - ); - } - - self.set_tainted_by_errors(diag.emit()); - } - // Find any late-bound regions declared in return type that do // not appear in the arguments. These are not well-formed. // @@ -2421,7 +2348,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// corresponding function in the trait that the impl implements, if it exists. /// If arg_idx is Some, then it corresponds to an input type index, otherwise it /// corresponds to the return type. - fn suggest_trait_fn_ty_for_impl_fn_infer( + pub(super) fn suggest_trait_fn_ty_for_impl_fn_infer( &self, fn_hir_id: HirId, arg_idx: Option, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index d250dee5113d..e62c4639b43d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -355,6 +355,22 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> { fn set_tainted_by_errors(&self, e: ErrorGuaranteed) { self.infcx.set_tainted_by_errors(e) } + + fn lower_fn_sig( + &self, + decl: &rustc_hir::FnDecl<'tcx>, + _generics: Option<&rustc_hir::Generics<'_>>, + _hir_id: rustc_hir::HirId, + _hir_ty: Option<&hir::Ty<'_>>, + ) -> (Vec>, Ty<'tcx>) { + let input_tys = decl.inputs.iter().map(|a| self.lowerer().lower_arg_ty(a, None)).collect(); + + let output_ty = match decl.output { + hir::FnRetTy::Return(output) => self.lowerer().lower_ty(output), + hir::FnRetTy::DefaultReturn(..) => self.tcx().types.unit, + }; + (input_tys, output_ty) + } } /// The `ty` representation of a user-provided type. Depending on the use-site From 78706740d57d54a6da8abc8eda148c3bcdb64d40 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 31 May 2024 13:42:13 +0000 Subject: [PATCH 104/154] Remove `allows_infer` now that every use of it is delegated to `HirTyLowerer` --- compiler/rustc_hir_analysis/src/collect.rs | 4 ---- compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 3 --- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 ---- 3 files changed, 11 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f6e5aeb53962..f5bcbf852bda 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -374,10 +374,6 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { self.item_def_id } - fn allow_infer(&self) -> bool { - false - } - fn re_infer( &self, _: Option<&ty::GenericParamDef>, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 8f498fcdf366..87c34ac535fe 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -90,9 +90,6 @@ pub trait HirTyLowerer<'tcx> { /// Returns the [`LocalDefId`] of the overarching item whose constituents get lowered. fn item_def_id(&self) -> LocalDefId; - /// Returns `true` if the current context allows the use of inference variables. - fn allow_infer(&self) -> bool; - /// Returns the region to use when a lifetime is omitted (and not elided). /// /// The `object_lifetime_default` argument states whether this lifetime is from a reference. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index e62c4639b43d..6e4a464905fa 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -222,10 +222,6 @@ impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> { self.body_id } - fn allow_infer(&self) -> bool { - true - } - fn re_infer( &self, def: Option<&ty::GenericParamDef>, From 4146b8280a70212ac8cec8ce69e5aff2a4a74577 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 31 May 2024 13:52:37 +0000 Subject: [PATCH 105/154] Remove some unnecessary explicit lifetimes --- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 6e4a464905fa..954a0956b70d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -213,8 +213,8 @@ impl<'a, 'tcx> Deref for FnCtxt<'a, 'tcx> { } } -impl<'a, 'tcx> HirTyLowerer<'tcx> for FnCtxt<'a, 'tcx> { - fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { +impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } From c8a331ac527264ce46b28a8592c31dcef2a5759b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 4 Jun 2024 13:36:28 +0000 Subject: [PATCH 106/154] Unify optional param info with object lifetime default boolean into an enum that exhaustively supports all call sites --- compiler/rustc_hir_analysis/src/collect.rs | 11 ++---- .../src/collect/predicates_of.rs | 13 ++++--- .../src/hir_ty_lowering/bounds.rs | 4 ++- .../src/hir_ty_lowering/mod.rs | 35 +++++++++++-------- .../src/hir_ty_lowering/object_safety.rs | 17 ++++++--- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 20 +++++++---- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 15 +++----- .../rustc_hir_typeck/src/method/confirm.rs | 13 ++++--- 8 files changed, 75 insertions(+), 53 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f5bcbf852bda..d84dcb78ad2e 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -44,7 +44,7 @@ use std::ops::Bound; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::errors; -use crate::hir_ty_lowering::HirTyLowerer; +use crate::hir_ty_lowering::{HirTyLowerer, RegionInferReason}; pub use type_of::test_opaque_hidden_types; mod generics_of; @@ -374,13 +374,8 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { self.item_def_id } - fn re_infer( - &self, - _: Option<&ty::GenericParamDef>, - span: Span, - object_lifetime_default: bool, - ) -> ty::Region<'tcx> { - if object_lifetime_default { + fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { + if let RegionInferReason::BorrowedObjectLifetimeDefault = reason { let e = struct_span_code_err!( self.tcx().dcx(), span, diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 0abe4f07e190..913fae6b5b69 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1,7 +1,7 @@ use crate::bounds::Bounds; use crate::collect::ItemCtxt; use crate::constrained_generic_params as cgp; -use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter}; +use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason}; use hir::{HirId, Node}; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; @@ -243,12 +243,15 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen } hir::WherePredicate::RegionPredicate(region_pred) => { - let r1 = icx.lowerer().lower_lifetime(region_pred.lifetime, None); + let r1 = icx + .lowerer() + .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate); predicates.extend(region_pred.bounds.iter().map(|bound| { let (r2, span) = match bound { - hir::GenericBound::Outlives(lt) => { - (icx.lowerer().lower_lifetime(lt, None), lt.ident.span) - } + hir::GenericBound::Outlives(lt) => ( + icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate), + lt.ident.span, + ), bound => { span_bug!( bound.span(), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index b6a1799c03f1..73ce577907eb 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -18,6 +18,8 @@ use crate::bounds::Bounds; use crate::errors; use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter}; +use super::RegionInferReason; + impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// Add a `Sized` bound to the `bounds` if appropriate. /// @@ -166,7 +168,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } hir::GenericBound::Outlives(lifetime) => { - let region = self.lower_lifetime(lifetime, None); + let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound); bounds.push_region_bound( self.tcx(), ty::Binder::bind_with_vars( diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 87c34ac535fe..9b8edbc10ad8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -80,6 +80,20 @@ pub enum PredicateFilter { SelfAndAssociatedTypeBounds, } +#[derive(Debug)] +pub enum RegionInferReason<'a> { + /// Lifetime on a trait object behind a reference. + /// This allows inferring information from the reference. + BorrowedObjectLifetimeDefault, + /// A trait object's lifetime. + ObjectLifetimeDefault, + /// Generic lifetime parameter + Param(&'a ty::GenericParamDef), + RegionPredicate, + Reference, + OutlivesBound, +} + /// A context which can lower type-system entities from the [HIR][hir] to /// the [`rustc_middle::ty`] representation. /// @@ -91,14 +105,7 @@ pub trait HirTyLowerer<'tcx> { fn item_def_id(&self) -> LocalDefId; /// Returns the region to use when a lifetime is omitted (and not elided). - /// - /// The `object_lifetime_default` argument states whether this lifetime is from a reference. - fn re_infer( - &self, - param: Option<&ty::GenericParamDef>, - span: Span, - object_lifetime_default: bool, - ) -> ty::Region<'tcx>; + fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx>; /// Returns the type to use when a type is omitted. fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>; @@ -267,7 +274,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub fn lower_lifetime( &self, lifetime: &hir::Lifetime, - def: Option<&ty::GenericParamDef>, + reason: RegionInferReason<'_>, ) -> ty::Region<'tcx> { let tcx = self.tcx(); let lifetime_name = |def_id| tcx.hir().name(tcx.local_def_id_to_hir_id(def_id)); @@ -301,7 +308,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Some(rbv::ResolvedArg::Error(guar)) => ty::Region::new_error(tcx, guar), - None => self.re_infer(def, lifetime.ident.span, false), + None => self.re_infer(lifetime.ident.span, reason), } } @@ -466,7 +473,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { - self.lowerer.lower_lifetime(lt, Some(param)).into() + self.lowerer.lower_lifetime(lt, RegionInferReason::Param(param)).into() } (&GenericParamDefKind::Type { has_default, .. }, GenericArg::Type(ty)) => { handle_ty_args(has_default, ty) @@ -509,7 +516,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } match param.kind { GenericParamDefKind::Lifetime => { - self.lowerer.re_infer(Some(param), self.span, false).into() + self.lowerer.re_infer(self.span, RegionInferReason::Param(param)).into() } GenericParamDefKind::Type { has_default, .. } => { if !infer_args && has_default { @@ -2041,7 +2048,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)), hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl), hir::TyKind::Ref(region, mt) => { - let r = self.lower_lifetime(region, None); + let r = self.lower_lifetime(region, RegionInferReason::Reference); debug!(?r); let t = self.lower_ty_common(mt.ty, true, false); Ty::new_ref(tcx, r, t, mt.mutbl) @@ -2270,7 +2277,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { &lifetimes[i] ) }; - self.lower_lifetime(lifetime, None).into() + self.lower_lifetime(lifetime, RegionInferReason::Param(¶m)).into() } else { tcx.mk_param_from_def(param) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index fef80102b623..b9c5ae0c65b5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -1,5 +1,7 @@ use crate::bounds::Bounds; -use crate::hir_ty_lowering::{GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds}; +use crate::hir_ty_lowering::{ + GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds, RegionInferReason, +}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::{codes::*, struct_span_code_err}; use rustc_hir as hir; @@ -321,13 +323,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Use explicitly-specified region bound. let region_bound = if !lifetime.is_elided() { - self.lower_lifetime(lifetime, None) + self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) } else { self.compute_object_lifetime_bound(span, existential_predicates).unwrap_or_else(|| { if tcx.named_bound_var(lifetime.hir_id).is_some() { - self.lower_lifetime(lifetime, None) + self.lower_lifetime(lifetime, RegionInferReason::ObjectLifetimeDefault) } else { - self.re_infer(None, span, !borrowed) + self.re_infer( + span, + if borrowed { + RegionInferReason::ObjectLifetimeDefault + } else { + RegionInferReason::BorrowedObjectLifetimeDefault + }, + ) } }) }; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index fb44e542f7ad..250e9c3c313e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -16,7 +16,7 @@ use rustc_hir_analysis::hir_ty_lowering::generics::{ }; use rustc_hir_analysis::hir_ty_lowering::{ ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgsLowerer, - GenericPathSegment, HirTyLowerer, IsMethodCall, + GenericPathSegment, HirTyLowerer, IsMethodCall, RegionInferReason, }; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; @@ -1280,9 +1280,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { match (¶m.kind, arg) { - (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { - self.fcx.lowerer().lower_lifetime(lt, Some(param)).into() - } + (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => self + .fcx + .lowerer() + .lower_lifetime(lt, RegionInferReason::Param(param)) + .into(), (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { self.fcx.lower_ty(ty).raw.into() } @@ -1324,9 +1326,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> ty::GenericArg<'tcx> { let tcx = self.fcx.tcx(); match param.kind { - GenericParamDefKind::Lifetime => { - self.fcx.re_infer(Some(param), self.span, false).into() - } + GenericParamDefKind::Lifetime => self + .fcx + .re_infer( + self.span, + rustc_hir_analysis::hir_ty_lowering::RegionInferReason::Param(param), + ) + .into(), GenericParamDefKind::Type { has_default, .. } => { if !infer_args && has_default { // If we have a default, then it doesn't matter that we're not diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 954a0956b70d..b9ff348c42ff 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -15,7 +15,7 @@ use hir::def_id::CRATE_DEF_ID; use rustc_errors::DiagCtxt; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; +use rustc_hir_analysis::hir_ty_lowering::{HirTyLowerer, RegionInferReason}; use rustc_infer::infer; use rustc_infer::infer::error_reporting::sub_relations::SubRelations; use rustc_infer::infer::error_reporting::TypeErrCtxt; @@ -222,15 +222,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { self.body_id } - fn re_infer( - &self, - def: Option<&ty::GenericParamDef>, - span: Span, - _object_lifetime_default: bool, - ) -> ty::Region<'tcx> { - let v = match def { - Some(def) => infer::RegionParameterDefinition(span, def.name), - None => infer::MiscVariable(span), + fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { + let v = match reason { + RegionInferReason::Param(def) => infer::RegionParameterDefinition(span, def.name), + _ => infer::MiscVariable(span), }; self.next_region_var(v) } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 0825e6613730..949b92410053 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -7,7 +7,9 @@ use rustc_hir::GenericArg; use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_call, lower_generic_args, }; -use rustc_hir_analysis::hir_ty_lowering::{GenericArgsLowerer, HirTyLowerer, IsMethodCall}; +use rustc_hir_analysis::hir_ty_lowering::{ + GenericArgsLowerer, HirTyLowerer, IsMethodCall, RegionInferReason, +}; use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk}; use rustc_middle::traits::{ObligationCauseCode, UnifyReceiverContext}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; @@ -388,9 +390,12 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { match (¶m.kind, arg) { - (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { - self.cfcx.fcx.lowerer().lower_lifetime(lt, Some(param)).into() - } + (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => self + .cfcx + .fcx + .lowerer() + .lower_lifetime(lt, RegionInferReason::Param(param)) + .into(), (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { self.cfcx.lower_ty(ty).raw.into() } From a8e091de4afb964480aa52642838ee5049c89cad Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 5 Jun 2024 11:46:52 +0200 Subject: [PATCH 107/154] bivariant alias: set `has_unconstrained_ty_var` --- .../src/infer/relate/generalize.rs | 12 +++++++++-- .../next-solver/generalize/bivariant-alias.rs | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/next-solver/generalize/bivariant-alias.rs diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index d4c7d752c953..aaea3b4820b3 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -329,6 +329,14 @@ impl<'tcx> Generalizer<'_, 'tcx> { } } + /// Create a new type variable in the universe of the target when + /// generalizing an alias. This has to set `has_unconstrained_ty_var` + /// if we're currently in a bivariant context. + fn next_ty_var_for_alias(&mut self) -> Ty<'tcx> { + self.has_unconstrained_ty_var |= self.ambient_variance == ty::Bivariant; + self.infcx.next_ty_var_in_universe(self.span, self.for_universe) + } + /// An occurs check failure inside of an alias does not mean /// that the types definitely don't unify. We may be able /// to normalize the alias after all. @@ -358,7 +366,7 @@ impl<'tcx> Generalizer<'_, 'tcx> { // // cc trait-system-refactor-initiative#110 if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias { - return Ok(self.infcx.next_ty_var_in_universe(self.span, self.for_universe)); + return Ok(self.next_ty_var_for_alias()); } let is_nested_alias = mem::replace(&mut self.in_alias, true); @@ -378,7 +386,7 @@ impl<'tcx> Generalizer<'_, 'tcx> { } debug!("generalization failure in alias"); - Ok(self.infcx.next_ty_var_in_universe(self.span, self.for_universe)) + Ok(self.next_ty_var_for_alias()) } } }; diff --git a/tests/ui/traits/next-solver/generalize/bivariant-alias.rs b/tests/ui/traits/next-solver/generalize/bivariant-alias.rs new file mode 100644 index 000000000000..b03d547838a0 --- /dev/null +++ b/tests/ui/traits/next-solver/generalize/bivariant-alias.rs @@ -0,0 +1,20 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// When generalizing an alias in a bivariant context, we have to set +// `has_unconstrained_ty_var` as we may otherwise never check for +// well-formedness of the generalized type, causing us to error due +// to ambiguity. +trait Trait { + type Assoc; +} + +struct BivariantArg>(T); + +fn generalize(input: BivariantArg) { + let _generalized = input; +} + +pub fn main() {} From 0380321e7806bdab232d7e95be2de47fad8f3c09 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 31 May 2024 16:57:07 -0300 Subject: [PATCH 108/154] Add unsafe_extern_blocks feature flag --- .../rustc_ast_passes/src/ast_validation.rs | 36 ++++++++++--------- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_lint_defs/src/builtin.rs | 7 ++-- compiler/rustc_span/src/symbol.rs | 1 + .../feature-gate-unsafe-extern-blocks.rs | 5 +++ .../feature-gate-unsafe-extern-blocks.stderr | 8 +++++ tests/ui/parser/unsafe-foreign-mod-2.rs | 2 ++ tests/ui/parser/unsafe-foreign-mod-2.stderr | 17 ++++++++- tests/ui/parser/unsafe-foreign-mod.rs | 6 ++-- tests/ui/parser/unsafe-foreign-mod.stderr | 8 +++++ .../extern-items-unsafe.edition2021.stderr | 4 +-- .../extern-items-unsafe.edition2024.stderr | 4 +-- .../extern-items-unsafe.rs | 2 ++ .../extern-items.edition2024.stderr | 8 ++--- .../unsafe-extern-blocks/extern-items.rs | 6 ++-- .../unsafe-extern-blocks/safe-items.rs | 2 ++ .../unsafe-items.edition2021.stderr | 4 +-- .../unsafe-items.edition2024.stderr | 4 +-- .../unsafe-extern-blocks/unsafe-items.rs | 2 ++ tests/ui/unpretty/expanded-exhaustive.rs | 1 + tests/ui/unpretty/expanded-exhaustive.stdout | 1 + 21 files changed, 93 insertions(+), 37 deletions(-) create mode 100644 tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs create mode 100644 tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr create mode 100644 tests/ui/parser/unsafe-foreign-mod.stderr diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index a9f06230fafc..dc554ba04dfe 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -440,16 +440,14 @@ impl<'a> AstValidator<'a> { } fn check_foreign_item_safety(&self, item_span: Span, safety: Safety) { - match safety { - Safety::Unsafe(_) | Safety::Safe(_) - if self.extern_mod_safety == Some(Safety::Default) => - { - self.dcx().emit_err(errors::InvalidSafetyOnExtern { - item_span, - block: self.current_extern_span(), - }); - } - _ => {} + if matches!(safety, Safety::Unsafe(_) | Safety::Safe(_)) + && (self.extern_mod_safety == Some(Safety::Default) + || !self.features.unsafe_extern_blocks) + { + self.dcx().emit_err(errors::InvalidSafetyOnExtern { + item_span, + block: self.current_extern_span(), + }); } } @@ -1044,13 +1042,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> { errors::VisibilityNotPermittedNote::IndividualForeignItems, ); - if &Safety::Default == safety { - this.lint_buffer.buffer_lint( - MISSING_UNSAFE_ON_EXTERN, - item.id, - item.span, - BuiltinLintDiag::MissingUnsafeOnExtern, - ); + if this.features.unsafe_extern_blocks { + if &Safety::Default == safety { + this.lint_buffer.buffer_lint( + MISSING_UNSAFE_ON_EXTERN, + item.id, + item.span, + BuiltinLintDiag::MissingUnsafeOnExtern, + ); + } + } else if let &Safety::Unsafe(span) = safety { + this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" }); } if abi.is_none() { diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8de2cdefa81c..486de706e526 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -624,6 +624,8 @@ declare_features! ( (unstable, type_changing_struct_update, "1.58.0", Some(86555)), /// Allows unnamed fields of struct and union type (incomplete, unnamed_fields, "1.74.0", Some(49804)), + /// Allows unsafe on extern declarations and safety qualifiers over internal items. + (unstable, unsafe_extern_blocks, "CURRENT_RUSTC_VERSION", Some(123743)), /// Allows unsized fn parameters. (unstable, unsized_fn_params, "1.49.0", Some(48055)), /// Allows unsized rvalues at arguments and parameters. diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index b4a34b1407da..ec124c3224cb 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4858,7 +4858,10 @@ declare_lint! { /// /// ### Example /// - /// ```rust,edition2024 + /// ```rust,edition2024,ignore + /// #![feature(unsafe_extern_blocks)] + /// #![allow(dead_code)] + /// /// extern "C" { /// fn foo(_: i32); /// } @@ -4880,5 +4883,5 @@ declare_lint! { pub MISSING_UNSAFE_ON_EXTERN, Allow, "detects missing unsafe keyword on extern declarations", - @edition Edition2024 => Warn; + @edition Edition2024 => Deny; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ede9b852ba84..f1933806c012 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1965,6 +1965,7 @@ symbols! { unsafe_block_in_unsafe_fn, unsafe_cell, unsafe_cell_raw_get, + unsafe_extern_blocks, unsafe_no_drop_flag, unsafe_pin_internals, unsize, diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs new file mode 100644 index 000000000000..eab134a4a4de --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.rs @@ -0,0 +1,5 @@ +unsafe extern "C" { + //~^ ERROR extern block cannot be declared unsafe +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr new file mode 100644 index 000000000000..7e9b199a2db5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-unsafe-extern-blocks.stderr @@ -0,0 +1,8 @@ +error: extern block cannot be declared unsafe + --> $DIR/feature-gate-unsafe-extern-blocks.rs:1:1 + | +LL | unsafe extern "C" { + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/unsafe-foreign-mod-2.rs b/tests/ui/parser/unsafe-foreign-mod-2.rs index 6d339cd90881..0b63a993c5b9 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.rs +++ b/tests/ui/parser/unsafe-foreign-mod-2.rs @@ -1,6 +1,8 @@ extern "C" unsafe { //~^ ERROR expected `{`, found keyword `unsafe` + //~| ERROR extern block cannot be declared unsafe unsafe fn foo(); + //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers } fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod-2.stderr b/tests/ui/parser/unsafe-foreign-mod-2.stderr index 0625e3362ed7..e59352395ed6 100644 --- a/tests/ui/parser/unsafe-foreign-mod-2.stderr +++ b/tests/ui/parser/unsafe-foreign-mod-2.stderr @@ -4,5 +4,20 @@ error: expected `{`, found keyword `unsafe` LL | extern "C" unsafe { | ^^^^^^ expected `{` -error: aborting due to 1 previous error +error: extern block cannot be declared unsafe + --> $DIR/unsafe-foreign-mod-2.rs:1:12 + | +LL | extern "C" unsafe { + | ^^^^^^ + +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/unsafe-foreign-mod-2.rs:4:5 + | +LL | extern "C" unsafe { + | ----------------- help: add unsafe to this `extern` block +... +LL | unsafe fn foo(); + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/tests/ui/parser/unsafe-foreign-mod.rs b/tests/ui/parser/unsafe-foreign-mod.rs index 26015a3c4445..eab134a4a4de 100644 --- a/tests/ui/parser/unsafe-foreign-mod.rs +++ b/tests/ui/parser/unsafe-foreign-mod.rs @@ -1,5 +1,5 @@ -//@ build-pass - -unsafe extern "C" {} +unsafe extern "C" { + //~^ ERROR extern block cannot be declared unsafe +} fn main() {} diff --git a/tests/ui/parser/unsafe-foreign-mod.stderr b/tests/ui/parser/unsafe-foreign-mod.stderr new file mode 100644 index 000000000000..77f6e93be10b --- /dev/null +++ b/tests/ui/parser/unsafe-foreign-mod.stderr @@ -0,0 +1,8 @@ +error: extern block cannot be declared unsafe + --> $DIR/unsafe-foreign-mod.rs:1:1 + | +LL | unsafe extern "C" { + | ^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr index 77554da10e60..3a99caa719b5 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:12:5 + --> $DIR/extern-items-unsafe.rs:14:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/extern-items-unsafe.rs:12:11 + --> $DIR/extern-items-unsafe.rs:14:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr index 33b752782d59..fcf937b7ac57 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:12:5 + --> $DIR/extern-items-unsafe.rs:14:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/extern-items-unsafe.rs:12:11 + --> $DIR/extern-items-unsafe.rs:14:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs index 721e07acca58..ad569a256db9 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items-unsafe.rs @@ -3,6 +3,8 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options +#![feature(unsafe_extern_blocks)] + unsafe extern "C" { static TEST1: i32; fn test1(i: i32); diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr index b19369c0a551..8e1ec8146351 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr @@ -1,5 +1,5 @@ -warning: extern blocks should be unsafe - --> $DIR/extern-items.rs:7:1 +error: extern blocks should be unsafe + --> $DIR/extern-items.rs:9:1 | LL | / extern "C" { LL | | @@ -8,7 +8,7 @@ LL | | fn test1(i: i32); LL | | } | |_^ | - = note: `#[warn(missing_unsafe_on_extern)]` on by default + = note: `#[deny(missing_unsafe_on_extern)]` on by default -warning: 1 warning emitted +error: aborting due to 1 previous error diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs index dfb851e276d4..905d1434155e 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs @@ -1,11 +1,13 @@ //@ revisions: edition2021 edition2024 //@[edition2021] edition:2021 +//@[edition2021] check-pass //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options -//@ check-pass + +#![feature(unsafe_extern_blocks)] extern "C" { - //[edition2024]~^ WARN extern blocks should be unsafe [missing_unsafe_on_extern] + //[edition2024]~^ ERROR extern blocks should be unsafe static TEST1: i32; fn test1(i: i32); } diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs index b0b8a8b012a6..74cd5621fce9 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-items.rs @@ -4,6 +4,8 @@ //@[edition2024] compile-flags: -Zunstable-options //@ check-pass +#![feature(unsafe_extern_blocks)] + unsafe extern "C" { safe static TEST1: i32; safe fn test1(i: i32); diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr index e3626bb497e4..8bb7ffefeea9 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2021.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:18:5 + --> $DIR/unsafe-items.rs:20:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/unsafe-items.rs:18:11 + --> $DIR/unsafe-items.rs:20:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr index 89bc501b7b5a..9a30142a632c 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.edition2024.stderr @@ -1,5 +1,5 @@ error[E0133]: call to unsafe function `test1` is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:18:5 + --> $DIR/unsafe-items.rs:20:5 | LL | test1(TEST1); | ^^^^^^^^^^^^ call to unsafe function @@ -7,7 +7,7 @@ LL | test1(TEST1); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: use of extern static is unsafe and requires unsafe block - --> $DIR/unsafe-items.rs:18:11 + --> $DIR/unsafe-items.rs:20:11 | LL | test1(TEST1); | ^^^^^ use of extern static diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs index dc2bae892a98..9066953abc61 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-items.rs @@ -3,6 +3,8 @@ //@[edition2024] edition:2024 //@[edition2024] compile-flags: -Zunstable-options +#![feature(unsafe_extern_blocks)] + unsafe extern "C" { unsafe static TEST1: i32; unsafe fn test1(i: i32); diff --git a/tests/ui/unpretty/expanded-exhaustive.rs b/tests/ui/unpretty/expanded-exhaustive.rs index 29472df897a1..92c2e7b48847 100644 --- a/tests/ui/unpretty/expanded-exhaustive.rs +++ b/tests/ui/unpretty/expanded-exhaustive.rs @@ -25,6 +25,7 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unnamed_fields)] +#![feature(unsafe_extern_blocks)] #![feature(yeet_expr)] #![allow(incomplete_features)] diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout index 0a09a3f6a423..9e45f57af354 100644 --- a/tests/ui/unpretty/expanded-exhaustive.stdout +++ b/tests/ui/unpretty/expanded-exhaustive.stdout @@ -26,6 +26,7 @@ #![feature(trait_alias)] #![feature(try_blocks)] #![feature(unnamed_fields)] +#![feature(unsafe_extern_blocks)] #![feature(yeet_expr)] #![allow(incomplete_features)] #[prelude_import] From 1afc7d716cfb7858863754217566b785bac179a4 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 3 Jun 2024 22:27:57 -0300 Subject: [PATCH 109/154] Make MISSING_UNSAFE_ON_EXTERN lint emit future compat info with suggestion to prepend unsafe --- compiler/rustc_ast_passes/messages.ftl | 2 ++ .../rustc_ast_passes/src/ast_validation.rs | 19 +++++++++++++------ compiler/rustc_ast_passes/src/errors.rs | 7 +++++++ compiler/rustc_lint/messages.ftl | 1 + .../rustc_lint/src/context/diagnostics.rs | 4 ++-- compiler/rustc_lint/src/lints.rs | 5 ++++- compiler/rustc_lint_defs/src/builtin.rs | 8 ++++++-- compiler/rustc_lint_defs/src/lib.rs | 4 +++- .../extern-items.edition2024.stderr | 4 +--- .../unsafe-extern-blocks/extern-items.rs | 2 +- 10 files changed, 40 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index b90b502c22b8..9a8689e27c06 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -177,6 +177,8 @@ ast_passes_match_arm_with_no_body = `match` arm with no body .suggestion = add a body after the pattern +ast_passes_missing_unsafe_on_extern = extern blocks must be unsafe + ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name .help = consider using the `#[path]` attribute to specify filesystem path diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index dc554ba04dfe..0fbb288cc968 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1044,12 +1044,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if this.features.unsafe_extern_blocks { if &Safety::Default == safety { - this.lint_buffer.buffer_lint( - MISSING_UNSAFE_ON_EXTERN, - item.id, - item.span, - BuiltinLintDiag::MissingUnsafeOnExtern, - ); + if item.span.at_least_rust_2024() { + this.dcx() + .emit_err(errors::MissingUnsafeOnExtern { span: item.span }); + } else { + this.lint_buffer.buffer_lint( + MISSING_UNSAFE_ON_EXTERN, + item.id, + item.span, + BuiltinLintDiag::MissingUnsafeOnExtern { + suggestion: item.span.shrink_to_lo(), + }, + ); + } } } else if let &Safety::Unsafe(span) = safety { this.dcx().emit_err(errors::UnsafeItem { span, kind: "extern block" }); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 05e99a3d6361..260c182bd9e4 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -494,6 +494,13 @@ pub struct UnsafeItem { pub kind: &'static str, } +#[derive(Diagnostic)] +#[diag(ast_passes_missing_unsafe_on_extern)] +pub struct MissingUnsafeOnExtern { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(ast_passes_fieldless_union)] pub struct FieldlessUnion { diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index bb6ad7c945b2..522f2f84cca6 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -463,6 +463,7 @@ lint_metavariable_wrong_operator = meta-variable repeats with different Kleene o lint_missing_fragment_specifier = missing fragment specifier lint_missing_unsafe_on_extern = extern blocks should be unsafe + .suggestion = needs `unsafe` before the extern keyword lint_mixed_script_confusables = the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs index f824e02dcf9d..c38804e7714b 100644 --- a/compiler/rustc_lint/src/context/diagnostics.rs +++ b/compiler/rustc_lint/src/context/diagnostics.rs @@ -205,8 +205,8 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: & }; lints::DeprecatedWhereClauseLocation { suggestion }.decorate_lint(diag); } - BuiltinLintDiag::MissingUnsafeOnExtern => { - lints::MissingUnsafeOnExtern.decorate_lint(diag); + BuiltinLintDiag::MissingUnsafeOnExtern { suggestion } => { + lints::MissingUnsafeOnExtern { suggestion }.decorate_lint(diag); } BuiltinLintDiag::SingleUseLifetime { param_span, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 01b455c588ba..985b66a54e15 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -2740,7 +2740,10 @@ pub enum DeprecatedWhereClauseLocationSugg { #[derive(LintDiagnostic)] #[diag(lint_missing_unsafe_on_extern)] -pub struct MissingUnsafeOnExtern; +pub struct MissingUnsafeOnExtern { + #[suggestion(code = "unsafe ", applicability = "machine-applicable")] + pub suggestion: Span, +} #[derive(LintDiagnostic)] #[diag(lint_single_use_lifetime)] diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index ec124c3224cb..7082a068c481 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -4858,8 +4858,9 @@ declare_lint! { /// /// ### Example /// - /// ```rust,edition2024,ignore + /// ```rust /// #![feature(unsafe_extern_blocks)] + /// #![warn(missing_unsafe_on_extern)] /// #![allow(dead_code)] /// /// extern "C" { @@ -4883,5 +4884,8 @@ declare_lint! { pub MISSING_UNSAFE_ON_EXTERN, Allow, "detects missing unsafe keyword on extern declarations", - @edition Edition2024 => Deny; + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024), + reference: "issue #123743 ", + }; } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 0f13046923eb..67e1bfee620a 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -630,7 +630,9 @@ pub enum BuiltinLintDiag { UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), DeprecatedWhereclauseLocation(Span, Option<(Span, String)>), - MissingUnsafeOnExtern, + MissingUnsafeOnExtern { + suggestion: Span, + }, SingleUseLifetime { /// Span of the parameter which declares this lifetime. param_span: Span, diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr index 8e1ec8146351..d456cfc6829e 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.edition2024.stderr @@ -1,4 +1,4 @@ -error: extern blocks should be unsafe +error: extern blocks must be unsafe --> $DIR/extern-items.rs:9:1 | LL | / extern "C" { @@ -7,8 +7,6 @@ LL | | static TEST1: i32; LL | | fn test1(i: i32); LL | | } | |_^ - | - = note: `#[deny(missing_unsafe_on_extern)]` on by default error: aborting due to 1 previous error diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs index 905d1434155e..16fa1bbb8a40 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/extern-items.rs @@ -7,7 +7,7 @@ #![feature(unsafe_extern_blocks)] extern "C" { - //[edition2024]~^ ERROR extern blocks should be unsafe + //[edition2024]~^ ERROR extern blocks must be unsafe static TEST1: i32; fn test1(i: i32); } From be0726c7c152700a47d91a27a4817c0af770e8e9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 4 Jun 2024 14:44:57 -0300 Subject: [PATCH 110/154] Add revisions to safe/unsafe on unadorned extern blocks test --- ...unadorned-extern-block.edition2021.stderr} | 5 +-- ...-unadorned-extern-block.edition2024.stderr | 32 +++++++++++++++++++ .../safe-unsafe-on-unadorned-extern-block.rs | 8 +++++ 3 files changed, 43 insertions(+), 2 deletions(-) rename tests/ui/rust-2024/unsafe-extern-blocks/{safe-unsafe-on-unadorned-extern-block.stderr => safe-unsafe-on-unadorned-extern-block.edition2021.stderr} (80%) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr similarity index 80% rename from tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr rename to tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr index 66624f1fcb16..411cf48b4866 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.stderr +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2021.stderr @@ -1,13 +1,14 @@ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:2:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 | LL | extern "C" { | ---------- help: add unsafe to this `extern` block +LL | LL | safe static TEST1: i32; | ^^^^^^^^^^^^^^^^^^^^^^^ error: items in unadorned `extern` blocks cannot have safety qualifiers - --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:4:5 + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5 | LL | extern "C" { | ---------- help: add unsafe to this `extern` block diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr new file mode 100644 index 000000000000..b634adc29996 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.edition2024.stderr @@ -0,0 +1,32 @@ +error: extern blocks must be unsafe + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:8:1 + | +LL | / extern "C" { +LL | | +LL | | safe static TEST1: i32; +LL | | +LL | | safe fn test1(i: i32); +LL | | +LL | | } + | |_^ + +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:10:5 + | +LL | extern "C" { + | ---------- help: add unsafe to this `extern` block +LL | +LL | safe static TEST1: i32; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: items in unadorned `extern` blocks cannot have safety qualifiers + --> $DIR/safe-unsafe-on-unadorned-extern-block.rs:12:5 + | +LL | extern "C" { + | ---------- help: add unsafe to this `extern` block +... +LL | safe fn test1(i: i32); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs index d37a7be452da..11f55cb195f2 100644 --- a/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs +++ b/tests/ui/rust-2024/unsafe-extern-blocks/safe-unsafe-on-unadorned-extern-block.rs @@ -1,4 +1,12 @@ +//@ revisions: edition2021 edition2024 +//@[edition2021] edition:2021 +//@[edition2024] edition:2024 +//@[edition2024] compile-flags: -Zunstable-options + +#![feature(unsafe_extern_blocks)] + extern "C" { + //[edition2024]~^ ERROR extern blocks must be unsafe safe static TEST1: i32; //~^ ERROR items in unadorned `extern` blocks cannot have safety qualifiers safe fn test1(i: i32); From 525828d5ee9baca7f7e651918df966f6bc38596a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 4 Jun 2024 15:46:32 -0300 Subject: [PATCH 111/154] Add rustfix test for unsafe extern blocks --- .../unsafe-extern-suggestion.fixed | 19 ++++++++++++++ .../unsafe-extern-suggestion.rs | 19 ++++++++++++++ .../unsafe-extern-suggestion.stderr | 25 +++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs create mode 100644 tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed new file mode 100644 index 000000000000..10c19759d8aa --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.fixed @@ -0,0 +1,19 @@ +//@ run-rustfix + +#![feature(unsafe_extern_blocks)] +#![deny(missing_unsafe_on_extern)] +#![allow(unused)] + +unsafe extern "C" { + //~^ ERROR extern blocks should be unsafe [missing_unsafe_on_extern] + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + static TEST1: i32; + fn test1(i: i32); +} + +unsafe extern "C" { + static TEST2: i32; + fn test2(i: i32); +} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs new file mode 100644 index 000000000000..b81e52ddc584 --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.rs @@ -0,0 +1,19 @@ +//@ run-rustfix + +#![feature(unsafe_extern_blocks)] +#![deny(missing_unsafe_on_extern)] +#![allow(unused)] + +extern "C" { + //~^ ERROR extern blocks should be unsafe [missing_unsafe_on_extern] + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + static TEST1: i32; + fn test1(i: i32); +} + +unsafe extern "C" { + static TEST2: i32; + fn test2(i: i32); +} + +fn main() {} diff --git a/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr new file mode 100644 index 000000000000..0a3c2cd25e3f --- /dev/null +++ b/tests/ui/rust-2024/unsafe-extern-blocks/unsafe-extern-suggestion.stderr @@ -0,0 +1,25 @@ +error: extern blocks should be unsafe + --> $DIR/unsafe-extern-suggestion.rs:7:1 + | +LL | extern "C" { + | ^ + | | + | _help: needs `unsafe` before the extern keyword: `unsafe` + | | +LL | | +LL | | +LL | | static TEST1: i32; +LL | | fn test1(i: i32); +LL | | } + | |_^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! + = note: for more information, see issue #123743 +note: the lint level is defined here + --> $DIR/unsafe-extern-suggestion.rs:4:9 + | +LL | #![deny(missing_unsafe_on_extern)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + From b710404f3b3990af8eebe2e168f6465535dfcc82 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 3 Jun 2024 20:13:31 -0400 Subject: [PATCH 112/154] Update the interpreter to handle the new cases --- .../src/interpret/terminator.rs | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 0649bb5617ce..cbfe25ca8df5 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -294,17 +294,30 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { /// Unwrap types that are guaranteed a null-pointer-optimization fn unfold_npo(&self, layout: TyAndLayout<'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> { - // Check if this is `Option` wrapping some type. - let inner = match layout.ty.kind() { - ty::Adt(def, args) if self.tcx.is_diagnostic_item(sym::Option, def.did()) => { - args[0].as_type().unwrap() - } - _ => { - // Not an `Option`. - return Ok(layout); - } + // Check if this is `Option` wrapping some type or if this is `Result` wrapping a 1-ZST and + // another type. + let ty::Adt(def, args) = layout.ty.kind() else { + // Not an ADT, so definitely no NPO. + return Ok(layout); }; - let inner = self.layout_of(inner)?; + let inner = if self.tcx.is_diagnostic_item(sym::Option, def.did()) { + // The wrapped type is the only arg. + self.layout_of(args[0].as_type().unwrap())? + } else if self.tcx.is_diagnostic_item(sym::Result, def.did()) { + // We want to extract which (if any) of the args is not a 1-ZST. + let lhs = self.layout_of(args[0].as_type().unwrap())?; + let rhs = self.layout_of(args[1].as_type().unwrap())?; + if lhs.is_1zst() { + rhs + } else if rhs.is_1zst() { + lhs + } else { + return Ok(layout); // no NPO + } + } else { + return Ok(layout); // no NPO + }; + // Check if the inner type is one of the NPO-guaranteed ones. // For that we first unpeel transparent *structs* (but not unions). let is_npo = |def: AdtDef<'tcx>| { From e704858b0b41b72da9645f9a51e2e55a482fa5c4 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 5 Jun 2024 14:28:42 +0000 Subject: [PATCH 113/154] Update description of the `IsTerminal` example --- library/std/src/io/stdio.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index c8968b74b12d..9aee2bb5e1c5 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -1190,9 +1190,8 @@ pub trait IsTerminal: crate::sealed::Sealed { /// /// - If you run this example by piping some text to it, e.g. `echo "foo" | path/to/executable` /// it will print: `Hello foo`. - /// - If you instead run the example interactively by running the executable directly, it will - /// panic with the message "Expected input to be piped to the process". - /// + /// - If you instead run the example interactively by running `path/to/executable` directly, it will + /// prompt for input. /// /// [changes]: io#platform-specific-behavior /// [`Stdin`]: crate::io::Stdin From 2fe41c68d3819a94a3f6a7773e109619bd4cc241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 5 Jun 2024 16:41:59 +0200 Subject: [PATCH 114/154] Fix publishing of toolstate history --- .github/workflows/ci.yml | 3 ++- src/ci/github-actions/jobs.yml | 1 + src/ci/publish_toolstate.sh | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9d6c56076a9..d2d4a7e3d42f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,8 @@ concurrency: cancel-in-progress: true env: TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate" + # This will be empty in PR jobs. + TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }} jobs: # The job matrix for `calculate_matrix` is defined in src/ci/github-actions/jobs.yml. # It calculates which jobs should be executed, based on the data of the ${{ github }} context. @@ -242,6 +244,5 @@ jobs: shell: bash if: needs.calculate_matrix.outputs.run_type == 'auto' env: - TOOLSTATE_REPO_ACCESS_TOKEN: ${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }} TOOLSTATE_ISSUES_API_URL: https://api.github.com/repos/rust-lang/rust/issues TOOLSTATE_PUBLISH: 1 diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index ca86f3f0110e..45c3fb4b2cd1 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -58,6 +58,7 @@ envs: CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55 AWS_REGION: us-west-1 + TOOLSTATE_PUBLISH: 1 try: <<: *production diff --git a/src/ci/publish_toolstate.sh b/src/ci/publish_toolstate.sh index 691df04e754a..e828365c416f 100755 --- a/src/ci/publish_toolstate.sh +++ b/src/ci/publish_toolstate.sh @@ -24,8 +24,8 @@ cd rust-toolstate FAILURE=1 for RETRY_COUNT in 1 2 3 4 5; do # The purpose of this is to publish the new "current" toolstate in the toolstate repo. - # This happens post-landing, on master. - # (Publishing the per-commit test results happens pre-landing in src/bootstrap/toolstate.rs). + # This happens at the end of auto builds. + # (Publishing the per-commit test results happens in src/bootstrap/toolstate.rs). "$(ciCheckoutPath)/src/tools/publish_toolstate.py" "$GIT_COMMIT" \ "$GIT_COMMIT_MSG" \ "$MESSAGE_FILE" \ From cdccf52c8aad1ef95ed9b11d2540a6d3faf087ba Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Wed, 5 Jun 2024 15:25:42 +0000 Subject: [PATCH 115/154] Clarify our tier 1 Windows Server support --- src/doc/rustc/src/platform-support.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 77859956c95f..633c26a4f56c 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -33,12 +33,12 @@ All tier 1 targets with host tools support the full standard library. target | notes -------|------- `aarch64-unknown-linux-gnu` | ARM64 Linux (kernel 4.1, glibc 2.17+) -`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+) [^x86_32-floats-return-ABI] -`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+) [^x86_32-floats-return-ABI] +`i686-pc-windows-gnu` | 32-bit MinGW (Windows 10+, Windows Server 2016+) [^x86_32-floats-return-ABI] +`i686-pc-windows-msvc` | 32-bit MSVC (Windows 10+, Windows Server 2016+) [^x86_32-floats-return-ABI] `i686-unknown-linux-gnu` | 32-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI] [`x86_64-apple-darwin`](platform-support/apple-darwin.md) | 64-bit macOS (10.12+, Sierra+) -`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 10+) -`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 10+) +`x86_64-pc-windows-gnu` | 64-bit MinGW (Windows 10+, Windows Server 2016+) +`x86_64-pc-windows-msvc` | 64-bit MSVC (Windows 10+, Windows Server 2016+) `x86_64-unknown-linux-gnu` | 64-bit Linux (kernel 3.2+, glibc 2.17+) [^x86_32-floats-return-ABI]: Due to limitations of the C ABI, floating-point support on `i686` targets is non-compliant: floating-point return values are passed via an x87 register, so NaN payload bits can be lost. See [issue #114479][x86-32-float-issue]. From 50b07aa89970369d2a25203b9426a47a9fec5fb4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 14 Mar 2024 16:51:33 +0000 Subject: [PATCH 116/154] add reachability test for const bodies --- ...dont_codegen_private_const_fn_only_used_in_const_eval.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs b/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs index eeeaebe52dd1..98ccf93fb5e3 100644 --- a/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs +++ b/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs @@ -8,3 +8,9 @@ const fn foo() {} pub static FOO: () = foo(); // CHECK-NOT: define{{.*}}foo{{.*}} + +const fn bar() {} + +pub const BAR: () = bar(); + +// CHECK: define{{.*}}bar{{.*}} From 22d0073d47e7f82b0943db94babe40420205eb6a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 14 Mar 2024 17:19:06 +0000 Subject: [PATCH 117/154] Don't walk the bodies of free constants for reachability. --- .../rustc_middle/src/mir/interpret/queries.rs | 26 ++++++++++++++++--- compiler/rustc_passes/src/reachable.rs | 18 ++++++++++--- ...rivate_const_fn_only_used_in_const_eval.rs | 2 +- 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index fe743fa4aac2..95857e8579d9 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -1,4 +1,6 @@ -use super::{ErrorHandled, EvalToConstValueResult, EvalToValTreeResult, GlobalId}; +use super::{ + ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult, EvalToValTreeResult, GlobalId, +}; use crate::mir; use crate::query::TyCtxtEnsure; @@ -13,7 +15,7 @@ use tracing::{debug, instrument}; impl<'tcx> TyCtxt<'tcx> { /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts - /// that can't take any generic arguments like statics, const items or enum discriminants. If a + /// that can't take any generic arguments like const items or enum discriminants. If a /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned. #[instrument(skip(self), level = "debug")] pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> { @@ -27,6 +29,24 @@ impl<'tcx> TyCtxt<'tcx> { let param_env = self.param_env(def_id).with_reveal_all_normalized(self); self.const_eval_global_id(param_env, cid, DUMMY_SP) } + + /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts + /// that can't take any generic arguments like const items or enum discriminants. If a + /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned. + #[instrument(skip(self), level = "debug")] + pub fn const_eval_poly_to_alloc(self, def_id: DefId) -> EvalToAllocationRawResult<'tcx> { + // In some situations def_id will have generic parameters within scope, but they aren't allowed + // to be used. So we can't use `Instance::mono`, instead we feed unresolved generic parameters + // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are + // encountered. + let args = GenericArgs::identity_for_item(self, def_id); + let instance = ty::Instance::new(def_id, args); + let cid = GlobalId { instance, promoted: None }; + let param_env = self.param_env(def_id).with_reveal_all_normalized(self); + let inputs = self.erase_regions(param_env.and(cid)); + self.eval_to_allocation_raw(inputs) + } + /// Resolves and evaluates a constant. /// /// The constant can be located on a trait like `::C`, in which case the given @@ -177,7 +197,7 @@ impl<'tcx> TyCtxt<'tcx> { impl<'tcx> TyCtxtEnsure<'tcx> { /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts - /// that can't take any generic arguments like statics, const items or enum discriminants. If a + /// that can't take any generic arguments like const items or enum discriminants. If a /// generic parameter is used within the constant `ErrorHandled::ToGeneric` will be returned. #[instrument(skip(self), level = "debug")] pub fn const_eval_poly(self, def_id: DefId) { diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 954a1ab6560f..ee632ea5df3f 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -29,12 +29,12 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; -use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::middle::privacy::{self, Level}; -use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc}; +use rustc_middle::mir::interpret::{ConstAllocation, ErrorHandled, GlobalAlloc}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ExistentialTraitRef, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_privacy::DefIdVisitor; use rustc_session::config::CrateType; use tracing::debug; @@ -209,8 +209,18 @@ impl<'tcx> ReachableContext<'tcx> { // Reachable constants will be inlined into other crates // unconditionally, so we need to make sure that their // contents are also reachable. - hir::ItemKind::Const(_, _, init) => { - self.visit_nested_body(init); + hir::ItemKind::Const(..) => { + match self.tcx.const_eval_poly_to_alloc(item.owner_id.def_id.into()) { + Ok(alloc) => { + let alloc = self.tcx.global_alloc(alloc.alloc_id).unwrap_memory(); + self.propagate_from_alloc(alloc); + } + Err(ErrorHandled::TooGeneric(span)) => span_bug!( + span, + "generic constants aren't implemented in reachability" + ), + Err(ErrorHandled::Reported(..)) => {} + } } hir::ItemKind::Static(..) => { if let Ok(alloc) = self.tcx.eval_static_initializer(item.owner_id.def_id) { diff --git a/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs b/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs index 98ccf93fb5e3..35071e238f33 100644 --- a/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs +++ b/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs @@ -13,4 +13,4 @@ const fn bar() {} pub const BAR: () = bar(); -// CHECK: define{{.*}}bar{{.*}} +// CHECK-NOT: define{{.*}}bar{{.*}} From a0358f44b33301e28070327eae7804a88a912b15 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Jun 2024 15:32:13 +0000 Subject: [PATCH 118/154] Also support generic constants --- compiler/rustc_passes/src/reachable.rs | 18 +++++++++--------- ...private_const_fn_only_used_in_const_eval.rs | 11 +++++++++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index ee632ea5df3f..74b89546e6f9 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -29,12 +29,12 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::Node; +use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::middle::privacy::{self, Level}; use rustc_middle::mir::interpret::{ConstAllocation, ErrorHandled, GlobalAlloc}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, ExistentialTraitRef, TyCtxt}; -use rustc_middle::{bug, span_bug}; use rustc_privacy::DefIdVisitor; use rustc_session::config::CrateType; use tracing::debug; @@ -206,19 +206,19 @@ impl<'tcx> ReachableContext<'tcx> { } } - // Reachable constants will be inlined into other crates - // unconditionally, so we need to make sure that their - // contents are also reachable. - hir::ItemKind::Const(..) => { + hir::ItemKind::Const(_, _, init) => { + // Only things actually ending up in the final constant need to be reachable. + // Everything else is either already available as `mir_for_ctfe`, or can't be used + // by codegen anyway. match self.tcx.const_eval_poly_to_alloc(item.owner_id.def_id.into()) { Ok(alloc) => { let alloc = self.tcx.global_alloc(alloc.alloc_id).unwrap_memory(); self.propagate_from_alloc(alloc); } - Err(ErrorHandled::TooGeneric(span)) => span_bug!( - span, - "generic constants aren't implemented in reachability" - ), + // Reachable generic constants will be inlined into other crates + // unconditionally, so we need to make sure that their + // contents are also reachable. + Err(ErrorHandled::TooGeneric(_)) => self.visit_nested_body(init), Err(ErrorHandled::Reported(..)) => {} } } diff --git a/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs b/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs index 35071e238f33..df50b4af8098 100644 --- a/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs +++ b/tests/codegen/dont_codegen_private_const_fn_only_used_in_const_eval.rs @@ -3,6 +3,8 @@ //@compile-flags: --crate-type=lib -Copt-level=0 +#![feature(generic_const_items)] + const fn foo() {} pub static FOO: () = foo(); @@ -14,3 +16,12 @@ const fn bar() {} pub const BAR: () = bar(); // CHECK-NOT: define{{.*}}bar{{.*}} + +const fn baz() {} + +#[rustfmt::skip] +pub const BAZ: () = if C { + baz() +}; + +// CHECK: define{{.*}}baz{{.*}} From ae4ae1685c9fcdfd834736c6cbcd58ba13b3e8b9 Mon Sep 17 00:00:00 2001 From: Ana Hobden Date: Thu, 16 May 2024 13:10:17 -0700 Subject: [PATCH 119/154] Repair several riscv64gc-unknown-linux-gnu codegen tests Fix tests/codegen/riscv-abi/call-llvm-intrinsics.rs Fix tests/codegen/riscv-abi/riscv64-lp64d-abi.rs Fix tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs On riscv64gc ignore tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs Make tests/codegen/riscv-abi/riscv64-lp64d-abi.rs no_core Make tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs no_core Set -O for tests/codegen/riscv-abi/riscv64-lp64d-abi.rs Set -O for tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs --- .../codegen/riscv-abi/call-llvm-intrinsics.rs | 2 +- tests/codegen/riscv-abi/riscv64-lp64d-abi.rs | 27 ++++++++++++------- .../riscv-abi/riscv64-lp64f-lp64d-abi.rs | 23 +++++++++++----- ...uginfo-emit-llvm-ir-and-split-debuginfo.rs | 1 + 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/tests/codegen/riscv-abi/call-llvm-intrinsics.rs b/tests/codegen/riscv-abi/call-llvm-intrinsics.rs index c3f795e88576..e72a649a530a 100644 --- a/tests/codegen/riscv-abi/call-llvm-intrinsics.rs +++ b/tests/codegen/riscv-abi/call-llvm-intrinsics.rs @@ -23,7 +23,7 @@ pub fn do_call() { unsafe { // Ensure that we `call` LLVM intrinsics instead of trying to `invoke` them - // CHECK: store float 4.000000e+00, float* %{{.}}, align 4 + // CHECK: store float 4.000000e+00, ptr %{{.}}, align 4 // CHECK: call float @llvm.sqrt.f32(float %{{.}} sqrt(4.0); } diff --git a/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs index 060d91a2696a..bcd9b0eae71d 100644 --- a/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs +++ b/tests/codegen/riscv-abi/riscv64-lp64d-abi.rs @@ -1,10 +1,19 @@ -// -//@ compile-flags: -C no-prepopulate-passes -//@ only-riscv64 -//@ only-linux -#![crate_type = "lib"] +//@ compile-flags: -O -C no-prepopulate-passes --target riscv64gc-unknown-linux-gnu +//@ needs-llvm-components: riscv -// CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 zeroext %i) +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} + +// CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 noundef zeroext %i) #[no_mangle] pub extern "C" fn f_fpr_tracking( a: f64, @@ -144,7 +153,7 @@ pub extern "C" fn f_ret_double_int64_s() -> DoubleInt64 { DoubleInt64 { f: 1., i: 2 } } -// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, [2 x i64] %0) +// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 noundef signext %a, i32 noundef signext %b, i32 noundef signext %c, i32 noundef signext %d, i32 noundef signext %e, i32 noundef signext %f, i32 noundef signext %g, i32 noundef signext %h, [2 x i64] %0) #[no_mangle] pub extern "C" fn f_double_int8_s_arg_insufficient_gprs( a: i32, @@ -250,11 +259,11 @@ pub struct IntDoubleInt { c: i32, } -// CHECK: define void @f_int_double_int_s_arg(%IntDoubleInt* {{.*}}%a) +// CHECK: define void @f_int_double_int_s_arg(ptr {{.*}} %a) #[no_mangle] pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {} -// CHECK: define void @f_ret_int_double_int_s(%IntDoubleInt* {{.*}}sret +// CHECK: define void @f_ret_int_double_int_s(ptr {{.*}} sret([24 x i8]) align 8 dereferenceable(24) %_0) #[no_mangle] pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt { IntDoubleInt { a: 1, b: 2., c: 3 } diff --git a/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs b/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs index 3d0512817f7c..27018d2e6d20 100644 --- a/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs +++ b/tests/codegen/riscv-abi/riscv64-lp64f-lp64d-abi.rs @@ -1,10 +1,19 @@ -// -//@ compile-flags: -C no-prepopulate-passes -//@ only-riscv64 -//@ only-linux -#![crate_type = "lib"] +//@ compile-flags: -O -C no-prepopulate-passes --target riscv64gc-unknown-linux-gnu +//@ needs-llvm-components: riscv -// CHECK: define void @f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 zeroext %i) +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} + +// CHECK: define void @f_fpr_tracking(float %0, float %1, float %2, float %3, float %4, float %5, float %6, float %7, i8 noundef zeroext %i) #[no_mangle] pub extern "C" fn f_fpr_tracking( a: f32, @@ -128,7 +137,7 @@ pub extern "C" fn f_ret_float_int64_s() -> FloatInt64 { FloatInt64 { f: 1., i: 2 } } -// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, i64 %0) +// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 noundef signext %a, i32 noundef signext %b, i32 noundef signext %c, i32 noundef signext %d, i32 noundef signext %e, i32 noundef signext %f, i32 noundef signext %g, i32 noundef signext %h, i64 %0) #[no_mangle] pub extern "C" fn f_float_int8_s_arg_insufficient_gprs( a: i32, diff --git a/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs b/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs index 861179650164..3322660d1a85 100644 --- a/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs +++ b/tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs @@ -1,5 +1,6 @@ //@ build-pass //@ only-linux +//@ ignore-riscv64 On this platform `-Csplit-debuginfo=unpacked` is unstable, see #120518 // //@ compile-flags: -g --emit=llvm-ir -Csplit-debuginfo=unpacked // From 743c41757c3211d989334b50b71df34279add5bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olaf=20Siwi=C5=84ski?= Date: Wed, 5 Jun 2024 21:54:22 +0200 Subject: [PATCH 120/154] check_expr_struct_fields: taint context with errors if struct definition is malformed --- compiler/rustc_hir_typeck/src/expr.rs | 9 ++++++++ tests/crashes/124552.rs | 12 ---------- .../static/duplicated-fields-issue-124464.rs} | 6 ++++- .../duplicated-fields-issue-124464.stderr | 22 +++++++++++++++++++ .../static/duplicated-fields-issue-125842.rs | 21 ++++++++++++++++++ .../duplicated-fields-issue-125842.stderr | 11 ++++++++++ 6 files changed, 68 insertions(+), 13 deletions(-) delete mode 100644 tests/crashes/124552.rs rename tests/{crashes/124464.rs => ui/static/duplicated-fields-issue-124464.rs} (57%) create mode 100644 tests/ui/static/duplicated-fields-issue-124464.stderr create mode 100644 tests/ui/static/duplicated-fields-issue-125842.rs create mode 100644 tests/ui/static/duplicated-fields-issue-125842.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4cc936eed08c..7dd7b3ff055e 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1671,6 +1671,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut error_happened = false; + if variant.fields.len() != remaining_fields.len() { + // Some field is defined more than once. Make sure we don't try to + // instantiate this struct in static/const context. + let guar = + self.dcx().span_delayed_bug(expr.span, "struct fields have non-unique names"); + self.set_tainted_by_errors(guar); + error_happened = true; + } + // Type-check each field. for (idx, field) in hir_fields.iter().enumerate() { let ident = tcx.adjust_ident(field.ident, variant.def_id); diff --git a/tests/crashes/124552.rs b/tests/crashes/124552.rs deleted file mode 100644 index 5320ce278430..000000000000 --- a/tests/crashes/124552.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ known-bug: rust-lang/rust#124552 - -struct B; - -struct Foo { - b: u32, - b: B, -} - -static BAR: Foo = Foo { b: B }; - -fn main() {} diff --git a/tests/crashes/124464.rs b/tests/ui/static/duplicated-fields-issue-124464.rs similarity index 57% rename from tests/crashes/124464.rs rename to tests/ui/static/duplicated-fields-issue-124464.rs index 471479f5cf1b..60609edbfebb 100644 --- a/tests/crashes/124464.rs +++ b/tests/ui/static/duplicated-fields-issue-124464.rs @@ -1,12 +1,16 @@ -//@ known-bug: rust-lang/rust #124464 +// Don't const eval fields with ambiguous layout. +// See issues #125842 and #124464. + enum TestOption { TestSome(T), TestSome(T), +//~^ ERROR the name `TestSome` is defined multiple times } pub struct Request { bar: TestOption, bar: u8, +//~^ ERROR field `bar` is already declared } fn default_instance() -> &'static Request { diff --git a/tests/ui/static/duplicated-fields-issue-124464.stderr b/tests/ui/static/duplicated-fields-issue-124464.stderr new file mode 100644 index 000000000000..a36192ae8d69 --- /dev/null +++ b/tests/ui/static/duplicated-fields-issue-124464.stderr @@ -0,0 +1,22 @@ +error[E0428]: the name `TestSome` is defined multiple times + --> $DIR/duplicated-fields-issue-124464.rs:6:5 + | +LL | TestSome(T), + | ----------- previous definition of the type `TestSome` here +LL | TestSome(T), + | ^^^^^^^^^^^ `TestSome` redefined here + | + = note: `TestSome` must be defined only once in the type namespace of this enum + +error[E0124]: field `bar` is already declared + --> $DIR/duplicated-fields-issue-124464.rs:12:5 + | +LL | bar: TestOption, + | -------------------- `bar` first declared here +LL | bar: u8, + | ^^^^^^^ field already declared + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0124, E0428. +For more information about an error, try `rustc --explain E0124`. diff --git a/tests/ui/static/duplicated-fields-issue-125842.rs b/tests/ui/static/duplicated-fields-issue-125842.rs new file mode 100644 index 000000000000..580b810232e0 --- /dev/null +++ b/tests/ui/static/duplicated-fields-issue-125842.rs @@ -0,0 +1,21 @@ +// Do not try to evaluate static initalizers that reference +// ill-defined types. This used to be an ICE. +// See issues #125842 and #124464. +struct Struct { + field: Option, + field: u8, +//~^ ERROR field `field` is already declared +} + +static STATIC_A: Struct = Struct { + field: 1 +}; + +static STATIC_B: Struct = { + let field = 1; + Struct { + field, + } +}; + +fn main() {} diff --git a/tests/ui/static/duplicated-fields-issue-125842.stderr b/tests/ui/static/duplicated-fields-issue-125842.stderr new file mode 100644 index 000000000000..c80bb99005ee --- /dev/null +++ b/tests/ui/static/duplicated-fields-issue-125842.stderr @@ -0,0 +1,11 @@ +error[E0124]: field `field` is already declared + --> $DIR/duplicated-fields-issue-125842.rs:6:5 + | +LL | field: Option, + | ----------------- `field` first declared here +LL | field: u8, + | ^^^^^^^^^ field already declared + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0124`. From 88e81bca9f83157afec49c4cddcdf25497cfe507 Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Fri, 24 May 2024 17:09:21 +0200 Subject: [PATCH 121/154] Fix typos in cargo-specifics.md --- src/doc/rustc/src/check-cfg/cargo-specifics.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc/src/check-cfg/cargo-specifics.md b/src/doc/rustc/src/check-cfg/cargo-specifics.md index bfa601619261..e3b8b537c42c 100644 --- a/src/doc/rustc/src/check-cfg/cargo-specifics.md +++ b/src/doc/rustc/src/check-cfg/cargo-specifics.md @@ -8,7 +8,7 @@ be an implementation detail, at least --check-cfg and the unexpected_cfgs are ow rustc, not Cargo. --> -This document is intented to summarize the principal ways Cargo interacts with +This document is intended to summarize the principal ways Cargo interacts with the `unexpected_cfgs` lint and `--check-cfg` flag. It is not intended to provide individual details, for that refer to the [`--check-cfg` documentation](../check-cfg.md) and to the [Cargo book](../../cargo/index.html). @@ -37,11 +37,11 @@ implementation detail and is therefor not documented in Cargo, we therefor do th *See the [`[lints]` section in the Cargo book][cargo-lints-table] for more details.* -When using a staticlly known custom config (ie. not dependant on a build-script), Cargo provides +When using a statically known custom config (ie. not dependant on a build-script), Cargo provides the custom lint config `check-cfg` under `[lints.rust.unexpected_cfgs]`. It can be used to set custom static [`--check-cfg`](../check-cfg.md) args, it is mainly useful when -the list of expected cfgs is known is advance. +the list of expected cfgs is known in advance. `Cargo.toml`: ```toml From 964e88555ba6a9fc41d3a19e114b77ed5064bad9 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 5 Jun 2024 13:34:21 -0700 Subject: [PATCH 122/154] Fix some wording in cargo-specifics.md --- src/doc/rustc/src/check-cfg/cargo-specifics.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc/src/check-cfg/cargo-specifics.md b/src/doc/rustc/src/check-cfg/cargo-specifics.md index e3b8b537c42c..bd4bebbc874a 100644 --- a/src/doc/rustc/src/check-cfg/cargo-specifics.md +++ b/src/doc/rustc/src/check-cfg/cargo-specifics.md @@ -3,7 +3,7 @@ @@ -17,7 +17,7 @@ to the [Cargo book](../../cargo/index.html). *See the [`[features]` section in the Cargo book][cargo-features] for more details.* -With the `[features]` table Cargo provides a mechanism to express conditional compilation and +With the `[features]` table, Cargo provides a mechanism to express conditional compilation and optional dependencies. Cargo *automatically* declares corresponding cfgs for every feature as expected. @@ -32,12 +32,12 @@ my_feature = [] ## `check-cfg` in `[lints.rust]` table - + *See the [`[lints]` section in the Cargo book][cargo-lints-table] for more details.* -When using a statically known custom config (ie. not dependant on a build-script), Cargo provides +When using a statically known custom config (i.e., not dependent on a build-script), Cargo provides the custom lint config `check-cfg` under `[lints.rust.unexpected_cfgs]`. It can be used to set custom static [`--check-cfg`](../check-cfg.md) args, it is mainly useful when From 58feec9b85a18d26507dfe6d075fd128a1265888 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 3 Jun 2024 01:10:24 +0100 Subject: [PATCH 123/154] Basic removal of `Ty` from places (boring) --- .../src/type_check/relate_tys.rs | 4 +- .../src/debuginfo/type_names.rs | 3 +- .../src/check/compare_impl_item.rs | 3 - compiler/rustc_hir_analysis/src/collect.rs | 12 +- .../src/collect/predicates_of.rs | 2 +- .../src/hir_ty_lowering/bounds.rs | 6 +- .../src/hir_ty_lowering/mod.rs | 47 +++--- .../src/hir_ty_lowering/object_safety.rs | 3 +- compiler/rustc_hir_typeck/src/demand.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 14 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 9 +- .../rustc_hir_typeck/src/method/confirm.rs | 11 +- .../rustc_hir_typeck/src/method/suggest.rs | 4 +- compiler/rustc_hir_typeck/src/writeback.rs | 2 +- .../src/infer/canonical/canonicalizer.rs | 27 ++-- .../src/infer/canonical/instantiate.rs | 2 +- .../rustc_infer/src/infer/canonical/mod.rs | 11 +- .../infer/error_reporting/need_type_info.rs | 4 +- compiler/rustc_infer/src/infer/freshen.rs | 7 +- compiler/rustc_infer/src/infer/mod.rs | 53 ++----- .../src/infer/relate/generalize.rs | 8 +- .../src/infer/relate/higher_ranked.rs | 3 +- .../rustc_infer/src/infer/snapshot/fudge.rs | 2 +- compiler/rustc_middle/src/mir/consts.rs | 28 ++-- .../rustc_middle/src/ty/abstract_const.rs | 2 +- compiler/rustc_middle/src/ty/codec.rs | 4 +- compiler/rustc_middle/src/ty/consts.rs | 144 ++++++------------ compiler/rustc_middle/src/ty/context.rs | 51 +++---- compiler/rustc_middle/src/ty/flags.rs | 5 +- compiler/rustc_middle/src/ty/fold.rs | 20 ++- compiler/rustc_middle/src/ty/generic_args.rs | 6 +- compiler/rustc_middle/src/ty/generics.rs | 12 +- compiler/rustc_middle/src/ty/layout.rs | 4 +- compiler/rustc_middle/src/ty/mod.rs | 4 +- compiler/rustc_middle/src/ty/opaque_types.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- compiler/rustc_middle/src/ty/relate.rs | 13 +- .../rustc_middle/src/ty/structural_impls.rs | 19 +-- compiler/rustc_middle/src/ty/walk.rs | 25 ++- .../src/build/expr/as_constant.rs | 6 +- .../src/canonicalizer.rs | 50 +----- .../rustc_next_trait_solver/src/resolve.rs | 7 +- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 11 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 5 +- compiler/rustc_symbol_mangling/src/legacy.rs | 11 +- compiler/rustc_symbol_mangling/src/v0.rs | 16 +- .../src/solve/eval_ctxt/canonical.rs | 2 +- .../src/solve/eval_ctxt/mod.rs | 14 +- .../src/solve/inspect/analyse.rs | 2 +- .../rustc_trait_selection/src/solve/mod.rs | 5 +- .../src/solve/normalize.rs | 9 +- .../src/solve/normalizes_to/anon_const.rs | 4 - .../src/solve/normalizes_to/mod.rs | 9 +- .../src/traits/auto_trait.rs | 3 +- .../src/traits/coherence.rs | 1 - .../src/traits/const_evaluatable.rs | 4 +- .../error_reporting/type_err_ctxt_ext.rs | 3 +- .../src/traits/fulfill.rs | 4 +- .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/project.rs | 20 +-- .../src/traits/select/confirmation.rs | 3 - .../src/traits/select/mod.rs | 5 +- .../rustc_trait_selection/src/traits/util.rs | 4 +- compiler/rustc_transmute/src/lib.rs | 3 +- compiler/rustc_ty_utils/src/consts.rs | 41 ++--- compiler/rustc_type_ir/src/canonical.rs | 55 +++---- compiler/rustc_type_ir/src/debug.rs | 4 +- compiler/rustc_type_ir/src/fold.rs | 2 +- compiler/rustc_type_ir/src/infcx.rs | 7 +- compiler/rustc_type_ir/src/inherent.rs | 17 +-- compiler/rustc_type_ir/src/predicate.rs | 1 - 71 files changed, 331 insertions(+), 581 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index cbd8a4125cd3..9863c4a38832 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -193,7 +193,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> { types: &mut |_bound_ty: ty::BoundTy| { unreachable!("we only replace regions in nll_relate, not types") }, - consts: &mut |_bound_var: ty::BoundVar, _ty| { + consts: &mut |_bound_var: ty::BoundVar| { unreachable!("we only replace regions in nll_relate, not consts") }, }; @@ -231,7 +231,7 @@ impl<'me, 'bccx, 'tcx> NllTypeRelating<'me, 'bccx, 'tcx> { types: &mut |_bound_ty: ty::BoundTy| { unreachable!("we only replace regions in nll_relate, not types") }, - consts: &mut |_bound_var: ty::BoundVar, _ty| { + consts: &mut |_bound_var: ty::BoundVar| { unreachable!("we only replace regions in nll_relate, not consts") }, }; diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 2360cce55a99..2783ffc49a81 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -693,7 +693,8 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S ty::ConstKind::Param(param) => { write!(output, "{}", param.name) } - _ => match ct.ty().kind() { + // THISPR + _ => match { todo!() as Ty<'tcx> }.kind() { ty::Int(ity) => { let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all()); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 74dcd672578e..82b57cdd1069 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2198,9 +2198,6 @@ fn param_env_with_gat_bounds<'tcx>( tcx, ty::INNERMOST, ty::BoundVar::from_usize(bound_vars.len() - 1), - tcx.type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), ) .into() } diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index d84dcb78ad2e..092d2d304c38 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -396,16 +396,8 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { Ty::new_error_with_message(self.tcx(), span, "bad placeholder type") } - fn ct_infer(&self, ty: Ty<'tcx>, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> { - let ty = self.tcx.fold_regions(ty, |r, _| match *r { - rustc_type_ir::RegionKind::ReStatic => r, - - // This is never reached in practice. If it ever is reached, - // `ReErased` should be changed to `ReStatic`, and any other region - // left alone. - r => bug!("unexpected region: {r:?}"), - }); - ty::Const::new_error_with_message(self.tcx(), ty, span, "bad placeholder constant") + fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> { + ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant") } fn probe_ty_param_bounds( diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 913fae6b5b69..40204961e9c4 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -196,7 +196,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen .type_of(param.def_id.to_def_id()) .no_bound_vars() .expect("const parameters cannot be generic"); - let ct = icx.lowerer().lower_const_param(param.hir_id, ct_ty); + let ct = icx.lowerer().lower_const_param(param.hir_id); predicates .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span)); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 73ce577907eb..7f6f57907c28 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -368,11 +368,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }, ) }); - let ty = tcx - .type_of(param.def_id) - .no_bound_vars() - .expect("ct params cannot have early bound vars"); - ty::Const::new_error(tcx, guar, ty).into() + ty::Const::new_error(tcx, guar).into() } }; num_bound_vars += 1; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 9b8edbc10ad8..0dee904c5a2d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -111,12 +111,7 @@ pub trait HirTyLowerer<'tcx> { fn ty_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx>; /// Returns the const to use when a const is omitted. - fn ct_infer( - &self, - ty: Ty<'tcx>, - param: Option<&ty::GenericParamDef>, - span: Span, - ) -> Const<'tcx>; + fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx>; /// Probe bounds in scope where the bounded type coincides with the given type parameter. /// @@ -439,7 +434,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn provided_kind( &mut self, - preceding_args: &[ty::GenericArg<'tcx>], + _preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, arg: &GenericArg<'tcx>, ) -> ty::GenericArg<'tcx> { @@ -447,7 +442,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Err(incorrect) = self.incorrect_args { if incorrect.invalid_args.contains(&(param.index as usize)) { - return param.to_error(tcx, preceding_args); + return param.to_error(tcx); } } @@ -487,12 +482,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ty::Const::from_anon_const(tcx, did).into() } (&GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => { - let ty = tcx - .at(self.span) - .type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"); - self.lowerer.ct_infer(ty, Some(param), inf.span).into() + self.lowerer.ct_infer(Some(param), inf.span).into() } (kind, arg) => span_bug!( self.span, @@ -511,7 +501,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let Err(incorrect) = self.incorrect_args { if incorrect.invalid_args.contains(&(param.index as usize)) { - return param.to_error(tcx, preceding_args); + return param.to_error(tcx); } } match param.kind { @@ -548,7 +538,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .no_bound_vars() .expect("const parameter types cannot be generic"); if let Err(guar) = ty.error_reported() { - return ty::Const::new_error(tcx, guar, ty).into(); + return ty::Const::new_error(tcx, guar).into(); } // FIXME(effects) see if we should special case effect params here if !infer_args && has_default { @@ -557,10 +547,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .into() } else { if infer_args { - self.lowerer.ct_infer(ty, Some(param), self.span).into() + self.lowerer.ct_infer(Some(param), self.span).into() } else { // We've already errored above about the mismatch. - ty::Const::new_misc_error(tcx, ty).into() + ty::Const::new_misc_error(tcx).into() } } } @@ -1908,7 +1898,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// Early-bound const parameters get lowered to [`ty::ConstKind::Param`] /// and late-bound ones to [`ty::ConstKind::Bound`]. - pub(crate) fn lower_const_param(&self, hir_id: HirId, param_ty: Ty<'tcx>) -> Const<'tcx> { + pub(crate) fn lower_const_param(&self, hir_id: HirId) -> Const<'tcx> { let tcx = self.tcx(); match tcx.named_bound_var(hir_id) { Some(rbv::ResolvedArg::EarlyBound(def_id)) => { @@ -1918,12 +1908,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.item_name(def_id); - ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty) + ty::Const::new_param(tcx, ty::ParamConst::new(index, name)) } Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { - ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index), param_ty) + ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)) } - Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar, param_ty), + Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar), arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", hir_id), } } @@ -2139,7 +2129,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } hir::TyKind::Array(ty, length) => { let length = match length { - hir::ArrayLen::Infer(inf) => self.ct_infer(tcx.types.usize, None, inf.span), + hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), hir::ArrayLen::Body(constant) => { ty::Const::from_anon_const(tcx, constant.def_id) } @@ -2177,7 +2167,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match tcx.lit_to_const(lit_input) { Ok(c) => c, Err(LitToConstError::Reported(err)) => { - ty::Const::new_error(tcx, err, ty) + ty::Const::new_error(tcx, err) } Err(LitToConstError::TypeError) => todo!(), } @@ -2198,19 +2188,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .type_of(def_id) .no_bound_vars() .expect("const parameter types cannot be generic"); - self.lower_const_param(expr.hir_id, ty) + self.lower_const_param(expr.hir_id) } _ => { let err = tcx .dcx() .emit_err(crate::errors::NonConstRange { span: expr.span }); - ty::Const::new_error(tcx, err, ty) + ty::Const::new_error(tcx, err) } }; - self.record_ty(expr.hir_id, c.ty(), expr.span); + // THISPR + self.record_ty(expr.hir_id, todo!(), expr.span); if let Some((id, span)) = neg { - self.record_ty(id, c.ty(), span); + self.record_ty(id, todo!(), span); } c }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index b9c5ae0c65b5..ed1749ea14f0 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -144,7 +144,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let references_self = match pred.skip_binder().term.unpack() { ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), ty::TermKind::Const(c) => { - c.ty().walk().any(|arg| arg == dummy_self.into()) + // THISPR + false } }; diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index fa147f9bfcfe..5d30b2a71e09 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -350,7 +350,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lt_op: |_| self.tcx.lifetimes.re_erased, ct_op: |ct| { if let ty::ConstKind::Infer(_) = ct.kind() { - self.next_const_var(ct.ty(), DUMMY_SP) + self.next_const_var(DUMMY_SP) } else { ct } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 084639ad40c0..616ce1f5b06d 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -436,7 +436,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn lower_array_length(&self, length: &hir::ArrayLen<'tcx>) -> ty::Const<'tcx> { match length { - hir::ArrayLen::Infer(inf) => self.ct_infer(self.tcx.types.usize, None, inf.span), + hir::ArrayLen::Infer(inf) => self.ct_infer(None, inf.span), hir::ArrayLen::Body(anon_const) => { let span = self.tcx.def_span(anon_const.def_id); let c = ty::Const::from_anon_const(self.tcx, anon_const.def_id); @@ -1292,20 +1292,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &GenericParamDefKind::Const { has_default, is_host_effect }, GenericArg::Infer(inf), ) => { - let tcx = self.fcx.tcx(); - if has_default && is_host_effect { self.fcx.var_for_effect(param) } else { - self.fcx - .ct_infer( - tcx.type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - Some(param), - inf.span, - ) - .into() + self.fcx.ct_infer(Some(param), inf.span).into() } } _ => unreachable!(), diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index b9ff348c42ff..f02b0f953900 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -237,12 +237,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { } } - fn ct_infer( - &self, - ty: Ty<'tcx>, - param: Option<&ty::GenericParamDef>, - span: Span, - ) -> Const<'tcx> { + fn ct_infer(&self, param: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> { // FIXME ideally this shouldn't use unwrap match param { Some( @@ -252,7 +247,7 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { }, ) => self.var_for_effect(param).as_const().unwrap(), Some(param) => self.var_for_def(span, param).as_const().unwrap(), - None => self.next_const_var(ty, span), + None => self.next_const_var(span), } } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 949b92410053..3c9a49e91a3f 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -406,16 +406,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { self.cfcx.ty_infer(Some(param), inf.span).into() } (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { - let tcx = self.cfcx.tcx(); - self.cfcx - .ct_infer( - tcx.type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - Some(param), - inf.span, - ) - .into() + self.cfcx.ct_infer(Some(param), inf.span).into() } (kind, arg) => { bug!("mismatched method arg kind {kind:?} in turbofish: {arg:?}") diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index b3947e142b26..c1e14f7fb753 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2096,9 +2096,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) .into(), GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(), - GenericArgKind::Const(arg) => { - self.next_const_var(arg.ty(), DUMMY_SP).into() - } + GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(), } } else { arg diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index e337105f0110..8727c0f87dc8 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -863,7 +863,7 @@ impl<'cx, 'tcx> TypeFolder> for Resolver<'cx, 'tcx> { fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { self.handle_term(ct, ty::Const::outer_exclusive_binder, |tcx, guar| { - ty::Const::new_error(tcx, guar, ct.ty()) + ty::Const::new_error(tcx, guar) }) .super_fold_with(self) } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 27b06c4b73e9..bc2592b43f3d 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -462,7 +462,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { // any equated inference vars correctly! let root_vid = self.infcx.unwrap().root_const_var(vid); if root_vid != vid { - ct = ty::Const::new_var(self.tcx, root_vid, ct.ty()); + ct = ty::Const::new_var(self.tcx, root_vid); vid = root_vid; } @@ -481,7 +481,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { ui = ty::UniverseIndex::ROOT; } return self.canonicalize_const_var( - CanonicalVarInfo { kind: CanonicalVarKind::Const(ui, ct.ty()) }, + CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) }, ct, ); } @@ -510,9 +510,7 @@ impl<'cx, 'tcx> TypeFolder> for Canonicalizer<'cx, 'tcx> { } ty::ConstKind::Placeholder(placeholder) => { return self.canonicalize_const_var( - CanonicalVarInfo { - kind: CanonicalVarKind::PlaceholderConst(placeholder, ct.ty()), - }, + CanonicalVarInfo { kind: CanonicalVarKind::PlaceholderConst(placeholder) }, ct, ); } @@ -719,9 +717,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { CanonicalVarKind::Region(u) => { CanonicalVarKind::Region(reverse_universe_map[&u]) } - CanonicalVarKind::Const(u, t) => { - CanonicalVarKind::Const(reverse_universe_map[&u], t) - } + CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]), CanonicalVarKind::PlaceholderTy(placeholder) => { CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: reverse_universe_map[&placeholder.universe], @@ -734,14 +730,11 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { ..placeholder }) } - CanonicalVarKind::PlaceholderConst(placeholder, t) => { - CanonicalVarKind::PlaceholderConst( - ty::Placeholder { - universe: reverse_universe_map[&placeholder.universe], - ..placeholder - }, - t, - ) + CanonicalVarKind::PlaceholderConst(placeholder) => { + CanonicalVarKind::PlaceholderConst(ty::Placeholder { + universe: reverse_universe_map[&placeholder.universe], + ..placeholder + }) } }, }) @@ -806,6 +799,6 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { !self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var)) ); let var = self.canonical_var(info, const_var.into()); - ty::Const::new_bound(self.tcx, self.binder_index, var, self.fold_ty(const_var.ty())) + ty::Const::new_bound(self.tcx, self.binder_index, var) } } diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs index de0e15ef3def..153de3d4c09d 100644 --- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs +++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs @@ -70,7 +70,7 @@ where GenericArgKind::Type(ty) => ty, r => bug!("{:?} is a type but value is {:?}", bound_ty, r), }, - consts: &mut |bound_ct: ty::BoundVar, _| match var_values[bound_ct].unpack() { + consts: &mut |bound_ct: ty::BoundVar| match var_values[bound_ct].unpack() { GenericArgKind::Const(ct) => ct, c => bug!("{:?} is a const but value is {:?}", bound_ct, c), }, diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs index 1abb8086d41c..8ad4f7926cad 100644 --- a/compiler/rustc_infer/src/infer/canonical/mod.rs +++ b/compiler/rustc_infer/src/infer/canonical/mod.rs @@ -143,8 +143,8 @@ impl<'tcx> InferCtxt<'tcx> { ty::Region::new_placeholder(self.tcx, placeholder_mapped).into() } - CanonicalVarKind::Const(ui, ty) => { - self.next_const_var_in_universe(ty, span, universe_map(ui)).into() + CanonicalVarKind::Const(ui) => { + self.next_const_var_in_universe(span, universe_map(ui)).into() } CanonicalVarKind::Effect => { let vid = self @@ -153,13 +153,12 @@ impl<'tcx> InferCtxt<'tcx> { .effect_unification_table() .new_key(EffectVarValue::Unknown) .vid; - ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid), self.tcx.types.bool) - .into() + ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(vid)).into() } - CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => { + CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }) => { let universe_mapped = universe_map(universe); let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound }; - ty::Const::new_placeholder(self.tcx, placeholder_mapped, ty).into() + ty::Const::new_placeholder(self.tcx, placeholder_mapped).into() } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index fb8c843f3095..cb0e13652e80 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -543,9 +543,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { match arg.unpack() { GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"), GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(), - GenericArgKind::Const(arg) => { - self.next_const_var(arg.ty(), DUMMY_SP).into() - } + GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(), } })) .unwrap(); diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index a3c8d5f4251e..3ef25ae2d3ed 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -79,7 +79,6 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { &mut self, input: Result, ty::InferConst>, freshener: F, - ty: Ty<'tcx>, ) -> ty::Const<'tcx> where F: FnOnce(u32) -> ty::InferConst, @@ -91,7 +90,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { Entry::Vacant(entry) => { let index = self.const_freshen_count; self.const_freshen_count += 1; - let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index), ty); + let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index)); entry.insert(ct); ct } @@ -149,7 +148,7 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { ty::InferConst::Var(inner.const_unification_table().find(v).vid) }); drop(inner); - self.freshen_const(input, ty::InferConst::Fresh, ct.ty()) + self.freshen_const(input, ty::InferConst::Fresh) } ty::ConstKind::Infer(ty::InferConst::EffectVar(v)) => { let mut inner = self.infcx.inner.borrow_mut(); @@ -158,7 +157,7 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { ty::InferConst::EffectVar(inner.effect_unification_table().find(v).vid) }); drop(inner); - self.freshen_const(input, ty::InferConst::Fresh, ct.ty()) + self.freshen_const(input, ty::InferConst::Fresh) } ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => { if i >= self.const_freshen_count { diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e9a4cc3e04b6..1f6c534fbec6 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -392,18 +392,18 @@ impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { self.opportunistic_resolve_float_var(vid) } - fn opportunistic_resolve_ct_var(&self, vid: ConstVid, ty: Ty<'tcx>) -> ty::Const<'tcx> { + fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> ty::Const<'tcx> { match self.probe_const_var(vid) { Ok(ct) => ct, - Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid), ty), + Err(_) => ty::Const::new_var(self.tcx, self.root_const_var(vid)), } } - fn opportunistic_resolve_effect_var(&self, vid: EffectVid, ty: Ty<'tcx>) -> ty::Const<'tcx> { + fn opportunistic_resolve_effect_var(&self, vid: EffectVid) -> ty::Const<'tcx> { match self.probe_effect_var(vid) { Some(ct) => ct, None => { - ty::Const::new_infer(self.tcx, InferConst::EffectVar(self.root_effect_var(vid)), ty) + ty::Const::new_infer(self.tcx, InferConst::EffectVar(self.root_effect_var(vid))) } } } @@ -832,9 +832,7 @@ impl<'tcx> InferCtxt<'tcx> { (0..table.len()) .map(|i| ty::EffectVid::from_usize(i)) .filter(|&vid| table.probe_value(vid).is_unknown()) - .map(|v| { - ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v), self.tcx.types.bool) - }) + .map(|v| ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(v))) .collect() } @@ -993,27 +991,22 @@ impl<'tcx> InferCtxt<'tcx> { Ty::new_var(self.tcx, vid) } - pub fn next_const_var(&self, ty: Ty<'tcx>, span: Span) -> ty::Const<'tcx> { - self.next_const_var_with_origin(ty, ConstVariableOrigin { span, param_def_id: None }) + pub fn next_const_var(&self, span: Span) -> ty::Const<'tcx> { + self.next_const_var_with_origin(ConstVariableOrigin { span, param_def_id: None }) } - pub fn next_const_var_with_origin( - &self, - ty: Ty<'tcx>, - origin: ConstVariableOrigin, - ) -> ty::Const<'tcx> { + pub fn next_const_var_with_origin(&self, origin: ConstVariableOrigin) -> ty::Const<'tcx> { let vid = self .inner .borrow_mut() .const_unification_table() .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) .vid; - ty::Const::new_var(self.tcx, vid, ty) + ty::Const::new_var(self.tcx, vid) } pub fn next_const_var_in_universe( &self, - ty: Ty<'tcx>, span: Span, universe: ty::UniverseIndex, ) -> ty::Const<'tcx> { @@ -1024,7 +1017,7 @@ impl<'tcx> InferCtxt<'tcx> { .const_unification_table() .new_key(ConstVariableValue::Unknown { origin, universe }) .vid; - ty::Const::new_var(self.tcx, vid, ty) + ty::Const::new_var(self.tcx, vid) } pub fn next_const_var_id(&self, origin: ConstVariableOrigin) -> ConstVid { @@ -1135,15 +1128,7 @@ impl<'tcx> InferCtxt<'tcx> { .const_unification_table() .new_key(ConstVariableValue::Unknown { origin, universe: self.universe() }) .vid; - ty::Const::new_var( - self.tcx, - const_var_id, - self.tcx - .type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - ) - .into() + ty::Const::new_var(self.tcx, const_var_id).into() } } } @@ -1157,7 +1142,7 @@ impl<'tcx> InferCtxt<'tcx> { .no_bound_vars() .expect("const parameter types cannot be generic"); debug_assert_eq!(self.tcx.types.bool, ty); - ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid), ty).into() + ty::Const::new_infer(self.tcx, ty::InferConst::EffectVar(effect_vid)).into() } /// Given a set of generics defined on a type or impl, returns the generic parameters mapping each @@ -1469,10 +1454,10 @@ impl<'tcx> InferCtxt<'tcx> { .or_insert_with(|| self.infcx.next_ty_var(self.span).into()) .expect_ty() } - fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> { + fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> { self.map .entry(bv) - .or_insert_with(|| self.infcx.next_const_var(ty, self.span).into()) + .or_insert_with(|| self.infcx.next_const_var(self.span).into()) .expect_const() } } @@ -1526,11 +1511,11 @@ impl<'tcx> InferCtxt<'tcx> { &self, param_env: ty::ParamEnv<'tcx>, unevaluated: ty::UnevaluatedConst<'tcx>, - ty: Ty<'tcx>, span: Span, ) -> Result, ErrorHandled> { match self.const_eval_resolve(param_env, unevaluated, span) { - Ok(Some(val)) => Ok(ty::Const::new_value(self.tcx, val, ty)), + // THISPR + Ok(Some(val)) => Ok(ty::Const::new_value(self.tcx, val, todo!())), Ok(None) => { let tcx = self.tcx; let def_id = unevaluated.def; @@ -1964,11 +1949,6 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { if let ty::ConstKind::Infer(_) = c.kind() { - let ty = c.ty(); - // If the type references param or infer then ICE ICE ICE - if ty.has_non_region_param() || ty.has_non_region_infer() { - bug!("const `{c}`'s type should not reference params or types"); - } ty::Const::new_placeholder( self.tcx, ty::PlaceholderConst { @@ -1979,7 +1959,6 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( idx }), }, - ty, ) } else { c.super_fold_with(self) diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index aaea3b4820b3..225c126fcf81 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -653,7 +653,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { { variable_table.union(vid, new_var_id); } - Ok(ty::Const::new_var(self.tcx(), new_var_id, c.ty())) + Ok(ty::Const::new_var(self.tcx(), new_var_id)) } } } @@ -671,11 +671,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> { args, args, )?; - Ok(ty::Const::new_unevaluated( - self.tcx(), - ty::UnevaluatedConst { def, args }, - c.ty(), - )) + Ok(ty::Const::new_unevaluated(self.tcx(), ty::UnevaluatedConst { def, args })) } ty::ConstKind::Placeholder(placeholder) => { if self.for_universe.can_name(placeholder.universe) { diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 70ed7cf9af1a..d3001eb5838b 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -43,11 +43,10 @@ impl<'tcx> InferCtxt<'tcx> { ty::PlaceholderType { universe: next_universe, bound: bound_ty }, ) }, - consts: &mut |bound_var: ty::BoundVar, ty| { + consts: &mut |bound_var: ty::BoundVar| { ty::Const::new_placeholder( self.tcx, ty::PlaceholderConst { universe: next_universe, bound: bound_var }, - ty, ) }, }; diff --git a/compiler/rustc_infer/src/infer/snapshot/fudge.rs b/compiler/rustc_infer/src/infer/snapshot/fudge.rs index 4408251c99dc..a086c82c92e8 100644 --- a/compiler/rustc_infer/src/infer/snapshot/fudge.rs +++ b/compiler/rustc_infer/src/infer/snapshot/fudge.rs @@ -244,7 +244,7 @@ impl<'a, 'tcx> TypeFolder> for InferenceFudger<'a, 'tcx> { // Recreate it with a fresh variable here. let idx = vid.index() - self.const_vars.0.start.index(); let origin = self.const_vars.1[idx]; - self.infcx.next_const_var_with_origin(ct.ty(), origin) + self.infcx.next_const_var_with_origin(origin) } else { ct } diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index e107c2c12bd6..5c069ff820d3 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -237,7 +237,8 @@ impl<'tcx> Const<'tcx> { #[inline(always)] pub fn ty(&self) -> Ty<'tcx> { match self { - Const::Ty(c) => c.ty(), + // THISPR + Const::Ty(c) => todo!(), Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty, } } @@ -260,7 +261,9 @@ impl<'tcx> Const<'tcx> { pub fn try_to_scalar(self) -> Option { match self { Const::Ty(c) => match c.kind() { - ty::ConstKind::Value(valtree) if c.ty().is_primitive() => { + // THISPR + // if c.ty().is_primitive() + ty::ConstKind::Value(valtree) if todo!() => { // A valtree of a type where leaves directly represent the scalar const value. // Just checking whether it is a leaf is insufficient as e.g. references are leafs // but the leaf value is the value they point to, not the reference itself! @@ -279,9 +282,9 @@ impl<'tcx> Const<'tcx> { match self { Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x), Const::Ty(c) => match c.kind() { - ty::ConstKind::Value(valtree) if c.ty().is_primitive() => { - Some(valtree.unwrap_leaf()) - } + // THISPR + // if c.ty().is_primitive() + ty::ConstKind::Value(valtree) if todo!() => Some(valtree.unwrap_leaf()), _ => None, }, _ => None, @@ -326,7 +329,7 @@ impl<'tcx> Const<'tcx> { match self.eval(tcx, param_env, DUMMY_SP) { Ok(val) => Self::Val(val, self.ty()), Err(ErrorHandled::Reported(guar, _span)) => { - Self::Ty(ty::Const::new_error(tcx, guar.into(), self.ty())) + Self::Ty(ty::Const::new_error(tcx, guar.into())) } Err(ErrorHandled::TooGeneric(_span)) => self, } @@ -339,7 +342,9 @@ impl<'tcx> Const<'tcx> { param_env: ty::ParamEnv<'tcx>, ) -> Option { match self { - Const::Ty(c) if c.ty().is_primitive() => { + // THISPR + // c.ty().is_primitive() + Const::Ty(c) if todo!() => { // Avoid the `valtree_to_const_val` query. Can only be done on primitive types that // are valtree leaves, and *not* on references. (References should return the // pointer here, which valtrees don't represent.) @@ -443,8 +448,9 @@ impl<'tcx> Const<'tcx> { match c.kind() { ty::ConstKind::Value(valtree) => { // Make sure that if `c` is normalized, then the return value is normalized. - let const_val = tcx.valtree_to_const_val((c.ty(), valtree)); - Self::Val(const_val, c.ty()) + // THISPR + let const_val = tcx.valtree_to_const_val((todo!(), valtree)); + Self::Val(const_val, todo!()) } _ => Self::Ty(c), } @@ -463,7 +469,9 @@ impl<'tcx> Const<'tcx> { // A valtree may be a reference. Valtree references correspond to a // different allocation each time they are evaluated. Valtrees for primitive // types are fine though. - ty::ConstKind::Value(_) => c.ty().is_primitive(), + // THISPR + // c.ty().is_primitive() + ty::ConstKind::Value(_) => todo!(), ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false, // This can happen if evaluation of a constant failed. The result does not matter // much since compilation is doomed. diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 7fb5e9aadae7..254e1b544819 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -53,7 +53,7 @@ impl<'tcx> TyCtxt<'tcx> { fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> { let ct = match c.kind() { ty::ConstKind::Unevaluated(uv) => match self.tcx.thir_abstract_const(uv.def) { - Err(e) => ty::Const::new_error(self.tcx, e, c.ty()), + Err(e) => ty::Const::new_error(self.tcx, e), Ok(Some(bac)) => { let args = self.tcx.erase_regions(uv.args); let bac = bac.instantiate(self.tcx, args); diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 07652b479292..33f564e9b59c 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -350,8 +350,8 @@ impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> impl<'tcx, D: TyDecoder>> Decodable for ty::Const<'tcx> { fn decode(decoder: &mut D) -> Self { - let consts: ty::ConstData<'tcx> = Decodable::decode(decoder); - decoder.interner().mk_ct_from_kind(consts.kind, consts.ty) + let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder); + decoder.interner().mk_ct_from_kind(kind) } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 384a4e7009d8..7e84b763fa8b 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -6,7 +6,7 @@ use rustc_error_messages::MultiSpan; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; -use rustc_macros::{HashStable, TyDecodable, TyEncodable}; +use rustc_macros::HashStable; use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; use tracing::{debug, instrument}; @@ -26,10 +26,9 @@ pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst>; #[cfg(target_pointer_width = "64")] rustc_data_structures::static_assert_size!(ConstKind<'_>, 24); -/// Use this rather than `ConstData`, whenever possible. #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] -pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo>>); +pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo>>); impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> { type Kind = ConstKind<'tcx>; @@ -49,26 +48,11 @@ impl<'tcx> rustc_type_ir::visit::Flags for Const<'tcx> { } } -/// Typed constant value. -#[derive(Copy, Clone, PartialEq, Eq, Hash)] -#[derive(HashStable, TyEncodable, TyDecodable)] -pub struct ConstData<'tcx> { - pub ty: Ty<'tcx>, - pub kind: ConstKind<'tcx>, -} - -#[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(ConstData<'_>, 32); - impl<'tcx> Const<'tcx> { - #[inline] - pub fn ty(self) -> Ty<'tcx> { - self.0.ty - } - #[inline] pub fn kind(self) -> ConstKind<'tcx> { - self.0.kind + let a: &ConstKind<'tcx> = self.0.0; + *a } // FIXME(compiler-errors): Think about removing this. @@ -84,28 +68,28 @@ impl<'tcx> Const<'tcx> { } #[inline] - pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - tcx.mk_ct_from_kind(kind, ty) + pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>) -> Const<'tcx> { + tcx.mk_ct_from_kind(kind) } #[inline] - pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst, ty: Ty<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Param(param), ty) + pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Param(param)) } #[inline] - 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) + pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer))) } #[inline] - pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32, ty: Ty<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh)), ty) + pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh))) } #[inline] - pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Infer(infer), ty) + pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Infer(infer)) } #[inline] @@ -113,50 +97,40 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar, - ty: Ty<'tcx>, ) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Bound(debruijn, var), ty) + Const::new(tcx, ty::ConstKind::Bound(debruijn, var)) } #[inline] - pub fn new_placeholder( - tcx: TyCtxt<'tcx>, - placeholder: ty::PlaceholderConst, - ty: Ty<'tcx>, - ) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Placeholder(placeholder), ty) + pub fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Placeholder(placeholder)) } #[inline] - pub fn new_unevaluated( - tcx: TyCtxt<'tcx>, - uv: ty::UnevaluatedConst<'tcx>, - ty: Ty<'tcx>, - ) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Unevaluated(uv), ty) + pub fn new_unevaluated(tcx: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Unevaluated(uv)) } #[inline] pub fn new_value(tcx: TyCtxt<'tcx>, val: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Value(val), ty) + Const::new(tcx, ty::ConstKind::Value(ty, val)) } #[inline] - pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Expr(expr), ty) + pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Expr(expr)) } #[inline] - pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed, ty: Ty<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Error(e), ty) + pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Error(e)) } /// Like [Ty::new_error] but for constants. #[track_caller] - pub fn new_misc_error(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Const<'tcx> { Const::new_error_with_message( tcx, - ty, DUMMY_SP, "ty::ConstKind::Error constructed but no error reported", ) @@ -166,48 +140,33 @@ impl<'tcx> Const<'tcx> { #[track_caller] pub fn new_error_with_message>( tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, span: S, msg: &'static str, ) -> Const<'tcx> { let reported = tcx.dcx().span_delayed_bug(span, msg); - Const::new_error(tcx, reported, ty) + Const::new_error(tcx, reported) } } impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { - fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst, ty: Ty<'tcx>) -> Self { - Const::new_infer(tcx, infer, ty) + fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self { + Const::new_infer(tcx, infer) } - fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid, ty: Ty<'tcx>) -> Self { - Const::new_var(tcx, vid, ty) + fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid) -> Self { + Const::new_var(tcx, vid) } - fn new_bound( - interner: TyCtxt<'tcx>, - debruijn: ty::DebruijnIndex, - var: ty::BoundVar, - ty: Ty<'tcx>, - ) -> Self { - Const::new_bound(interner, debruijn, var, ty) + fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { + Const::new_bound(interner, debruijn, var) } - fn new_anon_bound( - tcx: TyCtxt<'tcx>, - debruijn: ty::DebruijnIndex, - var: ty::BoundVar, - ty: Ty<'tcx>, - ) -> Self { - Const::new_bound(tcx, debruijn, var, ty) + fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { + Const::new_bound(tcx, debruijn, var) } - fn new_unevaluated( - interner: TyCtxt<'tcx>, - uv: ty::UnevaluatedConst<'tcx>, - ty: Ty<'tcx>, - ) -> Self { - Const::new_unevaluated(interner, uv, ty) + fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self { + Const::new_unevaluated(interner, uv) } fn ty(self) -> Ty<'tcx> { @@ -241,7 +200,6 @@ impl<'tcx> Const<'tcx> { def: def.to_def_id(), args: GenericArgs::identity_for_item(tcx, def.to_def_id()), }, - ty, ), } } @@ -293,9 +251,6 @@ impl<'tcx> Const<'tcx> { _, &hir::Path { res: Res::Def(DefKind::ConstParam, def_id), .. }, )) => { - // Use the type from the param's definition, since we can resolve it, - // not the expected parameter type from WithOptConstParam. - let param_ty = tcx.type_of(def_id).instantiate_identity(); match tcx.named_bound_var(expr.hir_id) { Some(rbv::ResolvedArg::EarlyBound(_)) => { // Find the name and index of the const parameter by indexing the generics of @@ -304,19 +259,12 @@ impl<'tcx> Const<'tcx> { let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; let name = tcx.item_name(def_id); - Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name), param_ty)) + Some(ty::Const::new_param(tcx, ty::ParamConst::new(index, name))) } Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { - Some(ty::Const::new_bound( - tcx, - debruijn, - ty::BoundVar::from_u32(index), - param_ty, - )) - } - Some(rbv::ResolvedArg::Error(guar)) => { - Some(ty::Const::new_error(tcx, guar, param_ty)) + Some(ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index))) } + Some(rbv::ResolvedArg::Error(guar)) => Some(ty::Const::new_error(tcx, guar)), arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", expr.hir_id), } } @@ -397,8 +345,8 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self { match self.eval(tcx, param_env, DUMMY_SP) { - Ok(val) => Self::new_value(tcx, val, self.ty()), - Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into(), self.ty()), + Ok(val) => Self::new_value(tcx, val, self.ty_for_ctfe(tcx).unwrap()), + Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()), Err(ErrorHandled::TooGeneric(_span)) => self, } } @@ -430,8 +378,12 @@ impl<'tcx> Const<'tcx> { /// contains const generic parameters or pointers). pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { let int = self.try_eval_scalar_int(tcx, param_env)?; - let size = - tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(self.ty())).ok()?.size; + let size = tcx + .layout_of( + param_env.with_reveal_all_normalized(tcx).and(self.ty_for_ctfe(tcx).unwrap()), + ) + .ok()? + .size; // if `ty` does not depend on generic parameters, use an empty param_env int.try_to_bits(size).ok() } @@ -440,7 +392,7 @@ impl<'tcx> Const<'tcx> { /// Panics if the value cannot be evaluated or doesn't contain a valid integer of the given type. pub fn eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u128 { self.try_eval_bits(tcx, param_env) - .unwrap_or_else(|| bug!("expected bits of {:#?}, got {:#?}", self.ty(), self)) + .unwrap_or_else(|| bug!("failed to evalate {:#?} to bits", self)) } #[inline] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 47f66c644062..7e8b3fea1eae 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -28,10 +28,10 @@ use crate::traits::solve::{ }; use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; use crate::ty::{ - self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData, - GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern, - PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, - Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility, + self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericParamDefKind, + ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern, PatternKind, + PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity, Region, + RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility, }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use rustc_ast::{self as ast, attr}; @@ -268,7 +268,7 @@ pub struct CtxtInterners<'tcx> { clauses: InternedSet<'tcx, ListWithCachedTypeInfo>>, projs: InternedSet<'tcx, List>, place_elems: InternedSet<'tcx, List>>, - const_: InternedSet<'tcx, WithCachedTypeInfo>>, + const_: InternedSet<'tcx, WithCachedTypeInfo>>, pat: InternedSet<'tcx, PatternKind<'tcx>>, const_allocation: InternedSet<'tcx, Allocation>, bound_variable_kinds: InternedSet<'tcx, List>, @@ -338,18 +338,18 @@ impl<'tcx> CtxtInterners<'tcx> { #[inline(never)] fn intern_const( &self, - data: ty::ConstData<'tcx>, + kind: ty::ConstKind<'tcx>, sess: &Session, untracked: &Untracked, ) -> Const<'tcx> { Const(Interned::new_unchecked( self.const_ - .intern(data, |data: ConstData<'_>| { - let flags = super::flags::FlagComputation::for_const(&data.kind, data.ty); - let stable_hash = self.stable_hash(&flags, sess, untracked, &data); + .intern(kind, |kind: ty::ConstKind<'_>| { + let flags = super::flags::FlagComputation::for_const_kind(&kind); + let stable_hash = self.stable_hash(&flags, sess, untracked, &kind); InternedInSet(self.arena.alloc(WithCachedTypeInfo { - internee: data, + internee: kind, stable_hash, flags: flags.flags, outer_exclusive_binder: flags.outer_exclusive_binder, @@ -601,18 +601,9 @@ impl<'tcx> CommonConsts<'tcx> { }; CommonConsts { - unit: mk_const(ty::ConstData { - kind: ty::ConstKind::Value(ty::ValTree::zst()), - ty: types.unit, - }), - true_: mk_const(ty::ConstData { - kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE)), - ty: types.bool, - }), - false_: mk_const(ty::ConstData { - kind: ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE)), - ty: types.bool, - }), + unit: mk_const(ty::ConstKind::Value(ty::ValTree::zst())), + true_: mk_const(ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE))), + false_: mk_const(ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE))), } } } @@ -2225,9 +2216,9 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + pub fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>) -> Const<'tcx> { self.interners.intern_const( - ty::ConstData { kind, ty }, + kind, self.sess, // This is only used to create a stable hashing context. &self.untracked, @@ -2252,14 +2243,10 @@ impl<'tcx> TyCtxt<'tcx> { ty::Region::new_early_param(self, param.to_early_bound_region_data()).into() } GenericParamDefKind::Type { .. } => Ty::new_param(self, param.index, param.name).into(), - GenericParamDefKind::Const { .. } => ty::Const::new_param( - self, - ParamConst { index: param.index, name: param.name }, - self.type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), - ) - .into(), + GenericParamDefKind::Const { .. } => { + ty::Const::new_param(self, ParamConst { index: param.index, name: param.name }) + .into() + } } } diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 93a51d3a3340..5f653aba4852 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -28,10 +28,9 @@ impl FlagComputation { result } - pub fn for_const(c: &ty::ConstKind<'_>, t: Ty<'_>) -> FlagComputation { + pub fn for_const_kind(kind: &ty::ConstKind<'_>) -> FlagComputation { let mut result = FlagComputation::new(); - result.add_const_kind(c); - result.add_ty(t); + result.add_const_kind(kind); result } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index b5b36cbd1ba1..9b5b1430c27f 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -134,13 +134,13 @@ impl<'a, 'tcx> TypeFolder> for RegionFolder<'a, 'tcx> { pub trait BoundVarReplacerDelegate<'tcx> { fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>; fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx>; - fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx>; + fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx>; } pub struct FnMutDelegate<'a, 'tcx> { pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), pub types: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a), - pub consts: &'a mut (dyn FnMut(ty::BoundVar, Ty<'tcx>) -> ty::Const<'tcx> + 'a), + pub consts: &'a mut (dyn FnMut(ty::BoundVar) -> ty::Const<'tcx> + 'a), } impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> { @@ -150,8 +150,8 @@ impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> { fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { (self.types)(bt) } - fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> { - (self.consts)(bv, ty) + fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> { + (self.consts)(bv) } } @@ -224,7 +224,7 @@ where fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => { - let ct = self.delegate.replace_const(bound_const, ct.ty()); + let ct = self.delegate.replace_const(bound_const); debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST)); ty::fold::shift_vars(self.tcx, ct, self.current_index.as_u32()) } @@ -282,7 +282,7 @@ impl<'tcx> TyCtxt<'tcx> { let delegate = FnMutDelegate { regions: &mut replace_regions, types: &mut |b| bug!("unexpected bound ty in binder: {b:?}"), - consts: &mut |b, ty| bug!("unexpected bound ct in binder: {b:?} {ty}"), + consts: &mut |b| bug!("unexpected bound ct in binder: {b:?}"), }; let mut replacer = BoundVarReplacer::new(self, delegate); value.fold_with(&mut replacer) @@ -353,9 +353,7 @@ impl<'tcx> TyCtxt<'tcx> { ty::BoundTy { var: shift_bv(t.var), kind: t.kind }, ) }, - consts: &mut |c, ty: Ty<'tcx>| { - ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c), ty) - }, + consts: &mut |c| ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c)), }, ) } @@ -398,12 +396,12 @@ impl<'tcx> TyCtxt<'tcx> { .expect_ty(); Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind }) } - fn replace_const(&mut self, bv: ty::BoundVar, ty: Ty<'tcx>) -> ty::Const<'tcx> { + fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> { let entry = self.map.entry(bv); let index = entry.index(); let var = ty::BoundVar::from_usize(index); let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const(); - ty::Const::new_bound(self.tcx, ty::INNERMOST, var, ty) + ty::Const::new_bound(self.tcx, ty::INNERMOST, var) } } diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index c3ab755175d8..7fff3d013249 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -228,7 +228,7 @@ impl<'tcx> GenericArg<'tcx> { ptr.cast::>>().as_ref(), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( - ptr.cast::>>().as_ref(), + ptr.cast::>>().as_ref(), ))), _ => intrinsics::unreachable(), } @@ -454,11 +454,11 @@ impl<'tcx> GenericArgs<'tcx> { def_id: DefId, original_args: &[GenericArg<'tcx>], ) -> GenericArgsRef<'tcx> { - ty::GenericArgs::for_item(tcx, def_id, |def, args| { + ty::GenericArgs::for_item(tcx, def_id, |def, _| { if let Some(arg) = original_args.get(def.index as usize) { *arg } else { - def.to_error(tcx, args) + def.to_error(tcx) } }) } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 89ba8cd2ad4c..185dbe447358 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -100,19 +100,11 @@ impl GenericParamDef { } } - pub fn to_error<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - preceding_args: &[ty::GenericArg<'tcx>], - ) -> ty::GenericArg<'tcx> { + pub fn to_error<'tcx>(&self, tcx: TyCtxt<'tcx>) -> ty::GenericArg<'tcx> { match &self.kind { ty::GenericParamDefKind::Lifetime => ty::Region::new_error_misc(tcx).into(), ty::GenericParamDefKind::Type { .. } => Ty::new_misc_error(tcx).into(), - ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error( - tcx, - tcx.type_of(self.def_id).instantiate(tcx, preceding_args), - ) - .into(), + ty::GenericParamDefKind::Const { .. } => ty::Const::new_misc_error(tcx).into(), } } } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index a2df90b2c0f8..142872009bf2 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -385,9 +385,7 @@ impl<'tcx> SizeSkeleton<'tcx> { ), } } - ty::Array(inner, len) - if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts => - { + ty::Array(inner, len) if tcx.features().transmute_generic_consts => { let len_eval = len.try_eval_target_usize(tcx, param_env); if len_eval == Some(0) { return Ok(SizeSkeleton::Known(Size::from_bytes(0))); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c6028ef74a9f..fc42a11cff01 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -87,7 +87,7 @@ pub use self::closure::{ CAPTURE_STRUCT_LOCAL, }; pub use self::consts::{ - Const, ConstData, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, + Const, ConstInt, ConstKind, Expr, ExprKind, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ tls, CtxtInterners, CurrentGcx, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, @@ -617,7 +617,7 @@ impl<'tcx> Term<'tcx> { ptr.cast::>>().as_ref(), ))), CONST_TAG => TermKind::Const(ty::Const(Interned::new_unchecked( - ptr.cast::>>().as_ref(), + ptr.cast::>>().as_ref(), ))), _ => core::intrinsics::unreachable(), } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index bbcbcdce1b2e..52902aadd7c7 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -216,7 +216,7 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { }) .emit_unless(self.ignore_errors); - ty::Const::new_error(self.tcx, guar, ct.ty()) + ty::Const::new_error(self.tcx, guar) } } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 1b37078e703d..8fec654acc58 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1467,7 +1467,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { write!(this, "_")?; Ok(()) }, - |this| this.print_type(ct.ty()), + |this| this.print_type(todo!()), ": ", )?; } else { @@ -1512,7 +1512,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { }, ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), ty::ConstKind::Value(value) => { - return self.pretty_print_const_valtree(value, ct.ty(), print_ty); + return self.pretty_print_const_valtree(value, todo!(), print_ty); } ty::ConstKind::Bound(debruijn, bound_var) => { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index a621d255a03e..b0581f89380c 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -652,18 +652,17 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( // and is the better alternative to waiting until `generic_const_exprs` can // be stabilized. (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { - assert_eq!(a.ty(), b.ty()); + let a_ty = tcx.type_of(au.def).instantiate(tcx, au.args); + let b_ty = tcx.type_of(bu.def).instantiate(tcx, bu.args); + assert_eq!(a_ty, b_ty); + let args = relation.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), au.args, bu.args, )?; - return Ok(ty::Const::new_unevaluated( - tcx, - ty::UnevaluatedConst { def: au.def, args }, - a.ty(), - )); + return Ok(ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst { def: au.def, args })); } (ty::ConstKind::Expr(ae), ty::ConstKind::Expr(be)) => { match (ae.kind, be.kind) { @@ -676,7 +675,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( } let args = relation.relate(ae.args(), be.args())?; - return Ok(ty::Const::new_expr(tcx, ty::Expr::new(ae.kind, args), a.ty())); + return Ok(ty::Const::new_expr(tcx, ty::Expr::new(ae.kind, args))); } _ => false, }; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 7a291b4dbff6..ee235d3781b8 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -210,17 +210,14 @@ impl<'tcx> DebugWithInfcx> for ty::Const<'tcx> { bug!("we checked that this is a valtree") }; let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); - cx.pretty_print_const_valtree(valtree, lifted.ty(), /*print_ty*/ true)?; + // THISPR + todo!(); + // cx.pretty_print_const_valtree(valtree, lifted.ty(), /*print_ty*/ true)?; f.write_str(&cx.into_buffer()) }); } // Fall back to something verbose. - write!( - f, - "{kind:?}: {ty:?}", - ty = &this.map(|data| data.ty()), - kind = &this.map(|data| data.kind()) - ) + write!(f, "{kind:?}", kind = &this.map(|data| data.kind())) } } @@ -647,7 +644,6 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { self, folder: &mut F, ) -> Result { - let ty = self.ty().try_fold_with(folder)?; let kind = match self.kind() { ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?), ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?), @@ -660,17 +656,12 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), }; - if ty != self.ty() || kind != self.kind() { - Ok(folder.interner().mk_ct_from_kind(kind, ty)) - } else { - Ok(self) - } + if kind != self.kind() { Ok(folder.interner().mk_ct_from_kind(kind)) } else { Ok(self) } } } impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { - try_visit!(self.ty().visit_with(visitor)); match self.kind() { ConstKind::Param(p) => p.visit_with(visitor), ConstKind::Infer(i) => i.visit_with(visitor), diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 58f69d772ecb..9b313fc7bf0a 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -212,21 +212,18 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) } }, GenericArgKind::Lifetime(_) => {} - GenericArgKind::Const(parent_ct) => { - stack.push(parent_ct.ty().into()); - match parent_ct.kind() { - ty::ConstKind::Infer(_) - | ty::ConstKind::Param(_) - | ty::ConstKind::Placeholder(_) - | ty::ConstKind::Bound(..) - | ty::ConstKind::Value(_) - | ty::ConstKind::Error(_) => {} + GenericArgKind::Const(parent_ct) => match parent_ct.kind() { + ty::ConstKind::Infer(_) + | ty::ConstKind::Param(_) + | ty::ConstKind::Placeholder(_) + | ty::ConstKind::Bound(..) + | ty::ConstKind::Value(_) + | ty::ConstKind::Error(_) => {} - ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()), - ty::ConstKind::Unevaluated(ct) => { - stack.extend(ct.args.iter().rev()); - } + ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()), + ty::ConstKind::Unevaluated(ct) => { + stack.extend(ct.args.iter().rev()); } - } + }, } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index f7229326c541..5eed6995fff8 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -50,9 +50,7 @@ pub(crate) fn as_constant_inner<'tcx>( let const_ = match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { Ok(c) => c, - Err(LitToConstError::Reported(guar)) => { - Const::Ty(ty::Const::new_error(tcx, guar, ty)) - } + Err(LitToConstError::Reported(guar)) => Const::Ty(ty::Const::new_error(tcx, guar)), Err(LitToConstError::TypeError) => { bug!("encountered type error in `lit_to_mir_constant`") } @@ -83,7 +81,7 @@ pub(crate) fn as_constant_inner<'tcx>( ConstOperand { user_ty, span, const_ } } ExprKind::ConstParam { param, def_id: _ } => { - let const_param = ty::Const::new_param(tcx, param, expr.ty); + let const_param = ty::Const::new_param(tcx, param); let const_ = Const::Ty(const_param); ConstOperand { user_ty: None, span, const_ } diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 127ebde5fec3..8b96519c3211 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -386,23 +386,15 @@ impl, I: Interner> TypeFolder } fn fold_const(&mut self, c: I::Const) -> I::Const { - // We could canonicalize all consts with static types, but the only ones we - // *really* need to worry about are the ones that we end up putting into `CanonicalVarKind` - // since canonical vars can't reference other canonical vars. - let ty = c - .ty() - .fold_with(&mut RegionsToStatic { interner: self.interner(), binder: ty::INNERMOST }); let kind = match c.kind() { ty::ConstKind::Infer(i) => match i { ty::InferConst::Var(vid) => { - // We compare `kind`s here because we've folded the `ty` with `RegionsToStatic` - // so we'll get a mismatch in types if it actually changed any regions. assert_eq!( - self.infcx.opportunistic_resolve_ct_var(vid, ty).kind(), - c.kind(), - "region vid should have been resolved fully before canonicalization" + self.infcx.opportunistic_resolve_ct_var(vid), + c, + "const vid should have been resolved fully before canonicalization" ); - CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), ty) + CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap()) } ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect, ty::InferConst::Fresh(_) => todo!(), @@ -410,16 +402,14 @@ impl, I: Interner> TypeFolder ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( PlaceholderLike::new(placeholder.universe(), self.variables.len().into()), - ty, ), CanonicalizeMode::Response { .. } => { - CanonicalVarKind::PlaceholderConst(placeholder, ty) + CanonicalVarKind::PlaceholderConst(placeholder) } }, ty::ConstKind::Param(_) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()), - ty, ), CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"), }, @@ -440,34 +430,6 @@ impl, I: Interner> TypeFolder }), ); - Const::new_anon_bound(self.interner(), self.binder_index, var, ty) - } -} - -struct RegionsToStatic { - interner: I, - binder: ty::DebruijnIndex, -} - -impl TypeFolder for RegionsToStatic { - fn interner(&self) -> I { - self.interner - } - - fn fold_binder(&mut self, t: ty::Binder) -> ty::Binder - where - T: TypeFoldable, - { - self.binder.shift_in(1); - let t = t.super_fold_with(self); - self.binder.shift_out(1); - t - } - - fn fold_region(&mut self, r: I::Region) -> I::Region { - match r.kind() { - ty::ReBound(db, _) if self.binder > db => r, - _ => Region::new_static(self.interner()), - } + Const::new_anon_bound(self.interner(), self.binder_index, var) } } diff --git a/compiler/rustc_next_trait_solver/src/resolve.rs b/compiler/rustc_next_trait_solver/src/resolve.rs index 1333b4aa7d83..92e05cc4901a 100644 --- a/compiler/rustc_next_trait_solver/src/resolve.rs +++ b/compiler/rustc_next_trait_solver/src/resolve.rs @@ -58,8 +58,7 @@ impl, I: Interner> TypeFolder for EagerRes fn fold_const(&mut self, c: I::Const) -> I::Const { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { - let ty = c.ty().fold_with(self); - let resolved = self.infcx.opportunistic_resolve_ct_var(vid, ty); + let resolved = self.infcx.opportunistic_resolve_ct_var(vid); if c != resolved && resolved.has_infer() { resolved.fold_with(self) } else { @@ -67,9 +66,7 @@ impl, I: Interner> TypeFolder for EagerRes } } ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { - let bool = Ty::new_bool(self.infcx.interner()); - debug_assert_eq!(c.ty(), bool); - self.infcx.opportunistic_resolve_effect_var(vid, bool) + self.infcx.opportunistic_resolve_effect_var(vid) } _ => { if c.has_infer() { diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index d67132d2dd4f..22224e1cc959 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -111,7 +111,8 @@ fn encode_const<'tcx>( // LE as literal argument // Element type - s.push_str(&encode_ty(tcx, c.ty(), dict, options)); + // THISPR + s.push_str(&encode_ty(tcx, todo!(), dict, options)); } // Literal arguments @@ -119,12 +120,14 @@ fn encode_const<'tcx>( // L[n]E as literal argument // Element type - s.push_str(&encode_ty(tcx, c.ty(), dict, options)); + // THISPR + let ct_ty: Ty<'tcx> = todo!(); + s.push_str(&encode_ty(tcx, ct_ty, dict, options)); // The only allowed types of const values are bool, u8, u16, u32, // u64, u128, usize i8, i16, i32, i64, i128, isize, and char. The // bool value false is encoded as 0 and true as 1. - match c.ty().kind() { + match ct_ty.kind() { ty::Int(ity) => { let bits = c.eval_bits(tcx, ty::ParamEnv::reveal_all()); let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; @@ -142,7 +145,7 @@ fn encode_const<'tcx>( let _ = write!(s, "{val}"); } _ => { - bug!("encode_const: unexpected type `{:?}`", c.ty()); + bug!("encode_const: unexpected type `{:?}`", ct_ty); } } } diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 1f3356f579fe..4d60dd73c3cc 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -463,7 +463,10 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { ty::ValTree::Branch(tables.tcx.lift(branch).unwrap()) } }; - let ty = tables.tcx.lift(self.ty()).unwrap(); + + // THISPR + let ty = todo!(); + // let ty = tables.tcx.lift(c.ty()).unwrap(); let const_val = tables.tcx.valtree_to_const_val((ty, val)); if matches!(const_val, mir::ConstValue::ZeroSized) { stable_mir::ty::TyConstKind::ZSTValue(ty.stable(tables)) diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 0ed1f67bb821..1fea9b561a26 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -269,16 +269,21 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { } fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> { + // THISPR + let ct_ty: Ty<'tcx> = todo!(); + // only print integers - match (ct.kind(), ct.ty().kind()) { + match (ct.kind(), ct_ty.kind()) { (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => { // The `pretty_print_const` formatting depends on -Zverbose-internals // flag, so we cannot reuse it here. - let signed = matches!(ct.ty().kind(), ty::Int(_)); + let signed = matches!(ct_ty.kind(), ty::Int(_)); write!( self, "{:#?}", - ty::ConstInt::new(scalar, signed, ct.ty().is_ptr_sized_integral()) + // THISPR + // ct.ty().is_ptr_sized_integral() + ty::ConstInt::new(scalar, signed, todo!()) )?; } _ => self.write_str("_")?, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index 57b1542ff5a4..bb45fd07bee4 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -567,7 +567,9 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { } let start = self.out.len(); - let ty = ct.ty(); + // THISPR + let ty: Ty<'tcx> = todo!(); + // let ty = ct.ty(); match ty.kind() { ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => { @@ -626,12 +628,10 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { } } _ => { - let pointee_ty = ct - .ty() - .builtin_deref(true) - .expect("tried to dereference on non-ptr type"); + let pointee_ty = + ty.builtin_deref(true).expect("tried to dereference on non-ptr type"); // FIXME(const_generics): add an assert that we only do this for valtrees. - let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind(), pointee_ty); + let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind()); dereferenced_const.print(self)?; } } @@ -649,7 +649,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { Ok(()) }; - match *ct.ty().kind() { + match *ty.kind() { ty::Array(..) | ty::Slice(_) => { self.push("A"); print_field_list(self)?; @@ -698,7 +698,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { } } _ => { - bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct.ty(), ct); + bug!("symbol_names: unsupported constant of type `{}` ({:?})", ty, ct); } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index 690c1797f239..0e0b9e983391 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -444,7 +444,7 @@ pub(in crate::solve) fn instantiate_canonical_state<'tcx, T: TypeFoldable infcx.next_ty_var(span).into(), - ty::GenericArgKind::Const(ct) => infcx.next_const_var(ct.ty(), span).into(), + ty::GenericArgKind::Const(_) => infcx.next_const_var(span).into(), }; orig_values.push(unconstrained); diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index f18f1f4f8f0d..eecceaec6a78 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -609,8 +609,8 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { ty } - pub(super) fn next_const_infer(&mut self, ty: Ty<'tcx>) -> ty::Const<'tcx> { - let ct = self.infcx.next_const_var(ty, DUMMY_SP); + pub(super) fn next_const_infer(&mut self) -> ty::Const<'tcx> { + let ct = self.infcx.next_const_var(DUMMY_SP); self.inspect.add_var_value(ct); ct } @@ -620,7 +620,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { pub(super) fn next_term_infer_of_kind(&mut self, kind: ty::Term<'tcx>) -> ty::Term<'tcx> { match kind.unpack() { ty::TermKind::Ty(_) => self.next_ty_infer().into(), - ty::TermKind::Const(ct) => self.next_const_infer(ct.ty()).into(), + ty::TermKind::Const(_) => self.next_const_infer().into(), } } @@ -1037,14 +1037,14 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { &self, param_env: ty::ParamEnv<'tcx>, unevaluated: ty::UnevaluatedConst<'tcx>, - ty: Ty<'tcx>, ) -> Option> { use rustc_middle::mir::interpret::ErrorHandled; match self.infcx.const_eval_resolve(param_env, unevaluated, DUMMY_SP) { - Ok(Some(val)) => Some(ty::Const::new_value(self.interner(), val, ty)), + // THISPR + Ok(Some(val)) => Some(ty::Const::new_value(self.interner(), val, todo!())), Ok(None) | Err(ErrorHandled::TooGeneric(_)) => None, Err(ErrorHandled::Reported(e, _)) => { - Some(ty::Const::new_error(self.interner(), e.into(), ty)) + Some(ty::Const::new_error(self.interner(), e.into())) } } } @@ -1124,7 +1124,7 @@ impl<'tcx> TypeFolder> for ReplaceAliasWithInfer<'_, '_, 'tcx> { fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { match ct.kind() { ty::ConstKind::Unevaluated(..) if !ct.has_escaping_bound_vars() => { - let infer_ct = self.ecx.next_const_infer(ct.ty()); + let infer_ct = self.ecx.next_const_infer(); let normalizes_to = ty::PredicateKind::AliasRelate( ct.into(), infer_ct.into(), diff --git a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs index 1f27978e5a62..19c95dad48cb 100644 --- a/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs +++ b/compiler/rustc_trait_selection/src/solve/inspect/analyse.rs @@ -208,7 +208,7 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> { Some(ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })) => { let unconstrained_term = match term.unpack() { ty::TermKind::Ty(_) => infcx.next_ty_var(span).into(), - ty::TermKind::Const(ct) => infcx.next_const_var(ct.ty(), span).into(), + ty::TermKind::Const(_) => infcx.next_const_var(span).into(), }; let goal = goal.with(infcx.tcx, ty::NormalizesTo { alias, term: unconstrained_term }); diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index 68a4831c3350..be5b36c5c8a0 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -169,7 +169,7 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { // FIXME(generic_const_exprs): Implement handling for generic // const expressions here. - if let Some(_normalized) = self.try_const_eval_resolve(param_env, uv, ct.ty()) { + if let Some(_normalized) = self.try_const_eval_resolve(param_env, uv) { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } else { self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) @@ -217,7 +217,8 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } _ => { - self.eq(goal.param_env, ct.ty(), ty)?; + // THISPR + self.eq(goal.param_env, todo!(), ty)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index c60d1aed415a..f42edebfcc42 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -109,7 +109,6 @@ where fn normalize_unevaluated_const( &mut self, - ty: Ty<'tcx>, uv: ty::UnevaluatedConst<'tcx>, ) -> Result, Vec> { let infcx = self.at.infcx; @@ -126,7 +125,7 @@ where self.depth += 1; - let new_infer_ct = infcx.next_const_var(ty, self.at.cause.span); + let new_infer_ct = infcx.next_const_var(self.at.cause.span); let obligation = Obligation::new( tcx, self.at.cause.clone(), @@ -143,7 +142,7 @@ where let ct = infcx.resolve_vars_if_possible(new_infer_ct); ct.try_fold_with(self)? } else { - ty::Const::new_unevaluated(tcx, uv, ty).try_super_fold_with(self)? + ty::Const::new_unevaluated(tcx, uv).try_super_fold_with(self)? }; self.depth -= 1; @@ -214,7 +213,7 @@ where if uv.has_escaping_bound_vars() { let (uv, mapped_regions, mapped_types, mapped_consts) = BoundVarReplacer::replace_bound_vars(infcx, &mut self.universes, uv); - let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv))?; + let result = ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv))?; Ok(PlaceholderReplacer::replace_placeholders( infcx, mapped_regions, @@ -224,7 +223,7 @@ where result, )) } else { - ensure_sufficient_stack(|| self.normalize_unevaluated_const(ct.ty(), uv)) + ensure_sufficient_stack(|| self.normalize_unevaluated_const(uv)) } } } diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs index 362c4072278d..a6e4b6ff4a81 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/anon_const.rs @@ -12,10 +12,6 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { if let Some(normalized_const) = self.try_const_eval_resolve( goal.param_env, ty::UnevaluatedConst::new(goal.predicate.alias.def_id, goal.predicate.alias.args), - self.interner() - .type_of(goal.predicate.alias.def_id) - .no_bound_vars() - .expect("const ty should not rely on other generics"), ) { self.instantiate_normalizes_to_term(goal, normalized_const.into()); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs index 8c63bd824bc0..787f08a084ee 100644 --- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs @@ -201,13 +201,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { let error_response = |ecx: &mut EvalCtxt<'_, InferCtxt<'tcx>>, reason| { let guar = tcx.dcx().span_delayed_bug(tcx.def_span(assoc_def.item.def_id), reason); let error_term = match assoc_def.item.kind { - ty::AssocKind::Const => ty::Const::new_error( - tcx, - guar, - tcx.type_of(goal.predicate.def_id()) - .instantiate(tcx, goal.predicate.alias.args), - ) - .into(), + ty::AssocKind::Const => ty::Const::new_error(tcx, guar).into(), ty::AssocKind::Type => Ty::new_error(tcx, guar).into(), // This makes no sense... ty::AssocKind::Fn => span_bug!( @@ -253,7 +247,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> { ty::EarlyBinder::bind( ty::Const::new_error_with_message( tcx, - tcx.type_of(assoc_def.item.def_id).instantiate_identity(), DUMMY_SP, "associated const projection is not supported yet", ) diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 6623a86e69ff..c3a25a50c7fb 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -765,7 +765,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { unevaluated, obligation.cause.span, ) { - Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, c.ty())), + // THISPR + Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, todo!())), Ok(None) => { let tcx = self.tcx; let reported = diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 7723f2229bf9..7120a061e5b3 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -529,7 +529,6 @@ fn plug_infer_with_placeholders<'tcx>( ty::Const::new_placeholder( self.infcx.tcx, ty::Placeholder { universe: self.universe, bound: self.next_var() }, - ct.ty(), ), ) else { diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 8348482386f7..7d9771af5afa 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -173,8 +173,7 @@ fn satisfied_from_param_env<'tcx>( debug!("is_const_evaluatable: candidate={:?}", c); if self.infcx.probe(|_| { let ocx = ObligationCtxt::new(self.infcx); - ocx.eq(&ObligationCause::dummy(), self.param_env, c.ty(), self.ct.ty()).is_ok() - && ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok() + ocx.eq(&ObligationCause::dummy(), self.param_env, c, self.ct).is_ok() && ocx.select_all_or_error().is_empty() }) { self.single_match = match self.single_match { @@ -215,7 +214,6 @@ fn satisfied_from_param_env<'tcx>( if let Some(Ok(c)) = single_match { let ocx = ObligationCtxt::new(infcx); - assert!(ocx.eq(&ObligationCause::dummy(), param_env, c.ty(), ct.ty()).is_ok()); assert!(ocx.eq(&ObligationCause::dummy(), param_env, c, ct).is_ok()); assert!(ocx.select_all_or_error().is_empty()); return true; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 9a0929baeaf2..416b62226cd8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -920,7 +920,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { &obligation.cause, None, None, - TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, ct.ty())), + // THISPR + TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, todo!())), false, false, ); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index a26288efc96d..277b52e274be 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -459,7 +459,8 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( // Only really excercised by generic_const_exprs DefineOpaqueTypes::Yes, - ct.ty(), + // THISPR + todo!(), ty, ) { Ok(inf_ok) => { @@ -633,7 +634,6 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { match self.selcx.infcx.try_const_eval_resolve( obligation.param_env, unevaluated, - c.ty(), obligation.cause.span, ) { Ok(val) => Ok(val), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index d918945dbed9..7be2c4a85c56 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -359,7 +359,7 @@ pub fn normalize_param_env_or_error<'tcx>( // `ty::Const::normalize` can only work with properly preserved binders. if c.has_escaping_bound_vars() { - return ty::Const::new_misc_error(self.0, c.ty()); + return ty::Const::new_misc_error(self.0); } // While it is pretty sus to be evaluating things with an empty param env, it // should actually be okay since without `feature(generic_const_exprs)` the only diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 501d9c9266e6..2c9cb79664b3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -523,16 +523,9 @@ fn normalize_to_error<'a, 'tcx>( | ty::AliasTermKind::InherentTy | ty::AliasTermKind::OpaqueTy | ty::AliasTermKind::WeakTy => selcx.infcx.next_ty_var(cause.span).into(), - ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => selcx - .infcx - .next_const_var( - selcx - .tcx() - .type_of(projection_term.def_id) - .instantiate(selcx.tcx(), projection_term.args), - cause.span, - ) - .into(), + ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => { + selcx.infcx.next_const_var(cause.span).into() + } }; let trait_obligation = Obligation { cause, @@ -744,8 +737,6 @@ fn project<'cx, 'tcx>( obligation.predicate.def_id, obligation.predicate.args, ), - tcx.type_of(obligation.predicate.def_id) - .instantiate(tcx, obligation.predicate.args), ) .into(), kind => { @@ -2071,15 +2062,14 @@ fn confirm_impl_candidate<'cx, 'tcx>( // * `args` ends up as `[u32, S]` let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args); let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_ty.defining_node); - let ty = tcx.type_of(assoc_ty.item.def_id); let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst); let term: ty::EarlyBinder<'tcx, ty::Term<'tcx>> = if is_const { let did = assoc_ty.item.def_id; let identity_args = crate::traits::GenericArgs::identity_for_item(tcx, did); let uv = ty::UnevaluatedConst::new(did, identity_args); - ty.map_bound(|ty| ty::Const::new_unevaluated(tcx, uv, ty).into()) + ty::EarlyBinder::bind(ty::Const::new_unevaluated(tcx, uv).into()) } else { - ty.map_bound(|ty| ty.into()) + tcx.type_of(assoc_ty.item.def_id).map_bound(|ty| ty.into()) }; if !tcx.check_args_compatible(assoc_ty.item.def_id, args) { let err = Ty::new_error_with_message( diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index ef0d8735d35f..749081006f39 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -665,9 +665,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { tcx, ty::INNERMOST, ty::BoundVar::from_usize(bound_vars.len() - 1), - tcx.type_of(param.def_id) - .no_bound_vars() - .expect("const parameter types cannot be generic"), ) .into() } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 2489b8916d18..93e6cbdf69af 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -947,7 +947,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { match self.infcx.try_const_eval_resolve( obligation.param_env, unevaluated, - c.ty(), obligation.cause.span, ) { Ok(val) => Ok(val), @@ -1009,7 +1008,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return Ok(EvaluatedToAmbig); } ty::ConstKind::Error(_) => return Ok(EvaluatedToOk), - _ => ct.ty(), + // THISPR + _ => todo!(), + // _ => ct.ty(), }; match self.infcx.at(&obligation.cause, obligation.param_env).eq( diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 5d5a22e189ce..960c27b636e1 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -483,7 +483,7 @@ impl<'tcx> TypeFolder> for BoundVarReplacer<'_, 'tcx> { let universe = self.universe_for(debruijn); let p = ty::PlaceholderConst { universe, bound: bound_const }; self.mapped_consts.insert(p, bound_const); - ty::Const::new_placeholder(self.infcx.tcx, p, ct.ty()) + ty::Const::new_placeholder(self.infcx.tcx, p) } _ => ct.super_fold_with(self), } @@ -626,7 +626,7 @@ impl<'tcx> TypeFolder> for PlaceholderReplacer<'_, 'tcx> { let db = ty::DebruijnIndex::from_usize( self.universe_indices.len() - index + self.current_index.as_usize() - 1, ); - ty::Const::new_bound(self.infcx.tcx, db, *replace_var, ct.ty()) + ty::Const::new_bound(self.infcx.tcx, db, *replace_var) } None => { if ct.has_infer() { diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 8d7d81d8f735..ccbcfed056fc 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -144,7 +144,8 @@ mod rustc { }); }; - let adt_def = c.ty().ty_adt_def()?; + let assume_def_id = tcx.get_lang_items(()).get(LangItem::TransmuteOpts)?; + let adt_def = tcx.adt_def(assume_def_id); assert_eq!( tcx.require_lang_item(LangItem::TransmuteOpts, None), diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 8a42298f2164..b403e063d40f 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -32,7 +32,10 @@ fn destructure_const<'tcx>( _ => bug!("cannot destructure constant {:?}", const_), }; - let (fields, variant) = match const_.ty().kind() { + // THISPR + let ct_ty: Ty<'tcx> = todo!(); + + let (fields, variant) = match ct_ty.kind() { ty::Array(inner_ty, _) | ty::Slice(inner_ty) => { // construct the consts for the elements of the array/slice let field_consts = branches @@ -121,7 +124,7 @@ fn recurse_build<'tcx>( let sp = node.span; match tcx.at(sp).lit_to_const(LitToConstInput { lit: &lit.node, ty: node.ty, neg }) { Ok(c) => c, - Err(LitToConstError::Reported(guar)) => ty::Const::new_error(tcx, guar, node.ty), + Err(LitToConstError::Reported(guar)) => ty::Const::new_error(tcx, guar), Err(LitToConstError::TypeError) => { bug!("encountered type error in lit_to_const") } @@ -137,35 +140,31 @@ fn recurse_build<'tcx>( } &ExprKind::NamedConst { def_id, args, user_ty: _ } => { let uneval = ty::UnevaluatedConst::new(def_id, args); - ty::Const::new_unevaluated(tcx, uneval, node.ty) + ty::Const::new_unevaluated(tcx, uneval) } - ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param, node.ty), + ExprKind::ConstParam { param, .. } => ty::Const::new_param(tcx, *param), ExprKind::Call { fun, args, .. } => { + let fun_ty = body.exprs[*fun].ty; let fun = recurse_build(tcx, body, *fun, root_span)?; let mut new_args = Vec::>::with_capacity(args.len()); for &id in args.iter() { new_args.push(recurse_build(tcx, body, id, root_span)?); } - ty::Const::new_expr( - tcx, - Expr::new_call(tcx, fun.ty(), fun, new_args.into_iter()), - node.ty, - ) + ty::Const::new_expr(tcx, Expr::new_call(tcx, fun_ty, fun, new_args.into_iter())) } &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => { + let lhs_ty = body.exprs[lhs].ty; let lhs = recurse_build(tcx, body, lhs, root_span)?; + let rhs_ty = body.exprs[rhs].ty; let rhs = recurse_build(tcx, body, rhs, root_span)?; - ty::Const::new_expr( - tcx, - Expr::new_binop(tcx, op, lhs.ty(), rhs.ty(), lhs, rhs), - node.ty, - ) + ty::Const::new_expr(tcx, Expr::new_binop(tcx, op, lhs_ty, rhs_ty, lhs, rhs)) } &ExprKind::Unary { op, arg } if check_unop(op) => { + let arg_ty = body.exprs[arg].ty; let arg = recurse_build(tcx, body, arg, root_span)?; - ty::Const::new_expr(tcx, Expr::new_unop(tcx, op, arg.ty(), arg), node.ty) + ty::Const::new_expr(tcx, Expr::new_unop(tcx, op, arg_ty, arg)) } // This is necessary so that the following compiles: // @@ -187,20 +186,12 @@ fn recurse_build<'tcx>( &ExprKind::Use { source } => { let value_ty = body.exprs[source].ty; let value = recurse_build(tcx, body, source, root_span)?; - ty::Const::new_expr( - tcx, - Expr::new_cast(tcx, CastKind::Use, value_ty, value, node.ty), - node.ty, - ) + ty::Const::new_expr(tcx, Expr::new_cast(tcx, CastKind::Use, value_ty, value, node.ty)) } &ExprKind::Cast { source } => { let value_ty = body.exprs[source].ty; let value = recurse_build(tcx, body, source, root_span)?; - ty::Const::new_expr( - tcx, - Expr::new_cast(tcx, CastKind::As, value_ty, value, node.ty), - node.ty, - ) + ty::Const::new_expr(tcx, Expr::new_cast(tcx, CastKind::As, value_ty, value, node.ty)) } ExprKind::Borrow { arg, .. } => { let arg_node = &body.exprs[*arg]; diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 1c30f03c6939..61ae36265ec7 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -115,8 +115,8 @@ impl CanonicalVarInfo { CanonicalVarKind::PlaceholderTy(_) => false, CanonicalVarKind::Region(_) => true, CanonicalVarKind::PlaceholderRegion(..) => false, - CanonicalVarKind::Const(..) => true, - CanonicalVarKind::PlaceholderConst(_, _) => false, + CanonicalVarKind::Const(_) => true, + CanonicalVarKind::PlaceholderConst(_) => false, CanonicalVarKind::Effect => true, } } @@ -126,8 +126,8 @@ impl CanonicalVarInfo { CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true, CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) - | CanonicalVarKind::Const(_, _) - | CanonicalVarKind::PlaceholderConst(_, _) + | CanonicalVarKind::Const(_) + | CanonicalVarKind::PlaceholderConst(_) | CanonicalVarKind::Effect => false, } } @@ -136,12 +136,12 @@ impl CanonicalVarInfo { match self.kind { CanonicalVarKind::Ty(_) | CanonicalVarKind::Region(_) - | CanonicalVarKind::Const(_, _) + | CanonicalVarKind::Const(_) | CanonicalVarKind::Effect => panic!("expected placeholder: {self:?}"), CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(), CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.var().as_usize(), - CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.var().as_usize(), + CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.var().as_usize(), } } } @@ -169,13 +169,13 @@ pub enum CanonicalVarKind { PlaceholderRegion(I::PlaceholderRegion), /// Some kind of const inference variable. - Const(UniverseIndex, I::Ty), + Const(UniverseIndex), /// Effect variable `'?E`. Effect, /// A "placeholder" that represents "any const". - PlaceholderConst(I::PlaceholderConst, I::Ty), + PlaceholderConst(I::PlaceholderConst), } impl PartialEq for CanonicalVarKind { @@ -185,10 +185,8 @@ impl PartialEq for CanonicalVarKind { (Self::PlaceholderTy(l0), Self::PlaceholderTy(r0)) => l0 == r0, (Self::Region(l0), Self::Region(r0)) => l0 == r0, (Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0, - (Self::Const(l0, l1), Self::Const(r0, r1)) => l0 == r0 && l1 == r1, - (Self::PlaceholderConst(l0, l1), Self::PlaceholderConst(r0, r1)) => { - l0 == r0 && l1 == r1 - } + (Self::Const(l0), Self::Const(r0)) => l0 == r0, + (Self::PlaceholderConst(l0), Self::PlaceholderConst(r0)) => l0 == r0, _ => std::mem::discriminant(self) == std::mem::discriminant(other), } } @@ -199,10 +197,10 @@ impl CanonicalVarKind { match self { CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui, CanonicalVarKind::Region(ui) => ui, - CanonicalVarKind::Const(ui, _) => ui, + CanonicalVarKind::Const(ui) => ui, CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(), CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(), - CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(), + CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe(), CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => { UniverseIndex::ROOT } @@ -220,7 +218,7 @@ impl CanonicalVarKind { CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) } CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui), - CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty), + CanonicalVarKind::Const(_) => CanonicalVarKind::Const(ui), CanonicalVarKind::PlaceholderTy(placeholder) => { CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui)) @@ -228,8 +226,8 @@ impl CanonicalVarKind { CanonicalVarKind::PlaceholderRegion(placeholder) => { CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui)) } - CanonicalVarKind::PlaceholderConst(placeholder, ty) => { - CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui), ty) + CanonicalVarKind::PlaceholderConst(placeholder) => { + CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui)) } CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) | CanonicalVarKind::Effect => { @@ -345,21 +343,14 @@ impl CanonicalVarValues { Region::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i)) .into() } - CanonicalVarKind::Effect => Const::new_anon_bound( - tcx, - ty::INNERMOST, - ty::BoundVar::from_usize(i), - Ty::new_bool(tcx), - ) - .into(), - CanonicalVarKind::Const(_, ty) - | CanonicalVarKind::PlaceholderConst(_, ty) => Const::new_anon_bound( - tcx, - ty::INNERMOST, - ty::BoundVar::from_usize(i), - ty, - ) - .into(), + CanonicalVarKind::Effect => { + Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i)) + .into() + } + CanonicalVarKind::Const(_) | CanonicalVarKind::PlaceholderConst(_) => { + Const::new_anon_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i)) + .into() + } } }, )), diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index 4e8be1ee4c28..c206f3ccdb5b 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -38,11 +38,11 @@ impl InferCtxtLike for NoInfcx { panic!("cannot resolve {vid:?}") } - fn opportunistic_resolve_ct_var(&self, vid: ConstVid, _: I::Ty) -> I::Const { + fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> I::Const { panic!("cannot resolve {vid:?}") } - fn opportunistic_resolve_effect_var(&self, vid: EffectVid, _: I::Ty) -> I::Const { + fn opportunistic_resolve_effect_var(&self, vid: EffectVid) -> I::Const { panic!("cannot resolve {vid:?}") } diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 501311ff72f7..ee3e5ce66d03 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -387,7 +387,7 @@ impl TypeFolder for Shifter { match ct.kind() { ty::ConstKind::Bound(debruijn, bound_ct) if debruijn >= self.current_index => { let debruijn = debruijn.shifted_in(self.amount); - Const::new_bound(self.tcx, debruijn, bound_ct, ct.ty()) + Const::new_bound(self.tcx, debruijn, bound_ct) } _ => ct.super_fold_with(self), } diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs index bb5081fb3357..24e10722448c 100644 --- a/compiler/rustc_type_ir/src/infcx.rs +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -12,15 +12,10 @@ pub trait InferCtxtLike { fn opportunistic_resolve_ty_var(&self, vid: TyVid) -> ::Ty; fn opportunistic_resolve_int_var(&self, vid: IntVid) -> ::Ty; fn opportunistic_resolve_float_var(&self, vid: FloatVid) -> ::Ty; - fn opportunistic_resolve_ct_var( - &self, - vid: ConstVid, - ty: ::Ty, - ) -> ::Const; + fn opportunistic_resolve_ct_var(&self, vid: ConstVid) -> ::Const; fn opportunistic_resolve_effect_var( &self, vid: EffectVid, - ty: ::Ty, ) -> ::Const; fn opportunistic_resolve_lt_var(&self, vid: RegionVid) -> ::Region; diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index f305ed9b5d77..94874a6acfce 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -104,22 +104,15 @@ pub trait Const>: + TypeSuperFoldable + Flags { - fn new_infer(interner: I, var: ty::InferConst, ty: I::Ty) -> Self; + fn new_infer(interner: I, var: ty::InferConst) -> Self; - fn new_var(interner: I, var: ty::ConstVid, ty: I::Ty) -> Self; + fn new_var(interner: I, var: ty::ConstVid) -> Self; - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst, ty: I::Ty) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst) -> Self; - fn new_anon_bound( - interner: I, - debruijn: ty::DebruijnIndex, - var: ty::BoundVar, - ty: I::Ty, - ) -> Self; + fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; - fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst, ty: I::Ty) -> Self; - - fn ty(self) -> I::Ty; + fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst) -> Self; } pub trait GenericsOf> { diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index e7039583c91c..9e0e52cfb4b7 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -567,7 +567,6 @@ impl AliasTerm { I::Const::new_unevaluated( interner, ty::UnevaluatedConst::new(self.def_id, self.args), - interner.type_of(self.def_id).instantiate(interner, &self.args), ) .into() } From a9702a66684f0e1f412d92a83761be2e461b69fb Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 3 Jun 2024 02:34:35 +0100 Subject: [PATCH 124/154] Add `Ty` to `ConstKind::Value` --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 1 + .../src/debuginfo/type_names.rs | 70 ++++++++++--------- .../rustc_codegen_ssa/src/mir/constant.rs | 2 +- .../src/check_consts/qualifs.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 3 +- compiler/rustc_infer/src/infer/freshen.rs | 2 +- compiler/rustc_infer/src/infer/mod.rs | 9 ++- compiler/rustc_middle/src/mir/consts.rs | 48 ++++++------- compiler/rustc_middle/src/mir/pretty.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 47 ++++++------- compiler/rustc_middle/src/ty/context.rs | 12 +++- compiler/rustc_middle/src/ty/fast_reject.rs | 4 +- compiler/rustc_middle/src/ty/flags.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 6 +- compiler/rustc_middle/src/ty/relate.rs | 2 +- .../rustc_middle/src/ty/structural_impls.rs | 17 +++-- compiler/rustc_middle/src/ty/walk.rs | 3 +- .../src/thir/pattern/const_to_pat.rs | 6 +- .../src/canonicalizer.rs | 2 +- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 4 +- .../rustc_smir/src/rustc_smir/convert/ty.rs | 8 +-- compiler/rustc_symbol_mangling/src/legacy.rs | 13 ++-- compiler/rustc_symbol_mangling/src/v0.rs | 67 ++++++++---------- .../src/solve/eval_ctxt/mod.rs | 9 ++- .../rustc_trait_selection/src/solve/mod.rs | 4 +- .../src/traits/auto_trait.rs | 3 +- .../src/traits/const_evaluatable.rs | 2 +- compiler/rustc_transmute/src/lib.rs | 5 +- compiler/rustc_ty_utils/src/consts.rs | 5 +- compiler/rustc_type_ir/src/const_kind.rs | 6 +- 30 files changed, 180 insertions(+), 186 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 39bbf87bea7b..7b1038d56176 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1201,6 +1201,7 @@ fn generic_simd_intrinsic<'ll, 'tcx>( .expect_const() .eval(tcx, ty::ParamEnv::reveal_all(), span) .unwrap() + .1 .unwrap_branch(); let n = idx.len() as u64; diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 2783ffc49a81..c4e5c8582404 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -693,42 +693,46 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S ty::ConstKind::Param(param) => { write!(output, "{}", param.name) } - // THISPR - _ => match { todo!() as Ty<'tcx> }.kind() { - ty::Int(ity) => { - let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all()); - let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; - write!(output, "{val}") - } - ty::Uint(_) => { - let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all()); - write!(output, "{val}") - } - ty::Bool => { - let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap(); - write!(output, "{val}") - } - _ => { - // If we cannot evaluate the constant to a known type, we fall back - // to emitting a stable hash value of the constant. This isn't very pretty - // but we get a deterministic, virtually unique value for the constant. - // - // Let's only emit 64 bits of the hash value. That should be plenty for - // avoiding collisions and will make the emitted type names shorter. - let hash_short = tcx.with_stable_hashing_context(|mut hcx| { - let mut hasher = StableHasher::new(); - let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap(); - hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher)); - hasher.finish::() - }); + ty::ConstKind::Value(ty, _) => { + match ty.kind() { + ty::Int(ity) => { + // FIXME: directly extract the bits from a valtree instead of evaluating an + // alreay evaluated `Const` in order to get the bits. + let bits = ct.eval_bits(tcx, ty::ParamEnv::reveal_all()); + let val = Integer::from_int_ty(&tcx, *ity).size().sign_extend(bits) as i128; + write!(output, "{val}") + } + ty::Uint(_) => { + let val = ct.eval_bits(tcx, ty::ParamEnv::reveal_all()); + write!(output, "{val}") + } + ty::Bool => { + let val = ct.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap(); + write!(output, "{val}") + } + _ => { + // If we cannot evaluate the constant to a known type, we fall back + // to emitting a stable hash value of the constant. This isn't very pretty + // but we get a deterministic, virtually unique value for the constant. + // + // Let's only emit 64 bits of the hash value. That should be plenty for + // avoiding collisions and will make the emitted type names shorter. + let hash_short = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); + let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), DUMMY_SP).unwrap(); + hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher)); + hasher.finish::() + }); - if cpp_like_debuginfo(tcx) { - write!(output, "CONST${hash_short:x}") - } else { - write!(output, "{{CONST#{hash_short:x}}}") + if cpp_like_debuginfo(tcx) { + write!(output, "CONST${hash_short:x}") + } else { + write!(output, "{{CONST#{hash_short:x}}}") + } } } - }, + } + _ => bug!("Invalid `Const` during codegen: {:?}", ct), } .unwrap(); } diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index dba5fbefd8a7..81eb44132dd4 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Const::Ty(c) => match c.kind() { // A constant that came from a const generic but was then used as an argument to old-style // simd_shuffle (passing as argument instead of as a generic param). - rustc_type_ir::ConstKind::Value(valtree) => return Ok(Some(valtree)), + rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Some(valtree)), other => span_bug!(constant.span, "{other:#?}"), }, // We should never encounter `Const::Val` unless MIR opts (like const prop) evaluate diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 5949444e599a..32500914f067 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -360,7 +360,7 @@ where Const::Ty(ct) if matches!( ct.kind(), - ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_) + ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_, _) ) => { None diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 93fb83fb3e4e..ba3233956b19 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2409,7 +2409,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { min_len: u64, ) -> (Option>, Ty<'tcx>) { let len = match len.eval(self.tcx, self.param_env, span) { - Ok(val) => val + // FIXME(BoxyUwU): Assert the `Ty` is a `usize`? + Ok((_, val)) => val .try_to_scalar() .and_then(|scalar| scalar.try_to_int().ok()) .and_then(|int| int.try_to_target_usize(self.tcx).ok()), diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 3ef25ae2d3ed..4bb59bd9037c 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { } ty::ConstKind::Param(_) - | ty::ConstKind::Value(_) + | ty::ConstKind::Value(_, _) | ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) | ty::ConstKind::Error(_) => ct.super_fold_with(self), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 1f6c534fbec6..4476611d9c82 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1299,7 +1299,7 @@ impl<'tcx> InferCtxt<'tcx> { | ty::ConstKind::Bound(_, _) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Unevaluated(_) - | ty::ConstKind::Value(_) + | ty::ConstKind::Value(_, _) | ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => ct, } @@ -1514,8 +1514,11 @@ impl<'tcx> InferCtxt<'tcx> { span: Span, ) -> Result, ErrorHandled> { match self.const_eval_resolve(param_env, unevaluated, span) { - // THISPR - Ok(Some(val)) => Ok(ty::Const::new_value(self.tcx, val, todo!())), + Ok(Some(val)) => Ok(ty::Const::new_value( + self.tcx, + val, + self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args), + )), Ok(None) => { let tcx = self.tcx; let def_id = unevaluated.def; diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 5c069ff820d3..b288347c6637 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -249,7 +249,7 @@ impl<'tcx> Const<'tcx> { pub fn is_required_const(&self) -> bool { match self { Const::Ty(c) => match c.kind() { - ty::ConstKind::Value(_) => false, // already a value, cannot error + ty::ConstKind::Value(_, _) => false, // already a value, cannot error _ => true, }, Const::Val(..) => false, // already a value, cannot error @@ -261,9 +261,7 @@ impl<'tcx> Const<'tcx> { pub fn try_to_scalar(self) -> Option { match self { Const::Ty(c) => match c.kind() { - // THISPR - // if c.ty().is_primitive() - ty::ConstKind::Value(valtree) if todo!() => { + ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => { // A valtree of a type where leaves directly represent the scalar const value. // Just checking whether it is a leaf is insufficient as e.g. references are leafs // but the leaf value is the value they point to, not the reference itself! @@ -282,9 +280,9 @@ impl<'tcx> Const<'tcx> { match self { Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x), Const::Ty(c) => match c.kind() { - // THISPR - // if c.ty().is_primitive() - ty::ConstKind::Value(valtree) if todo!() => Some(valtree.unwrap_leaf()), + ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => { + Some(valtree.unwrap_leaf()) + } _ => None, }, _ => None, @@ -312,8 +310,8 @@ impl<'tcx> Const<'tcx> { Const::Ty(c) => { // We want to consistently have a "clean" value for type system constants (i.e., no // data hidden in the padding), so we always go through a valtree here. - let val = c.eval(tcx, param_env, span)?; - Ok(tcx.valtree_to_const_val((self.ty(), val))) + let (ty, val) = c.eval(tcx, param_env, span)?; + Ok(tcx.valtree_to_const_val((ty, val))) } Const::Unevaluated(uneval, _) => { // FIXME: We might want to have a `try_eval`-like function on `Unevaluated` @@ -341,17 +339,16 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option { - match self { - // THISPR - // c.ty().is_primitive() - Const::Ty(c) if todo!() => { - // Avoid the `valtree_to_const_val` query. Can only be done on primitive types that - // are valtree leaves, and *not* on references. (References should return the - // pointer here, which valtrees don't represent.) - let val = c.eval(tcx, param_env, DUMMY_SP).ok()?; - Some(val.unwrap_leaf().into()) - } - _ => self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar(), + if let Const::Ty(c) = self + && let ty::ConstKind::Value(ty, val) = c.kind() + && ty.is_primitive() + { + // Avoid the `valtree_to_const_val` query. Can only be done on primitive types that + // are valtree leaves, and *not* on references. (References should return the + // pointer here, which valtrees don't represent.) + Some(val.unwrap_leaf().into()) + } else { + self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar() } } @@ -446,11 +443,10 @@ impl<'tcx> Const<'tcx> { pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self { match c.kind() { - ty::ConstKind::Value(valtree) => { + ty::ConstKind::Value(ty, valtree) => { // Make sure that if `c` is normalized, then the return value is normalized. - // THISPR - let const_val = tcx.valtree_to_const_val((todo!(), valtree)); - Self::Val(const_val, todo!()) + let const_val = tcx.valtree_to_const_val((ty, valtree)); + Self::Val(const_val, ty) } _ => Self::Ty(c), } @@ -469,9 +465,7 @@ impl<'tcx> Const<'tcx> { // A valtree may be a reference. Valtree references correspond to a // different allocation each time they are evaluated. Valtrees for primitive // types are fine though. - // THISPR - // c.ty().is_primitive() - ty::ConstKind::Value(_) => todo!(), + ty::ConstKind::Value(ty, _) => ty.is_primitive(), ty::ConstKind::Unevaluated(..) | ty::ConstKind::Expr(..) => false, // This can happen if evaluation of a constant failed. The result does not matter // much since compilation is doomed. diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index f1c79c0b0391..845a8da3443a 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1318,7 +1318,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { ty::ConstKind::Unevaluated(uv) => { format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,) } - ty::ConstKind::Value(val) => format!("ty::Valtree({})", fmt_valtree(&val)), + ty::ConstKind::Value(_, val) => format!("ty::Valtree({})", fmt_valtree(&val)), // No `ty::` prefix since we also use this to represent errors from `mir::Unevaluated`. ty::ConstKind::Error(_) => "Error".to_string(), // These variants shouldn't exist in the MIR. diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 7e84b763fa8b..dc13cc5437d5 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -24,7 +24,7 @@ pub type ConstKind<'tcx> = ir::ConstKind>; pub type UnevaluatedConst<'tcx> = ir::UnevaluatedConst>; #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(ConstKind<'_>, 24); +rustc_data_structures::static_assert_size!(ConstKind<'_>, 32); #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable)] #[rustc_pass_by_value] @@ -168,10 +168,6 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self { Const::new_unevaluated(interner, uv) } - - fn ty(self) -> Ty<'tcx> { - self.ty() - } } impl<'tcx> Const<'tcx> { @@ -311,7 +307,7 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, span: Span, - ) -> Result, ErrorHandled> { + ) -> Result<(Ty<'tcx>, ValTree<'tcx>), ErrorHandled> { assert!(!self.has_escaping_bound_vars(), "escaping vars in {self:?}"); match self.kind() { ConstKind::Unevaluated(unevaluated) => { @@ -329,9 +325,9 @@ impl<'tcx> Const<'tcx> { ); return Err(e.into()); }; - Ok(c) + Ok((tcx.type_of(unevaluated.def).instantiate(tcx, unevaluated.args), c)) } - ConstKind::Value(val) => Ok(val), + ConstKind::Value(ty, val) => Ok((ty, val)), ConstKind::Error(g) => Err(g.into()), ConstKind::Param(_) | ConstKind::Infer(_) @@ -345,7 +341,7 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Self { match self.eval(tcx, param_env, DUMMY_SP) { - Ok(val) => Self::new_value(tcx, val, self.ty_for_ctfe(tcx).unwrap()), + Ok((ty, val)) => Self::new_value(tcx, val, ty), Err(ErrorHandled::Reported(r, _span)) => Self::new_error(tcx, r.into()), Err(ErrorHandled::TooGeneric(_span)) => self, } @@ -356,8 +352,10 @@ impl<'tcx> Const<'tcx> { self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, - ) -> Option { - self.eval(tcx, param_env, DUMMY_SP).ok()?.try_to_scalar() + ) -> Option<(Ty<'tcx>, Scalar)> { + let (ty, val) = self.eval(tcx, param_env, DUMMY_SP).ok()?; + let val = val.try_to_scalar()?; + Some((ty, val)) } #[inline] @@ -368,8 +366,10 @@ impl<'tcx> Const<'tcx> { self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, - ) -> Option { - self.try_eval_scalar(tcx, param_env)?.try_to_int().ok() + ) -> Option<(Ty<'tcx>, ScalarInt)> { + let (ty, scalar) = self.try_eval_scalar(tcx, param_env)?; + let val = scalar.try_to_int().ok()?; + Some((ty, val)) } #[inline] @@ -377,15 +377,10 @@ impl<'tcx> Const<'tcx> { /// generics (or erroneous code) or if the value can't be represented as bits (e.g. because it /// contains const generic parameters or pointers). pub fn try_eval_bits(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - let int = self.try_eval_scalar_int(tcx, param_env)?; - let size = tcx - .layout_of( - param_env.with_reveal_all_normalized(tcx).and(self.ty_for_ctfe(tcx).unwrap()), - ) - .ok()? - .size; + let (ty, scalar) = self.try_eval_scalar_int(tcx, param_env)?; + let size = tcx.layout_of(param_env.with_reveal_all_normalized(tcx).and(ty)).ok()?.size; // if `ty` does not depend on generic parameters, use an empty param_env - int.try_to_bits(size).ok() + scalar.try_to_bits(size).ok() } #[inline] @@ -401,12 +396,14 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, ) -> Option { - self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok() + let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?; + scalar.try_to_target_usize(tcx).ok() } #[inline] pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> Option { - self.try_eval_scalar_int(tcx, param_env)?.try_into().ok() + let (_, scalar) = self.try_eval_scalar_int(tcx, param_env)?; + scalar.try_into().ok() } #[inline] @@ -419,7 +416,7 @@ impl<'tcx> Const<'tcx> { /// Panics if self.kind != ty::ConstKind::Value pub fn to_valtree(self) -> ty::ValTree<'tcx> { match self.kind() { - ty::ConstKind::Value(valtree) => valtree, + ty::ConstKind::Value(_, valtree) => valtree, _ => bug!("expected ConstKind::Value, got {:?}", self.kind()), } } @@ -427,7 +424,7 @@ impl<'tcx> Const<'tcx> { /// Attempts to convert to a `ValTree` pub fn try_to_valtree(self) -> Option> { match self.kind() { - ty::ConstKind::Value(valtree) => Some(valtree), + ty::ConstKind::Value(_, valtree) => Some(valtree), _ => None, } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 7e8b3fea1eae..f9a22aa72bee 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -601,9 +601,15 @@ impl<'tcx> CommonConsts<'tcx> { }; CommonConsts { - unit: mk_const(ty::ConstKind::Value(ty::ValTree::zst())), - true_: mk_const(ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::TRUE))), - false_: mk_const(ty::ConstKind::Value(ty::ValTree::Leaf(ty::ScalarInt::FALSE))), + unit: mk_const(ty::ConstKind::Value(types.unit, ty::ValTree::zst())), + true_: mk_const(ty::ConstKind::Value( + types.bool, + ty::ValTree::Leaf(ty::ScalarInt::TRUE), + )), + false_: mk_const(ty::ConstKind::Value( + types.bool, + ty::ValTree::Leaf(ty::ScalarInt::FALSE), + )), } } } diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 7508f0080ccf..923667e609be 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -337,7 +337,7 @@ impl DeepRejectCtxt { | ty::ConstKind::Error(_) => { return true; } - ty::ConstKind::Value(impl_val) => impl_val, + ty::ConstKind::Value(_, impl_val) => impl_val, ty::ConstKind::Infer(_) | ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { bug!("unexpected impl arg: {:?}", impl_ct) } @@ -357,7 +357,7 @@ impl DeepRejectCtxt { ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => { true } - ty::ConstKind::Value(obl_val) => obl_val == impl_val, + ty::ConstKind::Value(_, obl_val) => obl_val == impl_val, ty::ConstKind::Infer(_) => true, diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 5f653aba4852..21c115c2c966 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -372,7 +372,7 @@ impl FlagComputation { self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } - ty::ConstKind::Value(_) => {} + ty::ConstKind::Value(ty, _) => self.add_ty(ty), ty::ConstKind::Expr(e) => self.add_args(e.args()), ty::ConstKind::Error(_) => self.add_flags(TypeFlags::HAS_ERROR), } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 8fec654acc58..ef391be889cf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1511,8 +1511,8 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { _ => print_underscore!(), }, ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), - ty::ConstKind::Value(value) => { - return self.pretty_print_const_valtree(value, todo!(), print_ty); + ty::ConstKind::Value(ty, value) => { + return self.pretty_print_const_valtree(value, ty, print_ty); } ty::ConstKind::Bound(debruijn, bound_var) => { @@ -1666,7 +1666,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::Ref(_, inner, _) => { if let ty::Array(elem, len) = inner.kind() { if let ty::Uint(ty::UintTy::U8) = elem.kind() { - if let ty::ConstKind::Value(ty::ValTree::Leaf(int)) = len.kind() { + if let ty::ConstKind::Value(_, ty::ValTree::Leaf(int)) = len.kind() { match self.tcx().try_get_global_alloc(prov.alloc_id()) { Some(GlobalAlloc::Memory(alloc)) => { let len = int.assert_bits(self.tcx().data_layout.pointer_size); diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index b0581f89380c..c0ed5fad2475 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -646,7 +646,7 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( true } (ty::ConstKind::Placeholder(p1), ty::ConstKind::Placeholder(p2)) => p1 == p2, - (ty::ConstKind::Value(a_val), ty::ConstKind::Value(b_val)) => a_val == b_val, + (ty::ConstKind::Value(_, a_val), ty::ConstKind::Value(_, b_val)) => a_val == b_val, // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `generic_const_exprs` can diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index ee235d3781b8..cf4854d13646 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -201,18 +201,16 @@ impl<'tcx> DebugWithInfcx> for ty::Const<'tcx> { f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { // If this is a value, we spend some effort to make it look nice. - if let ConstKind::Value(_) = this.data.kind() { + if let ConstKind::Value(_, _) = this.data.kind() { return ty::tls::with(move |tcx| { // Somehow trying to lift the valtree results in lifetime errors, so we lift the // entire constant. let lifted = tcx.lift(*this.data).unwrap(); - let ConstKind::Value(valtree) = lifted.kind() else { + let ConstKind::Value(ty, valtree) = lifted.kind() else { bug!("we checked that this is a valtree") }; let mut cx = FmtPrinter::new(tcx, Namespace::ValueNS); - // THISPR - todo!(); - // cx.pretty_print_const_valtree(valtree, lifted.ty(), /*print_ty*/ true)?; + cx.pretty_print_const_valtree(valtree, ty, /*print_ty*/ true)?; f.write_str(&cx.into_buffer()) }); } @@ -652,7 +650,9 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { } ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?), ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?), - ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), + ConstKind::Value(t, v) => { + ConstKind::Value(t.try_fold_with(folder)?, v.try_fold_with(folder)?) + } ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), }; @@ -671,7 +671,10 @@ impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { } ConstKind::Placeholder(p) => p.visit_with(visitor), ConstKind::Unevaluated(uv) => uv.visit_with(visitor), - ConstKind::Value(v) => v.visit_with(visitor), + ConstKind::Value(t, v) => { + try_visit!(t.visit_with(visitor)); + v.visit_with(visitor) + } ConstKind::Error(e) => e.visit_with(visitor), ConstKind::Expr(e) => e.visit_with(visitor), } diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs index 9b313fc7bf0a..e0f204a687f6 100644 --- a/compiler/rustc_middle/src/ty/walk.rs +++ b/compiler/rustc_middle/src/ty/walk.rs @@ -217,9 +217,10 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) | ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Bound(..) - | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => {} + ty::ConstKind::Value(ty, _) => stack.push(ty.into()), + ty::ConstKind::Expr(expr) => stack.extend(expr.args().iter().rev()), ty::ConstKind::Unevaluated(ct) => { stack.extend(ct.args.iter().rev()); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 8d881713eeb3..cc5aa8ea9cc7 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -101,7 +101,7 @@ impl<'tcx> ConstToPat<'tcx> { // level of indirection can be eliminated let have_valtree = - matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_))); + matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_, _))); let inlined_const_as_pat = match cv { mir::Const::Ty(c) => match c.kind() { ty::ConstKind::Param(_) @@ -113,8 +113,8 @@ impl<'tcx> ConstToPat<'tcx> { | ty::ConstKind::Expr(_) => { span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind()) } - ty::ConstKind::Value(valtree) => { - self.recur(valtree, cv.ty()).unwrap_or_else(|_: FallbackToOpaqueConst| { + ty::ConstKind::Value(ty, valtree) => { + self.recur(valtree, ty).unwrap_or_else(|_: FallbackToOpaqueConst| { Box::new(Pat { span: self.span, ty: cv.ty(), diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index 8b96519c3211..f22e24ef6541 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -416,7 +416,7 @@ impl, I: Interner> TypeFolder // FIXME: See comment above -- we could fold the region separately or something. ty::ConstKind::Bound(_, _) | ty::ConstKind::Unevaluated(_) - | ty::ConstKind::Value(_) + | ty::ConstKind::Value(_, _) | ty::ConstKind::Error(_) | ty::ConstKind::Expr(_) => return c.super_fold_with(self), }; diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 22224e1cc959..bd8e52229fa7 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -116,12 +116,10 @@ fn encode_const<'tcx>( } // Literal arguments - ty::ConstKind::Value(..) => { + ty::ConstKind::Value(ct_ty, ..) => { // L[n]E as literal argument // Element type - // THISPR - let ct_ty: Ty<'tcx> = todo!(); s.push_str(&encode_ty(tcx, ct_ty, dict, options)); // The only allowed types of const values are bool, u8, u16, u32, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index 4d60dd73c3cc..f26439d42767 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -415,7 +415,7 @@ pub fn mir_const_from_ty_const<'tcx>( ty: Ty<'tcx>, ) -> stable_mir::ty::MirConst { let kind = match ty_const.kind() { - ty::Value(val) => { + ty::Value(ty, val) => { let val = match val { ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar), ty::ValTree::Branch(branch) => { @@ -456,7 +456,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { let kind = match self.kind() { - ty::Value(val) => { + ty::Value(ty, val) => { let val = match val { ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar), ty::ValTree::Branch(branch) => { @@ -464,9 +464,7 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { } }; - // THISPR - let ty = todo!(); - // let ty = tables.tcx.lift(c.ty()).unwrap(); + let ty = tables.tcx.lift(ty).unwrap(); let const_val = tables.tcx.valtree_to_const_val((ty, val)); if matches!(const_val, mir::ConstValue::ZeroSized) { stable_mir::ty::TyConstKind::ZSTValue(ty.stable(tables)) diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 1fea9b561a26..75cac6c7992a 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -269,21 +269,16 @@ impl<'tcx> Printer<'tcx> for SymbolPrinter<'tcx> { } fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> { - // THISPR - let ct_ty: Ty<'tcx> = todo!(); - // only print integers - match (ct.kind(), ct_ty.kind()) { - (ty::ConstKind::Value(ty::ValTree::Leaf(scalar)), ty::Int(_) | ty::Uint(_)) => { + match ct.kind() { + ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar)) if ty.is_integral() => { // The `pretty_print_const` formatting depends on -Zverbose-internals // flag, so we cannot reuse it here. - let signed = matches!(ct_ty.kind(), ty::Int(_)); + let signed = matches!(ty.kind(), ty::Int(_)); write!( self, "{:#?}", - // THISPR - // ct.ty().is_ptr_sized_integral() - ty::ConstInt::new(scalar, signed, todo!()) + ty::ConstInt::new(scalar, signed, ty.is_ptr_sized_integral()) )?; } _ => self.write_str("_")?, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index bb45fd07bee4..55479bce6fc8 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -541,8 +541,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { fn print_const(&mut self, ct: ty::Const<'tcx>) -> Result<(), PrintError> { // We only mangle a typed value if the const can be evaluated. let ct = ct.normalize(self.tcx, ty::ParamEnv::reveal_all()); - match ct.kind() { - ty::ConstKind::Value(_) => {} + let (ct_ty, valtree) = match ct.kind() { + ty::ConstKind::Value(ty, val) => (ty, val), // Placeholders (should be demangled as `_`). // NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore @@ -559,7 +559,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { self.push("p"); return Ok(()); } - } + }; if let Some(&i) = self.consts.get(&ct) { self.print_backref(i)?; @@ -567,18 +567,15 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { } let start = self.out.len(); - // THISPR - let ty: Ty<'tcx> = todo!(); - // let ty = ct.ty(); - match ty.kind() { + match ct_ty.kind() { ty::Uint(_) | ty::Int(_) | ty::Bool | ty::Char => { - ty.print(self)?; + ct_ty.print(self)?; let mut bits = ct.eval_bits(self.tcx, ty::ParamEnv::reveal_all()); // Negative integer values are mangled using `n` as a "sign prefix". - if let ty::Int(ity) = ty.kind() { + if let ty::Int(ity) = ct_ty.kind() { let val = Integer::from_int_ty(&self.tcx, *ity).size().sign_extend(bits) as i128; if val < 0 { @@ -600,38 +597,32 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { match inner_ty.kind() { ty::Str if mutbl.is_not() => { - match ct.kind() { - ty::ConstKind::Value(valtree) => { - let slice = - valtree.try_to_raw_bytes(self.tcx(), ty).unwrap_or_else(|| { - bug!( - "expected to get raw bytes from valtree {:?} for type {:}", - valtree, ty - ) - }); - let s = std::str::from_utf8(slice) - .expect("non utf8 str from MIR interpreter"); + let slice = + valtree.try_to_raw_bytes(self.tcx(), ct_ty).unwrap_or_else(|| { + bug!( + "expected to get raw bytes from valtree {:?} for type {:}", + valtree, + ct_ty + ) + }); + let s = + std::str::from_utf8(slice).expect("non utf8 str from MIR interpreter"); - self.push("e"); + self.push("e"); - // FIXME(eddyb) use a specialized hex-encoding loop. - for byte in s.bytes() { - let _ = write!(self.out, "{byte:02x}"); - } - - self.push("_"); - } - - _ => { - bug!("symbol_names: unsupported `&str` constant: {:?}", ct); - } + // FIXME(eddyb) use a specialized hex-encoding loop. + for byte in s.bytes() { + let _ = write!(self.out, "{byte:02x}"); } + + self.push("_"); } _ => { - let pointee_ty = - ty.builtin_deref(true).expect("tried to dereference on non-ptr type"); - // FIXME(const_generics): add an assert that we only do this for valtrees. - let dereferenced_const = self.tcx.mk_ct_from_kind(ct.kind()); + let pointee_ty = ct_ty + .builtin_deref(true) + .expect("tried to dereference on non-ptr type"); + let dereferenced_const = + ty::Const::new_value(self.tcx, valtree, pointee_ty); dereferenced_const.print(self)?; } } @@ -649,7 +640,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { Ok(()) }; - match *ty.kind() { + match *ct_ty.kind() { ty::Array(..) | ty::Slice(_) => { self.push("A"); print_field_list(self)?; @@ -698,7 +689,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> { } } _ => { - bug!("symbol_names: unsupported constant of type `{}` ({:?})", ty, ct); + bug!("symbol_names: unsupported constant of type `{}` ({:?})", ct_ty, ct); } } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs index eecceaec6a78..f90e47110376 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs @@ -1040,8 +1040,13 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> { ) -> Option> { use rustc_middle::mir::interpret::ErrorHandled; match self.infcx.const_eval_resolve(param_env, unevaluated, DUMMY_SP) { - // THISPR - Ok(Some(val)) => Some(ty::Const::new_value(self.interner(), val, todo!())), + Ok(Some(val)) => Some(ty::Const::new_value( + self.interner(), + val, + self.interner() + .type_of(unevaluated.def) + .instantiate(self.interner(), unevaluated.args), + )), Ok(None) | Err(ErrorHandled::TooGeneric(_)) => None, Err(ErrorHandled::Reported(e, _)) => { Some(ty::Const::new_error(self.interner(), e.into())) diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index be5b36c5c8a0..effbd94c3363 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -178,7 +178,9 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { ty::ConstKind::Infer(_) => { self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } - ty::ConstKind::Placeholder(_) | ty::ConstKind::Value(_) | ty::ConstKind::Error(_) => { + ty::ConstKind::Placeholder(_) + | ty::ConstKind::Value(_, _) + | ty::ConstKind::Error(_) => { self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } // We can freely ICE here as: diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index c3a25a50c7fb..1d32ef2ccd94 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -765,8 +765,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { unevaluated, obligation.cause.span, ) { - // THISPR - Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, todo!())), + Ok(Some(valtree)) => Ok(ty::Const::new_value(selcx.tcx(),valtree, self.tcx.type_of(unevaluated.def).instantiate(self.tcx, unevaluated.args))), Ok(None) => { let tcx = self.tcx; let reported = diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 7d9771af5afa..f93bd0a396dd 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -34,7 +34,7 @@ pub fn is_const_evaluatable<'tcx>( ty::ConstKind::Param(_) | ty::ConstKind::Bound(_, _) | ty::ConstKind::Placeholder(_) - | ty::ConstKind::Value(_) + | ty::ConstKind::Value(_, _) | ty::ConstKind::Error(_) => return Ok(()), ty::ConstKind::Infer(_) => return Err(NotConstEvaluatable::MentionsInfer), }; diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index ccbcfed056fc..ffebf7b0721a 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -135,7 +135,7 @@ mod rustc { use rustc_middle::ty::ScalarInt; use rustc_span::symbol::sym; - let Ok(cv) = c.eval(tcx, param_env, DUMMY_SP) else { + let Ok((ty, cv)) = c.eval(tcx, param_env, DUMMY_SP) else { return Some(Self { alignment: true, lifetimes: true, @@ -144,8 +144,7 @@ mod rustc { }); }; - let assume_def_id = tcx.get_lang_items(()).get(LangItem::TransmuteOpts)?; - let adt_def = tcx.adt_def(assume_def_id); + let adt_def = ty.ty_adt_def()?; assert_eq!( tcx.require_lang_item(LangItem::TransmuteOpts, None), diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index b403e063d40f..f5c66e48ea64 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -23,7 +23,7 @@ fn destructure_const<'tcx>( tcx: TyCtxt<'tcx>, const_: ty::Const<'tcx>, ) -> ty::DestructuredConst<'tcx> { - let ty::ConstKind::Value(valtree) = const_.kind() else { + let ty::ConstKind::Value(ct_ty, valtree) = const_.kind() else { bug!("cannot destructure constant {:?}", const_) }; @@ -32,9 +32,6 @@ fn destructure_const<'tcx>( _ => bug!("cannot destructure constant {:?}", const_), }; - // THISPR - let ct_ty: Ty<'tcx> = todo!(); - let (fields, variant) = match ct_ty.kind() { ty::Array(inner_ty, _) | ty::Slice(inner_ty) => { // construct the consts for the elements of the array/slice diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 7076df2893fe..84d48e14c241 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -32,7 +32,7 @@ pub enum ConstKind { Unevaluated(ty::UnevaluatedConst), /// Used to hold computed value. - Value(I::ValueConst), + Value(I::Ty, I::ValueConst), /// A placeholder for a const which could not be computed; this is /// propagated to avoid useless error messages. @@ -51,7 +51,7 @@ impl PartialEq for ConstKind { (Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1, (Placeholder(l0), Placeholder(r0)) => l0 == r0, (Unevaluated(l0), Unevaluated(r0)) => l0 == r0, - (Value(l0), Value(r0)) => l0 == r0, + (Value(l0, l1), Value(r0, r1)) => l0 == r0 && l1 == r1, (Error(l0), Error(r0)) => l0 == r0, (Expr(l0), Expr(r0)) => l0 == r0, _ => false, @@ -80,7 +80,7 @@ impl DebugWithInfcx for ConstKind { Unevaluated(uv) => { write!(f, "{:?}", &this.wrap(uv)) } - Value(valtree) => write!(f, "{valtree:?}"), + Value(ty, valtree) => write!(f, "({valtree:?}: {:?})", &this.wrap(ty)), Error(_) => write!(f, "{{const error}}"), Expr(expr) => write!(f, "{:?}", &this.wrap(expr)), } From 8d6705cdb8e6da72c61dfd0feb80ec4061d448bd Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 3 Jun 2024 03:11:11 +0100 Subject: [PATCH 125/154] Fully implement `ConstArgHasType` --- compiler/rustc_middle/src/traits/mod.rs | 2 + compiler/rustc_middle/src/ty/mod.rs | 24 ++++++ compiler/rustc_middle/src/ty/sty.rs | 22 ++++++ .../rustc_trait_selection/src/solve/mod.rs | 41 ++++++---- .../error_reporting/type_err_ctxt_ext.rs | 78 ++++++++----------- .../src/traits/fulfill.rs | 68 +++++++++------- .../src/traits/select/mod.rs | 26 ++++--- 7 files changed, 158 insertions(+), 103 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 62e71c4db11f..63678ab659df 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -616,6 +616,8 @@ pub enum SelectionError<'tcx> { /// We can thus not know whether the hidden type implements an auto trait, so /// we should not presume anything about it. OpaqueTypeAutoTraitLeakageUnknown(DefId), + /// Error for a `ConstArgHasType` goal + ConstArgHasWrongType { ct: ty::Const<'tcx>, ct_ty: Ty<'tcx>, expected_ty: Ty<'tcx> }, } #[derive(Clone, Debug, TypeVisitable)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index fc42a11cff01..e0fbf127e708 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -934,6 +934,30 @@ pub struct Placeholder { pub universe: UniverseIndex, pub bound: T, } +impl Placeholder { + pub fn find_const_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { + let mut candidates = env.caller_bounds().iter().filter_map(|clause| { + // `ConstArgHasType` are never desugared to be higher ranked. + match clause.kind().skip_binder() { + ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => { + assert!(!(placeholder_ct, ty).has_escaping_bound_vars()); + + match placeholder_ct.kind() { + ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => { + Some(ty) + } + _ => None, + } + } + _ => None, + } + }); + + let ty = candidates.next().unwrap(); + assert!(candidates.next().is_none()); + ty + } +} pub type PlaceholderRegion = Placeholder; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 879396b06781..c83f6b0b9ec6 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -21,6 +21,7 @@ use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_target::spec::abi; +use rustc_type_ir::visit::TypeVisitableExt; use std::assert_matches::debug_assert_matches; use std::borrow::Cow; use std::iter; @@ -339,6 +340,27 @@ impl ParamConst { pub fn for_def(def: &ty::GenericParamDef) -> ParamConst { ParamConst::new(def.index, def.name) } + + pub fn find_ty_from_env<'tcx>(self, env: ParamEnv<'tcx>) -> Ty<'tcx> { + let mut candidates = env.caller_bounds().iter().filter_map(|clause| { + // `ConstArgHasType` are never desugared to be higher ranked. + match clause.kind().skip_binder() { + ty::ClauseKind::ConstArgHasType(param_ct, ty) => { + assert!(!(param_ct, ty).has_escaping_bound_vars()); + + match param_ct.kind() { + ty::ConstKind::Param(param_ct) if param_ct.index == self.index => Some(ty), + _ => None, + } + } + _ => None, + } + }); + + let ty = candidates.next().unwrap(); + assert!(candidates.next().is_none()); + ty + } } #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index effbd94c3363..c47b01949641 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -200,30 +200,37 @@ impl<'a, 'tcx> EvalCtxt<'a, InferCtxt<'tcx>> { ) -> QueryResult<'tcx> { let (ct, ty) = goal.predicate; - // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant - // other than `ConstKind::Value`. Unfortunately this would require looking in the - // env for any `ConstArgHasType` assumptions for parameters and placeholders. I - // have not yet gotten around to implementing this though. - // - // We do still stall on infer vars though as otherwise a goal like: - // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later - // get unified with some const that is not of type `usize`. - match ct.kind() { + let ct_ty = match ct.kind() { // FIXME: Ignore effect vars because canonicalization doesn't handle them correctly // and if we stall on the var then we wind up creating ambiguity errors in a probe // for this goal which contains an effect var. Which then ends up ICEing. - ty::ConstKind::Infer(ty::InferConst::Var(_)) => { - self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + ty::ConstKind::Infer(ty::InferConst::EffectVar(_)) => { + return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); + } + ty::ConstKind::Infer(_) => { + return self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS); } ty::ConstKind::Error(_) => { - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes); } - _ => { - // THISPR - self.eq(goal.param_env, todo!(), ty)?; - self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + ty::ConstKind::Unevaluated(uv) => { + self.interner().type_of(uv.def).instantiate(self.interner(), uv.args) } - } + ty::ConstKind::Expr(_) => unimplemented!( + "`feature(generic_const_exprs)` is not supported in the new trait solver" + ), + ty::ConstKind::Param(_) => { + unreachable!("`ConstKind::Param` should have been canonicalized to `Placeholder`") + } + ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct), + ty::ConstKind::Value(ty, _) => ty, + ty::ConstKind::Placeholder(placeholder) => { + placeholder.find_const_ty_from_env(goal.param_env) + } + }; + + self.eq(goal.param_env, ct_ty, ty)?; + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 416b62226cd8..46b137881866 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -876,57 +876,25 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } - ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) => { - // Errors for `ConstEvaluatable` predicates show up as - // `SelectionError::ConstEvalFailure`, - // not `Unimplemented`. + // Errors for `ConstEvaluatable` predicates show up as + // `SelectionError::ConstEvalFailure`, + // not `Unimplemented`. + ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..)) + // Errors for `ConstEquate` predicates show up as + // `SelectionError::ConstEvalFailure`, + // not `Unimplemented`. + | ty::PredicateKind::ConstEquate { .. } + // Ambiguous predicates should never error + | ty::PredicateKind::Ambiguous + | ty::PredicateKind::NormalizesTo { .. } + | ty::PredicateKind::AliasRelate { .. } + | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType { .. }) => { span_bug!( span, - "const-evaluatable requirement gave wrong error: `{:?}`", + "Unexpected `Predicate` for `SelectionError`: `{:?}`", obligation ) } - - ty::PredicateKind::ConstEquate(..) => { - // Errors for `ConstEquate` predicates show up as - // `SelectionError::ConstEvalFailure`, - // not `Unimplemented`. - span_bug!( - span, - "const-equate requirement gave wrong error: `{:?}`", - obligation - ) - } - - ty::PredicateKind::Ambiguous => span_bug!(span, "ambiguous"), - - ty::PredicateKind::NormalizesTo(..) => span_bug!( - span, - "NormalizesTo predicate should never be the predicate cause of a SelectionError" - ), - - ty::PredicateKind::AliasRelate(..) => span_bug!( - span, - "AliasRelate predicate should never be the predicate cause of a SelectionError" - ), - - ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { - let mut diag = self.dcx().struct_span_err( - span, - format!("the constant `{ct}` is not of type `{ty}`"), - ); - self.note_type_err( - &mut diag, - &obligation.cause, - None, - None, - // THISPR - TypeError::Sorts(ty::error::ExpectedFound::new(true, ty, todo!())), - false, - false, - ); - diag - } } } @@ -989,6 +957,24 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { Overflow(_) => { bug!("overflow should be handled before the `report_selection_error` path"); } + + SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => { + let mut diag = self.dcx().struct_span_err( + span, + format!("the constant `{ct}` is not of type `{expected_ty}`"), + ); + + self.note_type_err( + &mut diag, + &obligation.cause, + None, + None, + TypeError::Sorts(ty::error::ExpectedFound::new(true, expected_ty, ct_ty)), + false, + false, + ); + diag + } }; self.note_obligation_cause(&mut err, &obligation); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 277b52e274be..bce5c7101cc5 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -439,38 +439,50 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> { // This is because this is not ever a useful obligation to report // as the cause of an overflow. ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { - // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant - // other than `ConstKind::Value`. Unfortunately this would require looking in the - // env for any `ConstArgHasType` assumptions for parameters and placeholders. I - // don't really want to implement this in the old solver so I haven't. - // - // We do still stall on infer vars though as otherwise a goal like: - // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later - // get unified with some const that is not of type `usize`. - let ct = self.selcx.infcx.shallow_resolve_const(ct); - match ct.kind() { - ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { + let ct = infcx.shallow_resolve_const(ct); + let ct_ty = match ct.kind() { + ty::ConstKind::Infer(var) => { + let var = match var { + ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid), + ty::InferConst::EffectVar(vid) => TyOrConstInferVar::Effect(vid), + ty::InferConst::Fresh(_) => { + bug!("encountered fresh const in fulfill") + } + }; pending_obligation.stalled_on.clear(); - pending_obligation.stalled_on.extend([TyOrConstInferVar::Const(vid)]); - ProcessResult::Unchanged + pending_obligation.stalled_on.extend([var]); + return ProcessResult::Unchanged; } ty::ConstKind::Error(_) => return ProcessResult::Changed(vec![]), - _ => { - match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq( - // Only really excercised by generic_const_exprs - DefineOpaqueTypes::Yes, - // THISPR - todo!(), - ty, - ) { - Ok(inf_ok) => { - ProcessResult::Changed(mk_pending(inf_ok.into_obligations())) - } - Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select( - SelectionError::Unimplemented, - )), - } + ty::ConstKind::Value(ty, _) => ty, + ty::ConstKind::Unevaluated(uv) => { + infcx.tcx.type_of(uv.def).instantiate(infcx.tcx, uv.args) } + // FIXME(generic_const_exprs): we should construct an alias like + // `>::Output` when this is an `Expr` representing + // `lhs + rhs`. + ty::ConstKind::Expr(_) => { + return ProcessResult::Changed(mk_pending(vec![])); + } + ty::ConstKind::Placeholder(_) => { + bug!("placeholder const {:?} in old solver", ct) + } + ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct), + ty::ConstKind::Param(param_ct) => { + param_ct.find_ty_from_env(obligation.param_env) + } + }; + + match infcx.at(&obligation.cause, obligation.param_env).eq( + // Only really excercised by generic_const_exprs + DefineOpaqueTypes::Yes, + ct_ty, + ty, + ) { + Ok(inf_ok) => ProcessResult::Changed(mk_pending(inf_ok.into_obligations())), + Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select( + SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty }, + )), } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 93e6cbdf69af..ce4fa5fa47cb 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -994,23 +994,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::PredicateKind::Ambiguous => Ok(EvaluatedToAmbig), ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => { - // FIXME(BoxyUwU): Really we should not be calling `ct.ty()` for any variant - // other than `ConstKind::Value`. Unfortunately this would require looking in the - // env for any `ConstArgHasType` assumptions for parameters and placeholders. I - // don't really want to implement this in the old solver so I haven't. - // - // We do still stall on infer vars though as otherwise a goal like: - // `ConstArgHasType(?x: usize, usize)` can succeed even though it might later - // get unified with some const that is not of type `usize`. let ct = self.infcx.shallow_resolve_const(ct); let ct_ty = match ct.kind() { - ty::ConstKind::Infer(ty::InferConst::Var(_)) => { + ty::ConstKind::Infer(_) => { return Ok(EvaluatedToAmbig); } ty::ConstKind::Error(_) => return Ok(EvaluatedToOk), - // THISPR - _ => todo!(), - // _ => ct.ty(), + ty::ConstKind::Value(ty, _) => ty, + ty::ConstKind::Unevaluated(uv) => { + self.tcx().type_of(uv.def).instantiate(self.tcx(), uv.args) + } + // FIXME(generic_const_exprs): See comment in `fulfill.rs` + ty::ConstKind::Expr(_) => return Ok(EvaluatedToOk), + ty::ConstKind::Placeholder(_) => { + bug!("placeholder const {:?} in old solver", ct) + } + ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct), + ty::ConstKind::Param(param_ct) => { + param_ct.find_ty_from_env(obligation.param_env) + } }; match self.infcx.at(&obligation.cause, obligation.param_env).eq( From 60a5bebbe591f228bf83f3c48f5f60fe87dedaad Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 3 Jun 2024 04:46:24 +0100 Subject: [PATCH 126/154] Add `Ty` to `mir::Const::Ty` --- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +-- .../rustc_codegen_ssa/src/mir/constant.rs | 2 +- .../src/check_consts/qualifs.rs | 4 +-- compiler/rustc_middle/src/mir/consts.rs | 35 ++++++++++++------- compiler/rustc_middle/src/mir/pretty.rs | 4 +-- compiler/rustc_middle/src/mir/visit.rs | 2 +- .../src/build/expr/as_constant.rs | 8 +++-- .../src/thir/pattern/const_to_pat.rs | 16 +++++---- .../rustc_mir_build/src/thir/pattern/mod.rs | 19 ++++++---- .../src/dataflow_const_prop.rs | 5 +-- compiler/rustc_mir_transform/src/gvn.rs | 12 +++++-- .../rustc_mir_transform/src/instsimplify.rs | 2 +- .../src/normalize_array_len.rs | 2 +- .../rustc_monomorphize/src/polymorphize.rs | 2 +- compiler/rustc_pattern_analysis/src/rustc.rs | 2 +- .../rustc_smir/src/rustc_internal/internal.rs | 4 ++- compiler/rustc_smir/src/rustc_smir/context.rs | 3 +- .../rustc_smir/src/rustc_smir/convert/mir.rs | 4 +-- .../rustc_smir/src/rustc_smir/convert/ty.rs | 2 +- 19 files changed, 81 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 291d2782c32c..fcfb297d50aa 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -346,7 +346,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } else { let tcx = self.tcx(); let maybe_uneval = match constant.const_ { - Const::Ty(ct) => match ct.kind() { + Const::Ty(_, ct) => match ct.kind() { ty::ConstKind::Unevaluated(_) => { bug!("should not encounter unevaluated Const::Ty here, got {:?}", ct) } @@ -1856,7 +1856,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Operand::Constant(constant) = op { let maybe_uneval = match constant.const_ { - Const::Val(..) | Const::Ty(_) => None, + Const::Val(..) | Const::Ty(_, _) => None, Const::Unevaluated(uv, _) => Some(uv), }; diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 81eb44132dd4..822f5c2c44a2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> Result>, ErrorHandled> { let uv = match self.monomorphize(constant.const_) { mir::Const::Unevaluated(uv, _) => uv.shrink(), - mir::Const::Ty(c) => match c.kind() { + mir::Const::Ty(_, c) => match c.kind() { // A constant that came from a const generic but was then used as an argument to old-style // simd_shuffle (passing as argument instead of as a generic param). rustc_type_ir::ConstKind::Value(_, valtree) => return Ok(Some(valtree)), diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 32500914f067..9fd7219499b2 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -357,7 +357,7 @@ where // Check the qualifs of the value of `const` items. let uneval = match constant.const_ { - Const::Ty(ct) + Const::Ty(_, ct) if matches!( ct.kind(), ty::ConstKind::Param(_) | ty::ConstKind::Error(_) | ty::ConstKind::Value(_, _) @@ -365,7 +365,7 @@ where { None } - Const::Ty(c) => { + Const::Ty(_, c) => { bug!("expected ConstKind::Param or ConstKind::Value here, found {:?}", c) } Const::Unevaluated(uv, _) => Some(uv), diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index b288347c6637..cc8979dd990e 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -204,7 +204,9 @@ pub enum Const<'tcx> { /// Any way of turning `ty::Const` into `ConstValue` should go through `valtree_to_const_val`; /// this ensures that we consistently produce "clean" values without data in the padding or /// anything like that. - Ty(ty::Const<'tcx>), + /// + /// FIXME(BoxyUwU): We should remove this `Ty` and look up the type for params via `ParamEnv` + Ty(Ty<'tcx>, ty::Const<'tcx>), /// An unevaluated mir constant which is not part of the type system. /// @@ -237,8 +239,15 @@ impl<'tcx> Const<'tcx> { #[inline(always)] pub fn ty(&self) -> Ty<'tcx> { match self { - // THISPR - Const::Ty(c) => todo!(), + Const::Ty(ty, ct) => { + match ct.kind() { + // Dont use the outter ty as on invalid code we can wind up with them not being the same. + // this then results in allowing const eval to add `1_i64 + 1_usize` in cases where the mir + // was originally `({N: usize} + 1_usize)` under `generic_const_exprs`. + ty::ConstKind::Value(ty, _) => ty, + _ => *ty, + } + } Const::Val(_, ty) | Const::Unevaluated(_, ty) => *ty, } } @@ -248,7 +257,7 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn is_required_const(&self) -> bool { match self { - Const::Ty(c) => match c.kind() { + Const::Ty(_, c) => match c.kind() { ty::ConstKind::Value(_, _) => false, // already a value, cannot error _ => true, }, @@ -260,7 +269,7 @@ impl<'tcx> Const<'tcx> { #[inline] pub fn try_to_scalar(self) -> Option { match self { - Const::Ty(c) => match c.kind() { + Const::Ty(_, c) => match c.kind() { ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => { // A valtree of a type where leaves directly represent the scalar const value. // Just checking whether it is a leaf is insufficient as e.g. references are leafs @@ -279,7 +288,7 @@ impl<'tcx> Const<'tcx> { // This is equivalent to `self.try_to_scalar()?.try_to_int().ok()`, but measurably faster. match self { Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x), - Const::Ty(c) => match c.kind() { + Const::Ty(_, c) => match c.kind() { ty::ConstKind::Value(ty, valtree) if ty.is_primitive() => { Some(valtree.unwrap_leaf()) } @@ -307,7 +316,7 @@ impl<'tcx> Const<'tcx> { span: Span, ) -> Result, ErrorHandled> { match self { - Const::Ty(c) => { + Const::Ty(_, c) => { // We want to consistently have a "clean" value for type system constants (i.e., no // data hidden in the padding), so we always go through a valtree here. let (ty, val) = c.eval(tcx, param_env, span)?; @@ -327,7 +336,7 @@ impl<'tcx> Const<'tcx> { match self.eval(tcx, param_env, DUMMY_SP) { Ok(val) => Self::Val(val, self.ty()), Err(ErrorHandled::Reported(guar, _span)) => { - Self::Ty(ty::Const::new_error(tcx, guar.into())) + Self::Ty(Ty::new_error(tcx, guar.into()), ty::Const::new_error(tcx, guar.into())) } Err(ErrorHandled::TooGeneric(_span)) => self, } @@ -339,7 +348,7 @@ impl<'tcx> Const<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Option { - if let Const::Ty(c) = self + if let Const::Ty(_, c) = self && let ty::ConstKind::Value(ty, val) = c.kind() && ty.is_primitive() { @@ -441,14 +450,14 @@ impl<'tcx> Const<'tcx> { Self::Val(val, ty) } - pub fn from_ty_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self { + pub fn from_ty_const(c: ty::Const<'tcx>, ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Self { match c.kind() { ty::ConstKind::Value(ty, valtree) => { // Make sure that if `c` is normalized, then the return value is normalized. let const_val = tcx.valtree_to_const_val((ty, valtree)); Self::Val(const_val, ty) } - _ => Self::Ty(c), + _ => Self::Ty(ty, c), } } @@ -460,7 +469,7 @@ impl<'tcx> Const<'tcx> { // - valtrees purposefully generate new allocations // - ConstValue::Slice also generate new allocations match self { - Const::Ty(c) => match c.kind() { + Const::Ty(_, c) => match c.kind() { ty::ConstKind::Param(..) => true, // A valtree may be a reference. Valtree references correspond to a // different allocation each time they are evaluated. Valtrees for primitive @@ -519,7 +528,7 @@ impl<'tcx> UnevaluatedConst<'tcx> { impl<'tcx> Display for Const<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { match *self { - Const::Ty(c) => pretty_print_const(c, fmt, true), + Const::Ty(_, c) => pretty_print_const(c, fmt, true), Const::Val(val, ty) => pretty_print_const_value(val, ty, fmt), // FIXME(valtrees): Correctly print mir constants. Const::Unevaluated(c, _ty) => { diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 845a8da3443a..c91b67297ee8 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -1313,7 +1313,7 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { }; let val = match const_ { - Const::Ty(ct) => match ct.kind() { + Const::Ty(_, ct) => match ct.kind() { ty::ConstKind::Param(p) => format!("ty::Param({p})"), ty::ConstKind::Unevaluated(uv) => { format!("ty::Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def), uv.args,) @@ -1417,7 +1417,7 @@ pub fn write_allocations<'tcx>( impl<'tcx> Visitor<'tcx> for CollectAllocIds { fn visit_constant(&mut self, c: &ConstOperand<'tcx>, _: Location) { match c.const_ { - Const::Ty(_) | Const::Unevaluated(..) => {} + Const::Ty(_, _) | Const::Unevaluated(..) => {} Const::Val(val, _) => { self.0.extend(alloc_ids_from_const_val(val)); } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 8901fd42d936..f553b417294a 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -895,7 +895,7 @@ macro_rules! make_mir_visitor { self.visit_span($(& $mutability)? *span); match const_ { - Const::Ty(ct) => self.visit_ty_const($(&$mutability)? *ct, location), + Const::Ty(_, ct) => self.visit_ty_const($(&$mutability)? *ct, location), Const::Val(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), Const::Unevaluated(_, ty) => self.visit_ty($(& $mutability)? *ty, TyContext::Location(location)), } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 5eed6995fff8..b783eba8c4e1 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::interpret::{Allocation, LitToConstError, LitToConstInput, use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{ - self, CanonicalUserType, CanonicalUserTypeAnnotation, TyCtxt, UserTypeAnnotationIndex, + self, CanonicalUserType, CanonicalUserTypeAnnotation, Ty, TyCtxt, UserTypeAnnotationIndex, }; use rustc_middle::{bug, span_bug}; use rustc_target::abi::Size; @@ -50,7 +50,9 @@ pub(crate) fn as_constant_inner<'tcx>( let const_ = match lit_to_mir_constant(tcx, LitToConstInput { lit: &lit.node, ty, neg }) { Ok(c) => c, - Err(LitToConstError::Reported(guar)) => Const::Ty(ty::Const::new_error(tcx, guar)), + Err(LitToConstError::Reported(guar)) => { + Const::Ty(Ty::new_error(tcx, guar), ty::Const::new_error(tcx, guar)) + } Err(LitToConstError::TypeError) => { bug!("encountered type error in `lit_to_mir_constant`") } @@ -82,7 +84,7 @@ pub(crate) fn as_constant_inner<'tcx>( } ExprKind::ConstParam { param, def_id: _ } => { let const_param = ty::Const::new_param(tcx, param); - let const_ = Const::Ty(const_param); + let const_ = Const::Ty(expr.ty, const_param); ConstOperand { user_ty: None, span, const_ } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index cc5aa8ea9cc7..36495101d3f4 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -101,9 +101,9 @@ impl<'tcx> ConstToPat<'tcx> { // level of indirection can be eliminated let have_valtree = - matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_, _))); + matches!(cv, mir::Const::Ty(_, c) if matches!(c.kind(), ty::ConstKind::Value(_, _))); let inlined_const_as_pat = match cv { - mir::Const::Ty(c) => match c.kind() { + mir::Const::Ty(_, c) => match c.kind() { ty::ConstKind::Param(_) | ty::ConstKind::Infer(_) | ty::ConstKind::Bound(_, _) @@ -336,9 +336,9 @@ impl<'tcx> ConstToPat<'tcx> { ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() { // `&str` is represented as a valtree, let's keep using this // optimization for now. - ty::Str => { - PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) } - } + ty::Str => PatKind::Constant { + value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)), + }, // All other references are converted into deref patterns and then recursively // convert the dereferenced constant to a pattern that is the sub-pattern of the // deref pattern. @@ -382,13 +382,15 @@ impl<'tcx> ConstToPat<'tcx> { self.saw_const_match_error.set(Some(e)); return Err(FallbackToOpaqueConst); } else { - PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) } + PatKind::Constant { + value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)), + } } } ty::Pat(..) | ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::RawPtr(..) => { // The raw pointers we see here have been "vetted" by valtree construction to be // just integers, so we simply allow them. - PatKind::Constant { value: mir::Const::Ty(ty::Const::new_value(tcx, cv, ty)) } + PatKind::Constant { value: mir::Const::Ty(ty, ty::Const::new_value(tcx, cv, ty)) } } ty::FnPtr(..) => { unreachable!( diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 33401cad631a..145a40ca3cd6 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -580,7 +580,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { .tcx .const_eval_global_id_for_typeck(param_env_reveal_all, cid, span) .map(|val| match val { - Some(valtree) => mir::Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), + Some(valtree) => mir::Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)), None => mir::Const::Val( self.tcx .const_eval_global_id(param_env_reveal_all, cid, span) @@ -659,7 +659,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; if let Some(lit_input) = lit_input { match tcx.at(expr.span).lit_to_const(lit_input) { - Ok(c) => return self.const_to_pat(Const::Ty(c), id, span).kind, + Ok(c) => return self.const_to_pat(Const::Ty(ty, c), id, span).kind, // If an error occurred, ignore that it's a literal // and leave reporting the error up to const eval of // the unevaluated constant below. @@ -681,8 +681,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // but something more principled, like a trait query checking whether this can be turned into a valtree. if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, span) { - let subpattern = - self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span); + let subpattern = self.const_to_pat( + Const::Ty(ty, ty::Const::new_value(self.tcx, valtree, ty)), + id, + span, + ); PatKind::InlineConstant { subpattern, def: def_id } } else { // If that fails, convert it to an opaque constant pattern. @@ -720,10 +723,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { _ => span_bug!(expr.span, "not a literal: {:?}", expr), }; - let lit_input = - LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg }; + let ct_ty = self.typeck_results.expr_ty(expr); + let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg }; match self.tcx.at(expr.span).lit_to_const(lit_input) { - Ok(constant) => self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span).kind, + Ok(constant) => { + self.const_to_pat(Const::Ty(ct_ty, constant), expr.hir_id, lit.span).kind + } Err(LitToConstError::Reported(e)) => PatKind::Error(e), Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index e88b727a21e9..a8caead46f2f 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -203,7 +203,8 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { && let operand_ty = operand.ty(self.local_decls, self.tcx) && let Some(operand_ty) = operand_ty.builtin_deref(true) && let ty::Array(_, len) = operand_ty.kind() - && let Some(len) = Const::Ty(*len).try_eval_scalar_int(self.tcx, self.param_env) + && let Some(len) = Const::Ty(self.tcx.types.usize, *len) + .try_eval_scalar_int(self.tcx, self.param_env) { state.insert_value_idx(target_len, FlatSet::Elem(len.into()), self.map()); } @@ -221,7 +222,7 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> { Rvalue::Len(place) => { let place_ty = place.ty(self.local_decls, self.tcx); if let ty::Array(_, len) = place_ty.ty.kind() { - Const::Ty(*len) + Const::Ty(self.tcx.types.usize, *len) .try_eval_scalar(self.tcx, self.param_env) .map_or(FlatSet::Top, FlatSet::Elem) } else if let [ProjectionElem::Deref] = place.projection[..] { diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index fadb5edefdfb..8194bd5c6cc7 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1108,7 +1108,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { // Trivial case: we are fetching a statically known length. let place_ty = place.ty(self.local_decls, self.tcx).ty; if let ty::Array(_, len) = place_ty.kind() { - return self.insert_constant(Const::from_ty_const(*len, self.tcx)); + return self.insert_constant(Const::from_ty_const( + *len, + self.tcx.types.usize, + self.tcx, + )); } let mut inner = self.simplify_place_value(place, location)?; @@ -1130,7 +1134,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { && let Some(to) = to.builtin_deref(true) && let ty::Slice(..) = to.kind() { - return self.insert_constant(Const::from_ty_const(*len, self.tcx)); + return self.insert_constant(Const::from_ty_const( + *len, + self.tcx.types.usize, + self.tcx, + )); } // Fallback: a symbolic `Len`. diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 40db3e38fd32..6806c517c17d 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -150,7 +150,7 @@ impl<'tcx> InstSimplifyContext<'tcx, '_> { return; } - let const_ = Const::from_ty_const(len, self.tcx); + let const_ = Const::from_ty_const(len, self.tcx.types.usize, self.tcx); let constant = ConstOperand { span: source_info.span, const_, user_ty: None }; *rvalue = Rvalue::Use(Operand::Constant(Box::new(constant))); } diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs index 2070895c9002..d5e727066614 100644 --- a/compiler/rustc_mir_transform/src/normalize_array_len.rs +++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs @@ -95,7 +95,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> { *rvalue = Rvalue::Use(Operand::Constant(Box::new(ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, - const_: Const::from_ty_const(len, self.tcx), + const_: Const::from_ty_const(len, self.tcx.types.usize, self.tcx), }))); } self.super_rvalue(rvalue, loc); diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index dc13766d1451..a3ca9e9f9cfe 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -263,7 +263,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> { fn visit_constant(&mut self, ct: &mir::ConstOperand<'tcx>, location: Location) { match ct.const_ { - mir::Const::Ty(c) => { + mir::Const::Ty(_, c) => { c.visit_with(self); } mir::Const::Unevaluated(mir::UnevaluatedConst { def, args: _, promoted }, ty) => { diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index ff68dd81beaf..81c5f3552319 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -737,7 +737,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { // this). We show this to the user as `usize::MAX..` which is slightly incorrect but // probably clear enough. let c = ty.numeric_max_val(cx.tcx).unwrap(); - let value = mir::Const::from_ty_const(c, cx.tcx); + let value = mir::Const::from_ty_const(c, ty.0, cx.tcx); lo = PatRangeBoundary::Finite(value); } let hi = if let Some(hi) = range.hi.minus_one() { diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index edfd48ed43b1..c33a52f4a7a8 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -251,7 +251,9 @@ impl RustcInternal for MirConst { fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> { let constant = tables.mir_consts[self.id]; match constant { - rustc_middle::mir::Const::Ty(ty) => rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap()), + rustc_middle::mir::Const::Ty(ty, ct) => { + rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap(), tcx.lift(ct).unwrap()) + } rustc_middle::mir::Const::Unevaluated(uneval, ty) => { rustc_middle::mir::Const::Unevaluated( tcx.lift(uneval).unwrap(), diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 9822ed79e2bd..8b09c5aef2f9 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -398,7 +398,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> { ))); } - Ok(mir::Const::Ty(ty::Const::zero_sized(tables.tcx, ty_internal)).stable(&mut *tables)) + Ok(mir::Const::Ty(ty_internal, ty::Const::zero_sized(tables.tcx, ty_internal)) + .stable(&mut *tables)) } fn new_const_str(&self, value: &str) -> MirConst { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs index 1c87293209c6..bcacf54baf36 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs @@ -729,9 +729,9 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { let id = tables.intern_mir_const(tables.tcx.lift(*self).unwrap()); match *self { - mir::Const::Ty(c) => MirConst::new( + mir::Const::Ty(ty, c) => MirConst::new( stable_mir::ty::ConstantKind::Ty(c.stable(tables)), - c.ty().stable(tables), + ty.stable(tables), id, ), mir::Const::Unevaluated(unev_const, ty) => { diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index f26439d42767..73bc87dc9abf 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -447,7 +447,7 @@ pub fn mir_const_from_ty_const<'tcx>( ty::ExprCt(_) => unimplemented!(), }; let stable_ty = tables.intern_ty(ty); - let id = tables.intern_mir_const(mir::Const::Ty(ty_const)); + let id = tables.intern_mir_const(mir::Const::Ty(ty, ty_const)); stable_mir::ty::MirConst::new(kind, stable_ty, id) } From 432c11feb6ddfffe6d1d111624ac86386b2fe751 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jun 2024 07:01:40 +0100 Subject: [PATCH 127/154] Remove `Type` from rustdoc `Const` --- src/librustdoc/clean/inline.rs | 28 ++++++++-------- src/librustdoc/clean/mod.rs | 32 ++++++------------- src/librustdoc/clean/types.rs | 8 ++--- src/librustdoc/clean/utils.rs | 4 +-- src/librustdoc/fold.rs | 2 +- src/librustdoc/html/render/print_item.rs | 17 +++++++--- src/librustdoc/json/conversions.rs | 7 ++-- src/librustdoc/json/mod.rs | 2 +- .../passes/check_doc_test_visibility.rs | 2 +- src/librustdoc/visit.rs | 2 +- src/rustdoc-json-types/lib.rs | 11 ++++--- src/tools/jsondoclint/src/item_kind.rs | 2 +- src/tools/jsondoclint/src/validator.rs | 9 ++++-- 13 files changed, 64 insertions(+), 62 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index c7366ce1a68c..0024e246ef00 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -130,7 +130,10 @@ pub(crate) fn try_inline( } Res::Def(DefKind::Const, did) => { record_extern_fqn(cx, did, ItemType::Constant); - cx.with_param_env(did, |cx| clean::ConstantItem(build_const(cx, did))) + cx.with_param_env(did, |cx| { + let (generics, ty, ct) = build_const_item(cx, did); + clean::ConstantItem(generics, Box::new(ty), ct) + }) } Res::Def(DefKind::Macro(kind), did) => { let is_doc_hidden = cx.tcx.is_doc_hidden(did) @@ -717,21 +720,20 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String { } } -fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant { +fn build_const_item( + cx: &mut DocContext<'_>, + def_id: DefId, +) -> (clean::Generics, clean::Type, clean::Constant) { let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id)); clean::simplify::move_bounds_to_generic_parameters(&mut generics); - - clean::Constant { - type_: Box::new(clean_middle_ty( - ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()), - cx, - Some(def_id), - None, - )), - generics, - kind: clean::ConstantKind::Extern { def_id }, - } + let ty = clean_middle_ty( + ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()), + cx, + None, + None, + ); + (generics, ty, clean::Constant { kind: clean::ConstantKind::Extern { def_id } }) } fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 839bfdf44af1..d4e28927728f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -283,31 +283,17 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> pub(crate) fn clean_const<'tcx>( constant: &hir::ConstArg<'_>, - cx: &mut DocContext<'tcx>, + _cx: &mut DocContext<'tcx>, ) -> Constant { - let def_id = cx.tcx.hir().body_owner_def_id(constant.value.body).to_def_id(); - Constant { - type_: Box::new(clean_middle_ty( - ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity()), - cx, - Some(def_id), - None, - )), - generics: Generics::default(), - kind: ConstantKind::Anonymous { body: constant.value.body }, - } + Constant { kind: ConstantKind::Anonymous { body: constant.value.body } } } pub(crate) fn clean_middle_const<'tcx>( constant: ty::Binder<'tcx, ty::Const<'tcx>>, - cx: &mut DocContext<'tcx>, + _cx: &mut DocContext<'tcx>, ) -> Constant { // FIXME: instead of storing the stringified expression, store `self` directly instead. - Constant { - type_: Box::new(clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None)), - generics: Generics::default(), - kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() }, - } + Constant { kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() } } } pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option { @@ -2738,11 +2724,11 @@ fn clean_maybe_renamed_item<'tcx>( ItemKind::Static(ty, mutability, body_id) => { StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) }) } - ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant { - type_: Box::new(clean_ty(ty, cx)), - generics: clean_generics(generics, cx), - kind: ConstantKind::Local { body: body_id, def_id }, - }), + ItemKind::Const(ty, generics, body_id) => ConstantItem( + clean_generics(generics, cx), + Box::new(clean_ty(ty, cx)), + Constant { kind: ConstantKind::Local { body: body_id, def_id } }, + ), ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), generics: clean_generics(ty.generics, cx), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index b387809cc717..28d3d5644432 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -830,7 +830,6 @@ pub(crate) enum ItemKind { TypeAliasItem(Box), OpaqueTyItem(OpaqueTy), StaticItem(Static), - ConstantItem(Constant), TraitItem(Box), TraitAliasItem(TraitAlias), ImplItem(Box), @@ -853,6 +852,7 @@ pub(crate) enum ItemKind { PrimitiveItem(PrimitiveType), /// A required associated constant in a trait declaration. TyAssocConstItem(Generics, Box), + ConstantItem(Generics, Box, Constant), /// An associated constant in a trait impl or a provided one in a trait declaration. AssocConstItem(Generics, Box, ConstantKind), /// A required associated type in a trait declaration. @@ -888,7 +888,7 @@ impl ItemKind { | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) - | ConstantItem(_) + | ConstantItem(_, _, _) | TraitAliasItem(_) | TyMethodItem(_) | MethodItem(_, _) @@ -922,7 +922,7 @@ impl ItemKind { | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) - | ConstantItem(_) + | ConstantItem(_, _, _) | TraitAliasItem(_) | ForeignFunctionItem(_) | ForeignStaticItem(_) @@ -2364,8 +2364,6 @@ pub(crate) struct Static { #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub(crate) struct Constant { - pub(crate) type_: Box, - pub(crate) generics: Generics, pub(crate) kind: ConstantKind, } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 24a01414c70c..7fc3d4508d7d 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -353,8 +353,8 @@ pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { s } // array lengths are obviously usize - ty::ConstKind::Value(ty::ValTree::Leaf(scalar)) - if *n.ty().kind() == ty::Uint(ty::UintTy::Usize) => + ty::ConstKind::Value(ty, ty::ValTree::Leaf(scalar)) + if *ty.kind() == ty::Uint(ty::UintTy::Usize) => { scalar.to_string() } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index cf11e2d7899e..c85b955d4c57 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -79,7 +79,7 @@ pub(crate) trait DocFolder: Sized { | FunctionItem(_) | OpaqueTyItem(_) | StaticItem(_) - | ConstantItem(_) + | ConstantItem(_, _, _) | TraitAliasItem(_) | TyMethodItem(_) | MethodItem(_, _) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index c5b88c7a951f..e1f79254b248 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -266,7 +266,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf clean::ProcMacroItem(ref m) => item_proc_macro(buf, cx, item, m), clean::PrimitiveItem(_) => item_primitive(buf, cx, item), clean::StaticItem(ref i) | clean::ForeignStaticItem(ref i) => item_static(buf, cx, item, i), - clean::ConstantItem(ref c) => item_constant(buf, cx, item, c), + clean::ConstantItem(generics, ty, c) => item_constant(buf, cx, item, generics, ty, c), clean::ForeignTypeItem => item_foreign_type(buf, cx, item), clean::KeywordItem => item_keyword(buf, cx, item), clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e), @@ -1844,7 +1844,14 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite } } -fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &clean::Constant) { +fn item_constant( + w: &mut Buffer, + cx: &mut Context<'_>, + it: &clean::Item, + generics: &clean::Generics, + ty: &clean::Type, + c: &clean::Constant, +) { wrap_item(w, |w| { let tcx = cx.tcx(); render_attributes_in_code(w, it, cx); @@ -1854,9 +1861,9 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle "{vis}const {name}{generics}: {typ}{where_clause}", vis = visibility_print_with_space(it, cx), name = it.name.unwrap(), - generics = c.generics.print(cx), - typ = c.type_.print(cx), - where_clause = print_where_clause(&c.generics, cx, 0, Ending::NoNewline), + generics = generics.print(cx), + typ = ty.print(cx), + where_clause = print_where_clause(&generics, cx, 0, Ending::NoNewline), ); // FIXME: The code below now prints diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 7e6a19aa52e0..afafb4fbe4b0 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -183,7 +183,7 @@ impl FromWithTcx for Constant { let expr = constant.expr(tcx); let value = constant.value(tcx); let is_literal = constant.is_literal(tcx); - Constant { type_: (*constant.type_).into_tcx(tcx), expr, value, is_literal } + Constant { expr, value, is_literal } } } @@ -321,7 +321,10 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ForeignTypeItem => ItemEnum::ForeignType, TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)), - ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)), + // FIXME(generic_const_items): Add support for generic free consts + ConstantItem(_generics, t, c) => { + ItemEnum::Constant { type_: (*t).into_tcx(tcx), const_: c.into_tcx(tcx) } + } MacroItem(m) => ItemEnum::Macro(m.source), ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)), PrimitiveItem(p) => { diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index c1d90020e87e..0ef24818515c 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -186,7 +186,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { | types::ItemEnum::Impl(_) | types::ItemEnum::TypeAlias(_) | types::ItemEnum::OpaqueTy(_) - | types::ItemEnum::Constant(_) + | types::ItemEnum::Constant { .. } | types::ItemEnum::Static(_) | types::ItemEnum::ForeignType | types::ItemEnum::Macro(_) diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 02589a137b41..d53eac0bccb1 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -62,7 +62,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - | clean::AssocTypeItem(..) | clean::TypeAliasItem(_) | clean::StaticItem(_) - | clean::ConstantItem(_) + | clean::ConstantItem(_, _, _) | clean::ExternCrateItem { .. } | clean::ImportItem(_) | clean::PrimitiveItem(_) diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index 01e6cb4b93bf..0660037e4d83 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -28,7 +28,7 @@ pub(crate) trait DocVisitor: Sized { | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) - | ConstantItem(_) + | ConstantItem(_, _, _) | TraitAliasItem(_) | TyMethodItem(_) | MethodItem(_, _) diff --git a/src/rustdoc-json-types/lib.rs b/src/rustdoc-json-types/lib.rs index 1c5a6dcfb1f2..68030493e9cf 100644 --- a/src/rustdoc-json-types/lib.rs +++ b/src/rustdoc-json-types/lib.rs @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; /// rustdoc format-version. -pub const FORMAT_VERSION: u32 = 29; +pub const FORMAT_VERSION: u32 = 30; /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information /// about the language items in the local crate, as well as info about external items to allow @@ -167,8 +167,6 @@ pub enum GenericArg { #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Constant { - #[serde(rename = "type")] - pub type_: Type, pub expr: String, pub value: Option, pub is_literal: bool, @@ -256,7 +254,12 @@ pub enum ItemEnum { TypeAlias(TypeAlias), OpaqueTy(OpaqueTy), - Constant(Constant), + Constant { + #[serde(rename = "type")] + type_: Type, + #[serde(rename = "const")] + const_: Constant, + }, Static(Static), diff --git a/src/tools/jsondoclint/src/item_kind.rs b/src/tools/jsondoclint/src/item_kind.rs index 9bd04e11cb39..525de03bbce3 100644 --- a/src/tools/jsondoclint/src/item_kind.rs +++ b/src/tools/jsondoclint/src/item_kind.rs @@ -150,7 +150,7 @@ impl Kind { ItemEnum::Impl(_) => Impl, ItemEnum::TypeAlias(_) => TypeAlias, ItemEnum::OpaqueTy(_) => OpaqueTy, - ItemEnum::Constant(_) => Constant, + ItemEnum::Constant { .. } => Constant, ItemEnum::Static(_) => Static, ItemEnum::Macro(_) => Macro, ItemEnum::ProcMacro(_) => ProcMacro, diff --git a/src/tools/jsondoclint/src/validator.rs b/src/tools/jsondoclint/src/validator.rs index 904c2b614f3f..5e35ce242fe4 100644 --- a/src/tools/jsondoclint/src/validator.rs +++ b/src/tools/jsondoclint/src/validator.rs @@ -101,7 +101,10 @@ impl<'a> Validator<'a> { ItemEnum::Impl(x) => self.check_impl(x, id), ItemEnum::TypeAlias(x) => self.check_type_alias(x), ItemEnum::OpaqueTy(x) => self.check_opaque_ty(x), - ItemEnum::Constant(x) => self.check_constant(x), + ItemEnum::Constant { type_, const_ } => { + self.check_type(type_); + self.check_constant(const_); + } ItemEnum::Static(x) => self.check_static(x), ItemEnum::ForeignType => {} // nop ItemEnum::Macro(x) => self.check_macro(x), @@ -231,8 +234,8 @@ impl<'a> Validator<'a> { self.check_generics(&x.generics); } - fn check_constant(&mut self, x: &'a Constant) { - self.check_type(&x.type_); + fn check_constant(&mut self, _x: &'a Constant) { + // nop } fn check_static(&mut self, x: &'a Static) { From a454da3b1c266e8121130de26864c99010436129 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jun 2024 07:01:58 +0100 Subject: [PATCH 128/154] Misc fixes to cranelift/clippy/miri --- compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs | 1 + src/tools/clippy/clippy_lints/src/large_const_arrays.rs | 2 +- src/tools/clippy/clippy_lints/src/large_stack_arrays.rs | 2 +- src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs | 4 ++-- src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 4 ++-- src/tools/miri/src/intrinsics/simd.rs | 1 + 7 files changed, 9 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index b17f191ce267..65eeaf156d84 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -133,6 +133,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>( .expect_const() .eval(fx.tcx, ty::ParamEnv::reveal_all(), span) .unwrap() + .1 .unwrap_branch(); assert_eq!(x.layout(), y.layout()); diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index b561054b5824..77d05020c828 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeConstArrays { && generics.params.is_empty() && !generics.has_where_clause_predicates && let ty = cx.tcx.type_of(item.owner_id).instantiate_identity() && let ty::Array(element_type, cst) = ty.kind() - && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind() + && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind() && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx) && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && self.maximum_allowed_size < u128::from(element_count) * u128::from(element_size) diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 208d1bb6e68a..f0f3f53647b9 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -64,7 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackArrays { if let ExprKind::Repeat(_, _) | ExprKind::Array(_) = expr.kind && !self.is_from_vec_macro(cx, expr.span) && let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind() - && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind() + && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind() && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx) && let Ok(element_size) = cx.layout_of(*element_type).map(|l| l.size.bytes()) && !cx.tcx.hir().parent_iter(expr.hir_id).any(|(_, node)| { diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs index 8199366d175f..45b375dbe3d7 100644 --- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs @@ -37,14 +37,14 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>) Some(lhs) => constant(cx, cx.typeck_results(), lhs)?, None => { let min_val_const = ty.numeric_min_val(cx.tcx)?; - mir_to_const(cx, mir::Const::from_ty_const(min_val_const, cx.tcx))? + mir_to_const(cx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))? }, }; let rhs_const = match rhs { Some(rhs) => constant(cx, cx.typeck_results(), rhs)?, None => { let max_val_const = ty.numeric_max_val(cx.tcx)?; - mir_to_const(cx, mir::Const::from_ty_const(max_val_const, cx.tcx))? + mir_to_const(cx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))? }, }; let lhs_val = lhs_const.int_value(cx, ty)?; diff --git a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs index 143fecdd237d..848b49130dc2 100644 --- a/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/zero_repeat_side_effects.rs @@ -55,7 +55,7 @@ impl LateLintPass<'_> for ZeroRepeatSideEffects { inner_check(cx, expr, inner_expr, true); } else if let ExprKind::Repeat(inner_expr, _) = expr.kind && let ty::Array(_, cst) = cx.typeck_results().expr_ty(expr).kind() - && let ConstKind::Value(ty::ValTree::Leaf(element_count)) = cst.kind() + && let ConstKind::Value(_, ty::ValTree::Leaf(element_count)) = cst.kind() && let Ok(element_count) = element_count.try_to_target_usize(cx.tcx) && element_count == 0 { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index b10830b24e1f..1147dce6215f 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1534,7 +1534,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) && let Some(min_val) = bnd_ty.numeric_min_val(cx.tcx) - && let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, cx.tcx)) + && let Some(min_const) = mir_to_const(cx, Const::from_ty_const(min_val, bnd_ty, cx.tcx)) && let Some(start_const) = constant(cx, cx.typeck_results(), start) { start_const == min_const @@ -1547,7 +1547,7 @@ pub fn is_range_full(cx: &LateContext<'_>, expr: &Expr<'_>, container_path: Opti if let rustc_ty::Adt(_, subst) = ty.kind() && let bnd_ty = subst.type_at(0) && let Some(max_val) = bnd_ty.numeric_max_val(cx.tcx) - && let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, cx.tcx)) + && let Some(max_const) = mir_to_const(cx, Const::from_ty_const(max_val, bnd_ty, cx.tcx)) && let Some(end_const) = constant(cx, cx.typeck_results(), end) { end_const == max_const diff --git a/src/tools/miri/src/intrinsics/simd.rs b/src/tools/miri/src/intrinsics/simd.rs index ed0c30e2a11a..8ba4964ff896 100644 --- a/src/tools/miri/src/intrinsics/simd.rs +++ b/src/tools/miri/src/intrinsics/simd.rs @@ -590,6 +590,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { .expect_const() .eval(*this.tcx, this.param_env(), this.tcx.span) .unwrap() + .1 .unwrap_branch(); let index_len = index.len(); From 56092a345b8f056c86d0878d45b5b07be64a8cf2 Mon Sep 17 00:00:00 2001 From: Boxy Date: Mon, 3 Jun 2024 03:38:09 +0100 Subject: [PATCH 129/154] Misc fixes (pattern type lowering, cfi, pretty printing) --- .../src/hir_ty_lowering/mod.rs | 17 +++++----- .../src/hir_ty_lowering/object_safety.rs | 6 ++-- compiler/rustc_middle/src/ty/print/pretty.rs | 19 +---------- .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 34 +++++++++++++------ 4 files changed, 36 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 0dee904c5a2d..7ec64f1feda2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2160,17 +2160,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } _ => (expr, None), }; - let c = match &expr.kind { + let (c, c_ty) = match &expr.kind { hir::ExprKind::Lit(lit) => { let lit_input = LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() }; - match tcx.lit_to_const(lit_input) { + let ct = match tcx.lit_to_const(lit_input) { Ok(c) => c, Err(LitToConstError::Reported(err)) => { ty::Const::new_error(tcx, err) } Err(LitToConstError::TypeError) => todo!(), - } + }; + (ct, ty) } hir::ExprKind::Path(hir::QPath::Resolved( @@ -2188,20 +2189,20 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .type_of(def_id) .no_bound_vars() .expect("const parameter types cannot be generic"); - self.lower_const_param(expr.hir_id) + let ct = self.lower_const_param(expr.hir_id); + (ct, ty) } _ => { let err = tcx .dcx() .emit_err(crate::errors::NonConstRange { span: expr.span }); - ty::Const::new_error(tcx, err) + (ty::Const::new_error(tcx, err), Ty::new_error(tcx, err)) } }; - // THISPR - self.record_ty(expr.hir_id, todo!(), expr.span); + self.record_ty(expr.hir_id, c_ty, expr.span); if let Some((id, span)) = neg { - self.record_ty(id, todo!(), span); + self.record_ty(id, c_ty, span); } c }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index ed1749ea14f0..34924f09d09e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -143,10 +143,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // `trait_object_dummy_self`, so check for that. let references_self = match pred.skip_binder().term.unpack() { ty::TermKind::Ty(ty) => ty.walk().any(|arg| arg == dummy_self.into()), - ty::TermKind::Const(c) => { - // THISPR - false - } + // FIXME(associated_const_equality): We should walk the const instead of not doing anything + ty::TermKind::Const(_) => false, }; // If the projection output contains `Self`, force the user to diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ef391be889cf..3cfebaa6b57e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1459,23 +1459,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { return Ok(()); } - macro_rules! print_underscore { - () => {{ - if print_ty { - self.typed_value( - |this| { - write!(this, "_")?; - Ok(()) - }, - |this| this.print_type(todo!()), - ": ", - )?; - } else { - write!(self, "_")?; - } - }}; - } - match ct.kind() { ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args }) => { match self.tcx().def_kind(def) { @@ -1508,7 +1491,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { ty::InferConst::Var(ct_vid) if let Some(name) = self.const_infer_name(ct_vid) => { p!(write("{}", name)) } - _ => print_underscore!(), + _ => write!(self, "_")?, }, ty::ConstKind::Param(ParamConst { name, .. }) => p!(write("{}", name)), ty::ConstKind::Value(ty, value) => { diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index bd8e52229fa7..0be8b5d57187 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -68,6 +68,8 @@ fn compress<'tcx>( fn encode_args<'tcx>( tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>, + for_def: DefId, + has_erased_self: bool, dict: &mut FxHashMap, usize>, options: EncodeTyOptions, ) -> String { @@ -76,7 +78,8 @@ fn encode_args<'tcx>( let args: Vec> = args.iter().collect(); if !args.is_empty() { s.push('I'); - for arg in args { + let def_generics = tcx.generics_of(for_def); + for (n, arg) in args.iter().enumerate() { match arg.unpack() { GenericArgKind::Lifetime(region) => { s.push_str(&encode_region(region, dict)); @@ -85,7 +88,10 @@ fn encode_args<'tcx>( s.push_str(&encode_ty(tcx, ty, dict, options)); } GenericArgKind::Const(c) => { - s.push_str(&encode_const(tcx, c, dict, options)); + let n = n + (has_erased_self as usize); + let ct_ty = + tcx.type_of(def_generics.param_at(n, tcx).def_id).instantiate_identity(); + s.push_str(&encode_const(tcx, c, ct_ty, dict, options)); } } } @@ -99,6 +105,7 @@ fn encode_args<'tcx>( fn encode_const<'tcx>( tcx: TyCtxt<'tcx>, c: Const<'tcx>, + ct_ty: Ty<'tcx>, dict: &mut FxHashMap, usize>, options: EncodeTyOptions, ) -> String { @@ -111,8 +118,7 @@ fn encode_const<'tcx>( // LE as literal argument // Element type - // THISPR - s.push_str(&encode_ty(tcx, todo!(), dict, options)); + s.push_str(&encode_ty(tcx, ct_ty, dict, options)); } // Literal arguments @@ -232,15 +238,21 @@ fn encode_predicate<'tcx>( ty::ExistentialPredicate::Trait(trait_ref) => { let name = encode_ty_name(tcx, trait_ref.def_id); let _ = write!(s, "u{}{}", name.len(), &name); - s.push_str(&encode_args(tcx, trait_ref.args, dict, options)); + s.push_str(&encode_args(tcx, trait_ref.args, trait_ref.def_id, true, dict, options)); } ty::ExistentialPredicate::Projection(projection) => { let name = encode_ty_name(tcx, projection.def_id); let _ = write!(s, "u{}{}", name.len(), &name); - s.push_str(&encode_args(tcx, projection.args, dict, options)); + s.push_str(&encode_args(tcx, projection.args, projection.def_id, true, dict, options)); match projection.term.unpack() { TermKind::Ty(ty) => s.push_str(&encode_ty(tcx, ty, dict, options)), - TermKind::Const(c) => s.push_str(&encode_const(tcx, c, dict, options)), + TermKind::Const(c) => s.push_str(&encode_const( + tcx, + c, + tcx.type_of(projection.def_id).instantiate(tcx, projection.args), + dict, + options, + )), } } ty::ExistentialPredicate::AutoTrait(def_id) => { @@ -486,7 +498,7 @@ pub fn encode_ty<'tcx>( // , as vendor extended type. let name = encode_ty_name(tcx, def_id); let _ = write!(s, "u{}{}", name.len(), &name); - s.push_str(&encode_args(tcx, args, dict, options)); + s.push_str(&encode_args(tcx, args, def_id, false, dict, options)); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); } typeid.push_str(&s); @@ -530,7 +542,7 @@ pub fn encode_ty<'tcx>( let mut s = String::new(); let name = encode_ty_name(tcx, *def_id); let _ = write!(s, "u{}{}", name.len(), &name); - s.push_str(&encode_args(tcx, args, dict, options)); + s.push_str(&encode_args(tcx, args, *def_id, false, dict, options)); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); } @@ -542,7 +554,7 @@ pub fn encode_ty<'tcx>( let name = encode_ty_name(tcx, *def_id); let _ = write!(s, "u{}{}", name.len(), &name); let parent_args = tcx.mk_args(args.as_coroutine_closure().parent_args()); - s.push_str(&encode_args(tcx, parent_args, dict, options)); + s.push_str(&encode_args(tcx, parent_args, *def_id, false, dict, options)); compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); typeid.push_str(&s); } @@ -557,6 +569,8 @@ pub fn encode_ty<'tcx>( s.push_str(&encode_args( tcx, tcx.mk_args(args.as_coroutine().parent_args()), + *def_id, + false, dict, options, )); From 7fa98d0c01050ee8c39bfc644d1414f5a21a1f21 Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jun 2024 18:50:14 +0100 Subject: [PATCH 130/154] ty::Expr reviews --- compiler/rustc_middle/src/ty/consts/kind.rs | 8 +++++--- compiler/rustc_middle/src/ty/relate.rs | 8 +++++--- compiler/rustc_ty_utils/src/consts.rs | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 5f29acf5ed27..bf834ef76074 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -104,10 +104,12 @@ impl<'tcx> Expr<'tcx> { tcx: TyCtxt<'tcx>, func_ty: Ty<'tcx>, func_expr: Const<'tcx>, - arguments: impl Iterator>, + arguments: impl IntoIterator>, ) -> Self { let args = tcx.mk_args_from_iter::<_, ty::GenericArg<'tcx>>( - [func_ty.into(), func_expr.into()].into_iter().chain(arguments.map(|ct| ct.into())), + [func_ty.into(), func_expr.into()] + .into_iter() + .chain(arguments.into_iter().map(|ct| ct.into())), ); Self { kind: ExprKind::FunctionCall, args } @@ -155,7 +157,7 @@ impl<'tcx> Expr<'tcx> { Self { kind, args } } - pub fn args(&self) -> ty::GenericArgsRef<'tcx> { + pub fn args(self) -> ty::GenericArgsRef<'tcx> { self.args } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index c0ed5fad2475..e24e64b23013 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -652,9 +652,11 @@ pub fn structurally_relate_consts<'tcx, R: TypeRelation<'tcx>>( // and is the better alternative to waiting until `generic_const_exprs` can // be stabilized. (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { - let a_ty = tcx.type_of(au.def).instantiate(tcx, au.args); - let b_ty = tcx.type_of(bu.def).instantiate(tcx, bu.args); - assert_eq!(a_ty, b_ty); + if cfg!(debug_assertions) { + let a_ty = tcx.type_of(au.def).instantiate(tcx, au.args); + let b_ty = tcx.type_of(bu.def).instantiate(tcx, bu.args); + assert_eq!(a_ty, b_ty); + } let args = relation.relate_with_variance( ty::Variance::Invariant, diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index f5c66e48ea64..1aec40e95f69 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -149,7 +149,7 @@ fn recurse_build<'tcx>( for &id in args.iter() { new_args.push(recurse_build(tcx, body, id, root_span)?); } - ty::Const::new_expr(tcx, Expr::new_call(tcx, fun_ty, fun, new_args.into_iter())) + ty::Const::new_expr(tcx, Expr::new_call(tcx, fun_ty, fun, new_args)) } &ExprKind::Binary { op, lhs, rhs } if check_binop(op) => { let lhs_ty = body.exprs[lhs].ty; From f74119a2e4a5c040c054ebee1ae2ccda828fd21f Mon Sep 17 00:00:00 2001 From: Boxy Date: Tue, 4 Jun 2024 09:10:08 +0100 Subject: [PATCH 131/154] Bless tests and handle tests/crashes --- tests/crashes/122908.rs | 4 - tests/crashes/125556.rs | 14 --- tests/debuginfo/function-names.rs | 4 +- .../issue_99325.main.built.after.32bit.mir | 2 +- .../issue_99325.main.built.after.64bit.mir | 2 +- ..._non-universal_region_substs_ice-111911.rs | 3 +- ...-universal_region_substs_ice-111911.stderr | 16 --- ...ram-type-depends-on-type-param.full.stderr | 14 ++- ...aram-type-depends-on-type-param.min.stderr | 14 ++- .../const-param-type-depends-on-type-param.rs | 1 + .../generic_const_exprs/error_in_ty.rs | 21 ++++ .../generic_const_exprs/error_in_ty.stderr | 45 +++++++ .../generic_const_exprs/eval-privacy.rs | 5 +- .../generic_const_exprs/eval-privacy.stderr | 4 +- .../issues/issue-71381.full.stderr | 18 ++- .../issues/issue-71381.min.stderr | 20 +++- tests/ui/const-generics/issues/issue-71381.rs | 1 + .../const-generics/not_wf_param_in_rpitit.rs | 14 +++ .../not_wf_param_in_rpitit.stderr | 113 ++++++++++++++++++ tests/ui/const-generics/transmute-fail.stderr | 2 +- tests/ui/const-generics/type_not_in_scope.rs | 3 +- .../const-generics/type_not_in_scope.stderr | 14 ++- tests/ui/consts/issue-103790.rs | 2 +- tests/ui/consts/issue-103790.stderr | 33 ++--- tests/ui/privacy/where-priv-type.rs | 45 +++---- tests/ui/privacy/where-priv-type.stderr | 26 ++-- .../effects/spec-effectvar-ice.rs | 6 +- .../effects/spec-effectvar-ice.stderr | 32 ++--- .../const_generic_type.infer.stderr | 2 +- .../const_generic_type.no_infer.stderr | 13 +- .../const_generic_type.rs | 4 +- ...ce-hir-wf-check-anon-const-issue-122199.rs | 27 ++--- ...ir-wf-check-anon-const-issue-122199.stderr | 44 +++---- ...ce-hir-wf-check-anon-const-issue-122989.rs | 16 +-- ...ir-wf-check-anon-const-issue-122989.stderr | 93 ++------------ 35 files changed, 389 insertions(+), 288 deletions(-) delete mode 100644 tests/crashes/122908.rs delete mode 100644 tests/crashes/125556.rs delete mode 100644 tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr create mode 100644 tests/ui/const-generics/generic_const_exprs/error_in_ty.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr create mode 100644 tests/ui/const-generics/not_wf_param_in_rpitit.rs create mode 100644 tests/ui/const-generics/not_wf_param_in_rpitit.stderr diff --git a/tests/crashes/122908.rs b/tests/crashes/122908.rs deleted file mode 100644 index c9da1bc18791..000000000000 --- a/tests/crashes/122908.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #122908 -trait Trait { - async fn handle(slf: &F) {} -} diff --git a/tests/crashes/125556.rs b/tests/crashes/125556.rs deleted file mode 100644 index f2e2a991b11e..000000000000 --- a/tests/crashes/125556.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ known-bug: rust-lang/rust#125556 -//@ compile-flags: -Znext-solver=coherence - -#![feature(generic_const_exprs)] - -pub struct A {} - -impl A<2> { - pub const fn B() {} -} - -impl A<2> { - pub const fn B() {} -} diff --git a/tests/debuginfo/function-names.rs b/tests/debuginfo/function-names.rs index 2b0c2593676b..96456d4c6b0b 100644 --- a/tests/debuginfo/function-names.rs +++ b/tests/debuginfo/function-names.rs @@ -37,7 +37,7 @@ // Const generic parameter // gdb-command:info functions -q function_names::const_generic_fn.* // gdb-check:[...]static fn function_names::const_generic_fn_bool(); -// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#ad91263f6d2dd96e}>(); +// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#[...]}>(); // gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>(); // gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>(); @@ -76,7 +76,7 @@ // Const generic parameter // cdb-command:x a!function_names::const_generic_fn* // cdb-check:[...] a!function_names::const_generic_fn_bool (void) -// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) +// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) // cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void) // cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void) diff --git a/tests/mir-opt/issue_99325.main.built.after.32bit.mir b/tests/mir-opt/issue_99325.main.built.after.32bit.mir index 0b0bac73e9f4..b7a054b5d540 100644 --- a/tests/mir-opt/issue_99325.main.built.after.32bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.32bit.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/mir-opt/issue_99325.main.built.after.64bit.mir b/tests/mir-opt/issue_99325.main.built.after.64bit.mir index 0b0bac73e9f4..b7a054b5d540 100644 --- a/tests/mir-opt/issue_99325.main.built.after.64bit.mir +++ b/tests/mir-opt/issue_99325.main.built.after.64bit.mir @@ -2,7 +2,7 @@ | User Type Annotations | 0: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [&*b"AAAA"], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:13:16: 13:46, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} -| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }: &'static [u8; 4_usize]], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} +| 1: user_ty: Canonical { value: TypeOf(DefId(0:3 ~ issue_99325[d56d]::function_with_bytes), UserArgs { args: [UnevaluatedConst { def: DefId(0:8 ~ issue_99325[d56d]::main::{constant#1}), args: [] }], user_self_ty: None }), max_universe: U0, variables: [], defining_opaque_types: [] }, span: $DIR/issue_99325.rs:14:16: 14:68, inferred_ty: fn() -> &'static [u8] {function_with_bytes::<&*b"AAAA">} | fn main() -> () { let mut _0: (); diff --git a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs index 05bd0d91168a..c55f3dcec68c 100644 --- a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs +++ b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.rs @@ -1,4 +1,5 @@ //@ edition:2021 +//@ check-pass // issues rust-lang/rust#111911 // test for ICE opaque type with non-universal region substs @@ -6,8 +7,6 @@ #![allow(incomplete_features)] pub async fn foo() {} -//~^ ERROR const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias -//~| ERROR const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias fn bar() -> impl Sized {} pub fn main() {} diff --git a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr b/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr deleted file mode 100644 index 1bdb9cd9501a..000000000000 --- a/tests/ui/const-generics/adt_const_params/opaque_type_with_non-universal_region_substs_ice-111911.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error: const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/opaque_type_with_non-universal_region_substs_ice-111911.rs:8:43 - | -LL | pub async fn foo() {} - | ^^ - -error: const parameter `X` is part of concrete type but not used in parameter list for the `impl Trait` type alias - --> $DIR/opaque_type_with_non-universal_region_substs_ice-111911.rs:8:43 - | -LL | pub async fn foo() {} - | ^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors - diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr index 2bfa604fc567..49cf42813235 100644 --- a/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.full.stderr @@ -6,6 +6,16 @@ LL | pub struct Dependent([(); X]); | = note: type parameters may not be used in the type of const parameters -error: aborting due to 1 previous error +error[E0392]: type parameter `T` is never used + --> $DIR/const-param-type-depends-on-type-param.rs:11:22 + | +LL | pub struct Dependent([(); X]); + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -For more information about this error, try `rustc --explain E0770`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0770. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr index 2bfa604fc567..49cf42813235 100644 --- a/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.min.stderr @@ -6,6 +6,16 @@ LL | pub struct Dependent([(); X]); | = note: type parameters may not be used in the type of const parameters -error: aborting due to 1 previous error +error[E0392]: type parameter `T` is never used + --> $DIR/const-param-type-depends-on-type-param.rs:11:22 + | +LL | pub struct Dependent([(); X]); + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -For more information about this error, try `rustc --explain E0770`. +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0392, E0770. +For more information about an error, try `rustc --explain E0392`. diff --git a/tests/ui/const-generics/const-param-type-depends-on-type-param.rs b/tests/ui/const-generics/const-param-type-depends-on-type-param.rs index 1583fc4ee6c8..5503b08930b0 100644 --- a/tests/ui/const-generics/const-param-type-depends-on-type-param.rs +++ b/tests/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -10,5 +10,6 @@ pub struct Dependent([(); X]); //~^ ERROR: the type of const parameters must not depend on other generic parameters +//~| ERROR: type parameter `T` is never used fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs b/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs new file mode 100644 index 000000000000..29ad935c0149 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs @@ -0,0 +1,21 @@ +//@ compile-flags: -Znext-solver=coherence + +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub struct A {} +//~^ ERROR: cannot find value `x` in this scope +//~| ERROR: `[usize; x]` is forbidden as the type of a const generic parameter + +impl A<2> { + //~^ ERROR: mismatched types + pub const fn B() {} + //~^ ERROR: duplicate definitions +} + +impl A<2> { + //~^ ERROR: mismatched types + pub const fn B() {} +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr new file mode 100644 index 000000000000..0e40255bcf59 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr @@ -0,0 +1,45 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/error_in_ty.rs:6:31 + | +LL | pub struct A {} + | - ^ help: a const parameter with a similar name exists: `z` + | | + | similarly named const parameter `z` defined here + +error: `[usize; x]` is forbidden as the type of a const generic parameter + --> $DIR/error_in_ty.rs:6:23 + | +LL | pub struct A {} + | ^^^^^^^^^^ + | + = note: the only supported types are integers, `bool` and `char` +help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + | +LL + #![feature(adt_const_params)] + | + +error[E0308]: mismatched types + --> $DIR/error_in_ty.rs:10:8 + | +LL | impl A<2> { + | ^ expected `[usize; x]`, found integer + +error[E0308]: mismatched types + --> $DIR/error_in_ty.rs:16:8 + | +LL | impl A<2> { + | ^ expected `[usize; x]`, found integer + +error[E0592]: duplicate definitions with name `B` + --> $DIR/error_in_ty.rs:12:5 + | +LL | pub const fn B() {} + | ^^^^^^^^^^^^^^^^ duplicate definitions for `B` +... +LL | pub const fn B() {} + | ---------------- other definition for `B` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0308, E0425, E0592. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs index af17a37bf23a..b662939c27eb 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs @@ -9,9 +9,10 @@ pub trait Trait { fn assoc_fn() -> Self::AssocTy; } -impl Trait for Const // OK, trait impl predicates +impl Trait for Const where - Const<{ my_const_fn(U) }>: , + // OK, trait impl predicates + Const<{ my_const_fn(U) }>:, { type AssocTy = Const<{ my_const_fn(U) }>; //~^ ERROR private type diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr index df0d43bef876..98dac313be41 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -1,5 +1,5 @@ error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface - --> $DIR/eval-privacy.rs:16:5 + --> $DIR/eval-privacy.rs:17:5 | LL | type AssocTy = Const<{ my_const_fn(U) }>; | ^^^^^^^^^^^^ can't leak private type @@ -8,7 +8,7 @@ LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface - --> $DIR/eval-privacy.rs:16:5 + --> $DIR/eval-privacy.rs:17:5 | LL | type AssocTy = Const<{ my_const_fn(U) }>; | ^^^^^^^^^^^^ can't leak private type diff --git a/tests/ui/const-generics/issues/issue-71381.full.stderr b/tests/ui/const-generics/issues/issue-71381.full.stderr index b6460e0017fa..05e847cf4c84 100644 --- a/tests/ui/const-generics/issues/issue-71381.full.stderr +++ b/tests/ui/const-generics/issues/issue-71381.full.stderr @@ -7,13 +7,25 @@ LL | pub fn call_me $DIR/issue-71381.rs:23:40 + --> $DIR/issue-71381.rs:24:40 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^ the type must not depend on the parameter `Args` | = note: type parameters may not be used in the type of const parameters -error: aborting due to 2 previous errors +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference + --> $DIR/issue-71381.rs:17:9 + | +LL | self.0 = Self::trampiline:: as _ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | pub fn call_me(&mut self) { + | ~~~~~~~~~ -For more information about this error, try `rustc --explain E0770`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0594, E0770. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/const-generics/issues/issue-71381.min.stderr b/tests/ui/const-generics/issues/issue-71381.min.stderr index e16d3b7a8a46..1c30e885d1b7 100644 --- a/tests/ui/const-generics/issues/issue-71381.min.stderr +++ b/tests/ui/const-generics/issues/issue-71381.min.stderr @@ -7,7 +7,7 @@ LL | pub fn call_me $DIR/issue-71381.rs:23:40 + --> $DIR/issue-71381.rs:24:40 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^ the type must not depend on the parameter `Args` @@ -23,13 +23,25 @@ LL | pub fn call_me $DIR/issue-71381.rs:23:19 + --> $DIR/issue-71381.rs:24:19 | LL | const FN: unsafe extern "C" fn(Args), | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the only supported types are integers, `bool` and `char` -error: aborting due to 4 previous errors +error[E0594]: cannot assign to `self.0`, which is behind a `&` reference + --> $DIR/issue-71381.rs:17:9 + | +LL | self.0 = Self::trampiline:: as _ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `self` is a `&` reference, so the data it refers to cannot be written + | +help: consider changing this to be a mutable reference + | +LL | pub fn call_me(&mut self) { + | ~~~~~~~~~ -For more information about this error, try `rustc --explain E0770`. +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0594, E0770. +For more information about an error, try `rustc --explain E0594`. diff --git a/tests/ui/const-generics/issues/issue-71381.rs b/tests/ui/const-generics/issues/issue-71381.rs index e472ef31fcdd..166b724a7a33 100644 --- a/tests/ui/const-generics/issues/issue-71381.rs +++ b/tests/ui/const-generics/issues/issue-71381.rs @@ -15,6 +15,7 @@ impl Test { //~^ ERROR: the type of const parameters must not depend on other generic parameters //[min]~^^ ERROR: using function pointers as const generic parameters is forbidden self.0 = Self::trampiline:: as _ + //~^ ERROR: cannot assign to `self.0` } unsafe extern "C" fn trampiline< diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.rs b/tests/ui/const-generics/not_wf_param_in_rpitit.rs new file mode 100644 index 000000000000..5471dc9022f9 --- /dev/null +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.rs @@ -0,0 +1,14 @@ +//@ edition:2021 + +trait Trait { + //~^ ERROR: cannot find value `bar` in this scope + //~| ERROR: cycle detected when computing type of `Trait::N` + //~| ERROR: the trait `Trait` cannot be made into an object + //~| ERROR: the trait `Trait` cannot be made into an object + //~| ERROR: the trait `Trait` cannot be made into an object + //~| ERROR: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter + //~| ERROR: trait objects must include the `dyn` keyword + async fn a() {} +} + +fn main() {} diff --git a/tests/ui/const-generics/not_wf_param_in_rpitit.stderr b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr new file mode 100644 index 000000000000..9095948d22b8 --- /dev/null +++ b/tests/ui/const-generics/not_wf_param_in_rpitit.stderr @@ -0,0 +1,113 @@ +error[E0425]: cannot find value `bar` in this scope + --> $DIR/not_wf_param_in_rpitit.rs:3:30 + | +LL | trait Trait { + | ^^^ not found in this scope + +error[E0391]: cycle detected when computing type of `Trait::N` + --> $DIR/not_wf_param_in_rpitit.rs:3:22 + | +LL | trait Trait { + | ^^^^^ + | + = note: ...which immediately requires computing type of `Trait::N` again +note: cycle used when computing explicit predicates of trait `Trait` + --> $DIR/not_wf_param_in_rpitit.rs:3:1 + | +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/not_wf_param_in_rpitit.rs:3:22 + | +LL | trait Trait { + | ^^^^^ `Trait` 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/not_wf_param_in_rpitit.rs:11:14 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +... +LL | async fn a() {} + | ^ ...because associated function `a` has no `self` parameter +help: consider turning `a` into a method by giving it a `&self` argument + | +LL | async fn a(&self) {} + | +++++ +help: alternatively, consider constraining `a` so it does not apply to trait objects + | +LL | async fn a() where Self: Sized {} + | +++++++++++++++++ + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/not_wf_param_in_rpitit.rs:3:13 + | +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/not_wf_param_in_rpitit.rs:11:14 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +... +LL | async fn a() {} + | ^ ...because associated function `a` has no `self` parameter +help: consider turning `a` into a method by giving it a `&self` argument + | +LL | async fn a(&self) {} + | +++++ +help: alternatively, consider constraining `a` so it does not apply to trait objects + | +LL | async fn a() where Self: Sized {} + | +++++++++++++++++ + +error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter + --> $DIR/not_wf_param_in_rpitit.rs:3:22 + | +LL | trait Trait { + | ^^^^^ + | + = note: the only supported types are integers, `bool` and `char` + +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/not_wf_param_in_rpitit.rs:3:13 + | +LL | trait Trait { + | ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/not_wf_param_in_rpitit.rs:11:14 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +... +LL | async fn a() {} + | ^ ...because associated function `a` has no `self` parameter + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider turning `a` into a method by giving it a `&self` argument + | +LL | async fn a(&self) {} + | +++++ +help: alternatively, consider constraining `a` so it does not apply to trait objects + | +LL | async fn a() where Self: Sized {} + | +++++++++++++++++ + +error[E0782]: trait objects must include the `dyn` keyword + --> $DIR/not_wf_param_in_rpitit.rs:3:22 + | +LL | trait Trait { + | ^^^^^ + | +help: add `dyn` keyword before this trait + | +LL | trait Trait { + | +++ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0038, E0391, E0425, E0782. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr index 1b0d1ea50d08..b76ec10bd3f2 100644 --- a/tests/ui/const-generics/transmute-fail.stderr +++ b/tests/ui/const-generics/transmute-fail.stderr @@ -13,7 +13,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | std::mem::transmute(v) | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `[[u32; H]; W]` (this type does not have a fixed size) + = note: source type: `[[u32; H]; W]` (size can vary because of [u32; H]) = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W]) error[E0512]: cannot transmute between types of different sizes, or dependently-sized types diff --git a/tests/ui/const-generics/type_not_in_scope.rs b/tests/ui/const-generics/type_not_in_scope.rs index 917abaed15e0..1eb265d74d1c 100644 --- a/tests/ui/const-generics/type_not_in_scope.rs +++ b/tests/ui/const-generics/type_not_in_scope.rs @@ -5,6 +5,7 @@ impl X { } } fn getn() -> [u8; N] {} -//~^ ERROR expected type, found built-in attribute `cfg_attr` +//~^ ERROR: expected type, found built-in attribute `cfg_attr` +//~| ERROR: mismatched types fn main() {} diff --git a/tests/ui/const-generics/type_not_in_scope.stderr b/tests/ui/const-generics/type_not_in_scope.stderr index 5eb81ca05224..5f45550a6279 100644 --- a/tests/ui/const-generics/type_not_in_scope.stderr +++ b/tests/ui/const-generics/type_not_in_scope.stderr @@ -10,7 +10,15 @@ error[E0573]: expected type, found built-in attribute `cfg_attr` LL | fn getn() -> [u8; N] {} | ^^^^^^^^ not a type -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/type_not_in_scope.rs:7:33 + | +LL | fn getn() -> [u8; N] {} + | ---- ^^^^^^^ expected `[u8; N]`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression -Some errors have detailed explanations: E0412, E0573. -For more information about an error, try `rustc --explain E0412`. +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0412, E0573. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/consts/issue-103790.rs b/tests/ui/consts/issue-103790.rs index 5d130821dc8e..d19115ede74b 100644 --- a/tests/ui/consts/issue-103790.rs +++ b/tests/ui/consts/issue-103790.rs @@ -5,7 +5,7 @@ struct S; //~^ ERROR the name `S` is already used for a generic parameter in this item's generic parameters //~| ERROR missing generics for struct `S` //~| ERROR cycle detected when computing type of `S::S` -//~| ERROR cycle detected when computing type of `S` //~| ERROR `()` is forbidden as the type of a const generic parameter +//~| ERROR `S<{const error}, {const error}>` is forbidden as the type of a const generic parameter fn main() {} diff --git a/tests/ui/consts/issue-103790.stderr b/tests/ui/consts/issue-103790.stderr index eecaf5ff63a3..c671f078cb5c 100644 --- a/tests/ui/consts/issue-103790.stderr +++ b/tests/ui/consts/issue-103790.stderr @@ -29,26 +29,7 @@ LL | struct S; | ^ | = note: ...which immediately requires computing type of `S::S` again -note: cycle used when computing type of `S` - --> $DIR/issue-103790.rs:4:1 - | -LL | struct S; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0391]: cycle detected when computing type of `S` - --> $DIR/issue-103790.rs:4:1 - | -LL | struct S; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires computing type of `S::S`... - --> $DIR/issue-103790.rs:4:32 - | -LL | struct S; - | ^ - = note: ...which again requires computing type of `S`, completing the cycle -note: cycle used when checking that `S` is well-formed +note: cycle used when computing explicit predicates of `S` --> $DIR/issue-103790.rs:4:1 | LL | struct S; @@ -67,6 +48,18 @@ help: add `#![feature(adt_const_params)]` to the crate attributes to enable more LL + #![feature(adt_const_params)] | +error: `S<{const error}, {const error}>` is forbidden as the type of a const generic parameter + --> $DIR/issue-103790.rs:4:32 + | +LL | struct S; + | ^ + | + = note: the only supported types are integers, `bool` and `char` +help: add `#![feature(adt_const_params)]` to the crate attributes to enable more complex and user defined types + | +LL + #![feature(adt_const_params)] + | + error: aborting due to 5 previous errors Some errors have detailed explanations: E0107, E0391, E0403. diff --git a/tests/ui/privacy/where-priv-type.rs b/tests/ui/privacy/where-priv-type.rs index a62feace2da2..20467301ae17 100644 --- a/tests/ui/privacy/where-priv-type.rs +++ b/tests/ui/privacy/where-priv-type.rs @@ -11,55 +11,46 @@ pub struct PubTy; pub struct PubTyGeneric(T); pub trait PubTr {} impl PubTr for PrivTy {} -pub trait PubTrWithAssocTy { type AssocTy; } -impl PubTrWithAssocTy for PrivTy { type AssocTy = PrivTy; } - +pub trait PubTrWithAssocTy { + type AssocTy; +} +impl PubTrWithAssocTy for PrivTy { + type AssocTy = PrivTy; +} pub struct S //~^ WARNING type `PrivTy` is more private than the item `S` where - PrivTy: -{} - + PrivTy:, {} pub enum E //~^ WARNING type `PrivTy` is more private than the item `E` where - PrivTy: -{} - + PrivTy:, {} pub fn f() //~^ WARNING type `PrivTy` is more private than the item `f` where - PrivTy: -{} - + PrivTy:, +{ +} impl S //~^ WARNING type `PrivTy` is more private than the item `S` where - PrivTy: + PrivTy:, { pub fn f() //~^ WARNING type `PrivTy` is more private than the item `S::f` where - PrivTy: - {} + PrivTy:, + { + } } +impl PubTr for PubTy where PrivTy: {} -impl PubTr for PubTy -where - PrivTy: -{} - - -impl PubTr for PubTyGeneric -where - T: PubTrWithAssocTy -{} - +impl PubTr for PubTyGeneric where T: PubTrWithAssocTy {} pub struct Const; @@ -70,7 +61,7 @@ pub trait Trait { impl Trait for Const where - Const<{ my_const_fn(U) }>: , + Const<{ my_const_fn(U) }>:, { type AssocTy = Const<{ my_const_fn(U) }>; //~^ ERROR private type diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr index 8ea2e17c4361..08963e07c35a 100644 --- a/tests/ui/privacy/where-priv-type.stderr +++ b/tests/ui/privacy/where-priv-type.stderr @@ -1,5 +1,5 @@ warning: type `PrivTy` is more private than the item `S` - --> $DIR/where-priv-type.rs:18:1 + --> $DIR/where-priv-type.rs:21:1 | LL | pub struct S | ^^^^^^^^^^^^ struct `S` is reachable at visibility `pub` @@ -12,7 +12,7 @@ LL | struct PrivTy; = note: `#[warn(private_bounds)]` on by default warning: type `PrivTy` is more private than the item `E` - --> $DIR/where-priv-type.rs:25:1 + --> $DIR/where-priv-type.rs:26:1 | LL | pub enum E | ^^^^^^^^^^ enum `E` is reachable at visibility `pub` @@ -24,13 +24,13 @@ LL | struct PrivTy; | ^^^^^^^^^^^^^ warning: type `PrivTy` is more private than the item `f` - --> $DIR/where-priv-type.rs:32:1 + --> $DIR/where-priv-type.rs:31:1 | LL | / pub fn f() LL | | LL | | where -LL | | PrivTy: - | |___________^ function `f` is reachable at visibility `pub` +LL | | PrivTy:, + | |____________^ function `f` is reachable at visibility `pub` | note: but type `PrivTy` is only usable at visibility `pub(crate)` --> $DIR/where-priv-type.rs:8:1 @@ -39,13 +39,13 @@ LL | struct PrivTy; | ^^^^^^^^^^^^^ warning: type `PrivTy` is more private than the item `S` - --> $DIR/where-priv-type.rs:39:1 + --> $DIR/where-priv-type.rs:38:1 | LL | / impl S LL | | LL | | where -LL | | PrivTy: - | |___________^ implementation `S` is reachable at visibility `pub` +LL | | PrivTy:, + | |____________^ implementation `S` is reachable at visibility `pub` | note: but type `PrivTy` is only usable at visibility `pub(crate)` --> $DIR/where-priv-type.rs:8:1 @@ -54,13 +54,13 @@ LL | struct PrivTy; | ^^^^^^^^^^^^^ warning: type `PrivTy` is more private than the item `S::f` - --> $DIR/where-priv-type.rs:44:5 + --> $DIR/where-priv-type.rs:43:5 | LL | / pub fn f() LL | | LL | | where -LL | | PrivTy: - | |_______________^ associated function `S::f` is reachable at visibility `pub` +LL | | PrivTy:, + | |________________^ associated function `S::f` is reachable at visibility `pub` | note: but type `PrivTy` is only usable at visibility `pub(crate)` --> $DIR/where-priv-type.rs:8:1 @@ -69,7 +69,7 @@ LL | struct PrivTy; | ^^^^^^^^^^^^^ error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface - --> $DIR/where-priv-type.rs:75:5 + --> $DIR/where-priv-type.rs:66:5 | LL | type AssocTy = Const<{ my_const_fn(U) }>; | ^^^^^^^^^^^^ can't leak private type @@ -78,7 +78,7 @@ LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface - --> $DIR/where-priv-type.rs:75:5 + --> $DIR/where-priv-type.rs:66:5 | LL | type AssocTy = Const<{ my_const_fn(U) }>; | ^^^^^^^^^^^^ can't leak private type diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs index 9778217d462d..6b5ba5bb6241 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.rs @@ -17,8 +17,6 @@ impl const Foo for T where T: const Specialize {} //~^ error: const `impl` for trait `Foo` which is not marked with `#[const_trait]` //~| error: `const` can only be applied to `#[const_trait]` traits //~| error: the const parameter `host` is not constrained by the impl trait, self type, or predicates [E0207] -//~| error: specialization impl does not specialize any associated items -//~| error: could not resolve generic parameters on overridden impl +//~| error: conflicting implementations of trait `Foo` -fn main() { -} +fn main() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr index d18063f8d3d8..70dd0350dc42 100644 --- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/spec-effectvar-ice.stderr @@ -37,6 +37,15 @@ LL | impl const Foo for T {} = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported +error[E0119]: conflicting implementations of trait `Foo` + --> $DIR/spec-effectvar-ice.rs:16:1 + | +LL | impl const Foo for T {} + | ----------------------- first implementation here +... +LL | impl const Foo for T where T: const Specialize {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation + error[E0207]: the const parameter `host` is not constrained by the impl trait, self type, or predicates --> $DIR/spec-effectvar-ice.rs:16:9 | @@ -46,24 +55,7 @@ LL | impl const Foo for T where T: const Specialize {} = note: expressions using a const parameter must map each value to a distinct output value = note: proving the result of expressions other than the parameter are unique is not supported -error: specialization impl does not specialize any associated items - --> $DIR/spec-effectvar-ice.rs:16:1 - | -LL | impl const Foo for T where T: const Specialize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl is a specialization of this impl - --> $DIR/spec-effectvar-ice.rs:12:1 - | -LL | impl const Foo for T {} - | ^^^^^^^^^^^^^^^^^^^^^^^ +error: aborting due to 6 previous errors -error: could not resolve generic parameters on overridden impl - --> $DIR/spec-effectvar-ice.rs:16:1 - | -LL | impl const Foo for T where T: const Specialize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 7 previous errors - -For more information about this error, try `rustc --explain E0207`. +Some errors have detailed explanations: E0119, E0207. +For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr index 6a1a770228da..3b6999cabc41 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr +++ b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr @@ -1,5 +1,5 @@ error: `Bar` is forbidden as the type of a const generic parameter - --> $DIR/const_generic_type.rs:7:24 + --> $DIR/const_generic_type.rs:8:24 | LL | async fn test() { | ^^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr index a1a69bfaca37..56a102016514 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr +++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr @@ -1,13 +1,13 @@ -error[E0283]: type annotations needed - --> $DIR/const_generic_type.rs:7:1 +error: unconstrained opaque type + --> $DIR/const_generic_type.rs:5:12 | -LL | async fn test() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type +LL | type Bar = impl std::fmt::Display; + | ^^^^^^^^^^^^^^^^^^^^^^ | - = note: cannot satisfy `_: std::fmt::Display` + = note: `Bar` must be used in combination with a concrete type within the same module error: `Bar` is forbidden as the type of a const generic parameter - --> $DIR/const_generic_type.rs:7:24 + --> $DIR/const_generic_type.rs:8:24 | LL | async fn test() { | ^^^^^^^^^^ @@ -16,4 +16,3 @@ LL | async fn test() { error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.rs b/tests/ui/type-alias-impl-trait/const_generic_type.rs index 95a5e1c62861..bfd06826f00c 100644 --- a/tests/ui/type-alias-impl-trait/const_generic_type.rs +++ b/tests/ui/type-alias-impl-trait/const_generic_type.rs @@ -3,10 +3,10 @@ #![feature(type_alias_impl_trait)] type Bar = impl std::fmt::Display; +//[no_infer]~^ ERROR: unconstrained opaque type async fn test() { - //[no_infer]~^ ERROR: type annotations needed - //~^^ ERROR: `Bar` is forbidden as the type of a const generic parameter + //~^ ERROR: `Bar` is forbidden as the type of a const generic parameter #[cfg(infer)] let x: u32 = N; } diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs index db155f4fa3c3..3f43fbfc0cf4 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.rs @@ -1,7 +1,6 @@ trait Trait { //~^ ERROR cannot find value `bar` in this scope //~| ERROR cycle detected when computing type of `Trait::N` - //~| ERROR cycle detected when computing type of `Trait::N` //~| ERROR the trait `Trait` cannot be made into an object //~| ERROR the trait `Trait` cannot be made into an object //~| ERROR the trait `Trait` cannot be made into an object @@ -11,20 +10,20 @@ trait Trait { //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! fn fnc(&self) -> Trait { - //~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters - //~| ERROR expected value, found builtin type `u32` - //~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - //~| ERROR associated item referring to unboxed trait object for its own trait - //~| ERROR the trait `Trait` cannot be made into an object - //~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] - //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~^ ERROR the name `N` is already used for a generic parameter in this item's generic parameters + //~| ERROR expected value, found builtin type `u32` + //~| ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + //~| ERROR associated item referring to unboxed trait object for its own trait + //~| ERROR the trait `Trait` cannot be made into an object + //~| ERROR `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter + //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| WARN trait objects without an explicit `dyn` are deprecated [bare_trait_objects] + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! bar - //~^ ERROR cannot find value `bar` in this scope + //~^ ERROR cannot find value `bar` in this scope } } diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr index cf985d9d1fdf..f2456f99e623 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122199.stderr @@ -1,5 +1,5 @@ error[E0403]: the name `N` is already used for a generic parameter in this item's generic parameters - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:18 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:18 | LL | trait Trait { | - first use of `N` @@ -14,13 +14,13 @@ LL | trait Trait { | ^^^ not found in this scope error[E0423]: expected value, found builtin type `u32` - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:29 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:29 | LL | fn fnc(&self) -> Trait { | ^^^ not a value error[E0425]: cannot find value `bar` in this scope - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:26:9 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:25:9 | LL | bar | ^^^ not found in this scope @@ -53,28 +53,14 @@ LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0391]: cycle detected when computing type of `Trait::N` - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:13 - | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: ...which immediately requires computing type of `Trait::N` again -note: cycle used when computing explicit predicates of trait `Trait` - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:1:1 - | -LL | trait Trait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:12 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:12 | LL | fn fnc(&self) -> Trait { | ^^^^^^^^^^^^^^^^^^^^ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:21 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 | LL | fn fnc(&self) -> Trait { | ^^^^^ @@ -87,7 +73,7 @@ LL | fn fnc(&self) -> Trait { | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:44 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:44 | LL | fn fnc(&self) -> Trait { | ^^^^^ @@ -120,7 +106,7 @@ LL | trait Trait { | ^^^^^ `Trait` 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/ice-hir-wf-check-anon-const-issue-122199.rs:13:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -136,7 +122,7 @@ LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/ice-hir-wf-check-anon-const-issue-122199.rs:13:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -154,7 +140,7 @@ LL | trait Trait { = note: the only supported types are integers, `bool` and `char` error: associated item referring to unboxed trait object for its own trait - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:44 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:44 | LL | trait Trait { | ----- in this trait @@ -168,7 +154,7 @@ LL | fn fnc(&self) -> Self { | ~~~~ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:21 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 | LL | fn fnc(&self) -> Trait { | ^^^^^ @@ -182,13 +168,13 @@ LL | fn fnc(&self) -> Trait { | +++ error[E0038]: the trait `Trait` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:21 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 | LL | fn fnc(&self) -> Trait { | ^^^^^ `Trait` 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/ice-hir-wf-check-anon-const-issue-122199.rs:13:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -204,7 +190,7 @@ LL | trait Trait { | ^^^^^^^^^^^^^^^^^^^^ `Trait` 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/ice-hir-wf-check-anon-const-issue-122199.rs:13:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:8 | LL | trait Trait { | ----- this trait cannot be made into an object... @@ -215,14 +201,14 @@ LL | fn fnc(&self) -> Trait { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: `(dyn Trait<{const error}> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:13:21 + --> $DIR/ice-hir-wf-check-anon-const-issue-122199.rs:12:21 | LL | fn fnc(&self) -> Trait { | ^^^^^ | = note: the only supported types are integers, `bool` and `char` -error: aborting due to 14 previous errors; 5 warnings emitted +error: aborting due to 13 previous errors; 5 warnings emitted Some errors have detailed explanations: E0038, E0391, E0403, E0423, E0425. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs index 2995f26af4a6..a953f1818c58 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.rs @@ -1,15 +1,11 @@ // Regression test for ICE #122989 trait Foo> { -//~^ WARN trait objects without an explicit `dyn` are deprecated -//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! -//~| ERROR cycle detected when computing type of `Foo::N` -//~| ERROR cycle detected when computing type of `Foo::N` -//~| ERROR the trait `Foo` cannot be made into an object -//~| ERROR the trait `Foo` cannot be made into an object -//~| ERROR the trait `Foo` cannot be made into an object -//~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter - fn func() { - } + //~^ WARN trait objects without an explicit `dyn` are deprecated + //~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| ERROR cycle detected when computing type of `Foo::N` + //~| ERROR the trait `Foo` cannot be made into an object + //~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter + fn func() {} } trait Bar> {} diff --git a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr index e6fdc4408736..a0fd11de2dc6 100644 --- a/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr +++ b/tests/ui/wf/ice-hir-wf-check-anon-const-issue-122989.stderr @@ -13,7 +13,7 @@ LL | trait Foo> { | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:20 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 | LL | trait Bar> {} | ^^^^^^ @@ -32,7 +32,7 @@ LL | trait Foo> { | ^^^^^^^^^^^^^^^ | note: ...which requires computing type of `Bar::M`... - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:11 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 | LL | trait Bar> {} | ^^^^^^^^^^^^^^^ @@ -44,26 +44,6 @@ LL | trait Foo> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information -error[E0391]: cycle detected when computing type of `Foo::N` - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:11 - | -LL | trait Foo> { - | ^^^^^^^^^^^^^^^ - | -note: ...which requires computing type of `Bar::M`... - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:11 - | -LL | trait Bar> {} - | ^^^^^^^^^^^^^^^ - = note: ...which again requires computing type of `Foo::N`, completing the cycle -note: cycle used when computing explicit predicates of trait `Foo` - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:1 - | -LL | trait Foo> { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - error[E0038]: the trait `Foo` cannot be made into an object --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:24 | @@ -71,43 +51,20 @@ LL | trait Foo> { | ^ `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/ice-hir-wf-check-anon-const-issue-122989.rs:11:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8 | LL | trait Foo> { | --- this trait cannot be made into an object... ... -LL | fn func() { +LL | fn func() {} | ^^^^ ...because associated function `func` has no `self` parameter help: consider turning `func` into a method by giving it a `&self` argument | -LL | fn func(&self) { +LL | fn func(&self) {} | +++++ help: alternatively, consider constraining `func` so it does not apply to trait objects | -LL | fn func() where Self: Sized { - | +++++++++++++++++ - -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:11 - | -LL | trait Foo> { - | ^^^^^^^^^^^^^^^ `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/ice-hir-wf-check-anon-const-issue-122989.rs:11:8 - | -LL | trait Foo> { - | --- this trait cannot be made into an object... -... -LL | fn func() { - | ^^^^ ...because associated function `func` has no `self` parameter -help: consider turning `func` into a method by giving it a `&self` argument - | -LL | fn func(&self) { - | +++++ -help: alternatively, consider constraining `func` so it does not apply to trait objects - | -LL | fn func() where Self: Sized { +LL | fn func() where Self: Sized {} | +++++++++++++++++ error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter @@ -119,61 +76,37 @@ LL | trait Foo> { = note: the only supported types are integers, `bool` and `char` error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:11 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11 | LL | trait Bar> {} | ^^^^^^^^^^^^^^^ `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/ice-hir-wf-check-anon-const-issue-122989.rs:11:8 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8 | LL | trait Foo> { | --- this trait cannot be made into an object... ... -LL | fn func() { +LL | fn func() {} | ^^^^ ...because associated function `func` has no `self` parameter help: consider turning `func` into a method by giving it a `&self` argument | -LL | fn func(&self) { +LL | fn func(&self) {} | +++++ help: alternatively, consider constraining `func` so it does not apply to trait objects | -LL | fn func() where Self: Sized { +LL | fn func() where Self: Sized {} | +++++++++++++++++ error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:15:20 + --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20 | LL | trait Bar> {} | ^^^^^^ | = note: the only supported types are integers, `bool` and `char` -error[E0038]: the trait `Foo` cannot be made into an object - --> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:11 - | -LL | trait Foo> { - | ^^^^^^^^^^^^^^^ `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/ice-hir-wf-check-anon-const-issue-122989.rs:11:8 - | -LL | trait Foo> { - | --- this trait cannot be made into an object... -... -LL | fn func() { - | ^^^^ ...because associated function `func` has no `self` parameter - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -help: consider turning `func` into a method by giving it a `&self` argument - | -LL | fn func(&self) { - | +++++ -help: alternatively, consider constraining `func` so it does not apply to trait objects - | -LL | fn func() where Self: Sized { - | +++++++++++++++++ - -error: aborting due to 8 previous errors; 2 warnings emitted +error: aborting due to 5 previous errors; 2 warnings emitted Some errors have detailed explanations: E0038, E0391. For more information about an error, try `rustc --explain E0038`. From 2e082677a6d36f1741520b0b824ea43a903a1ba5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 5 Jun 2024 09:40:31 -0400 Subject: [PATCH 132/154] Fix function-names.rs test --- tests/debuginfo/function-names.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/debuginfo/function-names.rs b/tests/debuginfo/function-names.rs index 96456d4c6b0b..993bdd68fc78 100644 --- a/tests/debuginfo/function-names.rs +++ b/tests/debuginfo/function-names.rs @@ -37,7 +37,7 @@ // Const generic parameter // gdb-command:info functions -q function_names::const_generic_fn.* // gdb-check:[...]static fn function_names::const_generic_fn_bool(); -// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#[...]}>(); +// gdb-check:[...]static fn function_names::const_generic_fn_non_int<{CONST#a70c39591cb5f53d}>(); // gdb-check:[...]static fn function_names::const_generic_fn_signed_int<-7>(); // gdb-check:[...]static fn function_names::const_generic_fn_unsigned_int<14>(); @@ -76,7 +76,7 @@ // Const generic parameter // cdb-command:x a!function_names::const_generic_fn* // cdb-check:[...] a!function_names::const_generic_fn_bool (void) -// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) +// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) // cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void) // cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void) From 3a6b606ad9e6c9efc83bd9e7ab0025080d052bc0 Mon Sep 17 00:00:00 2001 From: Boxy Date: Wed, 5 Jun 2024 22:39:42 +0100 Subject: [PATCH 133/154] remove const arg windows debug info tests --- tests/debuginfo/function-names.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/debuginfo/function-names.rs b/tests/debuginfo/function-names.rs index 993bdd68fc78..d9b61e736215 100644 --- a/tests/debuginfo/function-names.rs +++ b/tests/debuginfo/function-names.rs @@ -76,9 +76,6 @@ // Const generic parameter // cdb-command:x a!function_names::const_generic_fn* // cdb-check:[...] a!function_names::const_generic_fn_bool (void) -// cdb-check:[...] a!function_names::const_generic_fn_non_int (void) -// cdb-check:[...] a!function_names::const_generic_fn_unsigned_int<14> (void) -// cdb-check:[...] a!function_names::const_generic_fn_signed_int<-7> (void) #![allow(unused_variables)] #![feature(omit_gdb_pretty_printer_section)] From bb901a114f1abef304f2420be071da8aa3c21406 Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 3 Jun 2024 13:08:39 +0200 Subject: [PATCH 134/154] Don't trigger `unsafe_op_in_unsafe_fn` for deprecated safe fns Fixes #125875. --- .../rustc_mir_build/src/check_unsafety.rs | 81 +++++++++++-------- tests/ui/rust-2024/unsafe-env.e2021.stderr | 27 ++++++- tests/ui/rust-2024/unsafe-env.e2024.stderr | 49 +++++++++-- tests/ui/rust-2024/unsafe-env.rs | 12 ++- 4 files changed, 124 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 659ae1724603..9a19445e3779 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -88,6 +88,33 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { } } + fn emit_deprecated_safe_fn_call(&self, span: Span, kind: &UnsafeOpKind) -> bool { + match kind { + // Allow calls to deprecated-safe unsafe functions if the caller is + // from an edition before 2024. + &UnsafeOpKind::CallToUnsafeFunction(Some(id)) + if !span.at_least_rust_2024() + && self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) => + { + self.tcx.emit_node_span_lint( + DEPRECATED_SAFE, + self.hir_context, + span, + CallToDeprecatedSafeFnRequiresUnsafe { + span, + function: with_no_trimmed_paths!(self.tcx.def_path_str(id)), + sub: CallToDeprecatedSafeFnRequiresUnsafeSub { + left: span.shrink_to_lo(), + right: span.shrink_to_hi(), + }, + }, + ); + true + } + _ => false, + } + } + fn requires_unsafe(&mut self, span: Span, kind: UnsafeOpKind) { let unsafe_op_in_unsafe_fn_allowed = self.unsafe_op_in_unsafe_fn_allowed(); match self.safety_context { @@ -101,43 +128,29 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { } SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {} SafetyContext::UnsafeFn => { - // unsafe_op_in_unsafe_fn is disallowed - kind.emit_unsafe_op_in_unsafe_fn_lint( - self.tcx, - self.hir_context, - span, - self.suggest_unsafe_block, - ); - self.suggest_unsafe_block = false; - } - SafetyContext::Safe => match kind { - // Allow calls to deprecated-safe unsafe functions if the - // caller is from an edition before 2024. - UnsafeOpKind::CallToUnsafeFunction(Some(id)) - if !span.at_least_rust_2024() - && self.tcx.has_attr(id, sym::rustc_deprecated_safe_2024) => - { - self.tcx.emit_node_span_lint( - DEPRECATED_SAFE, + let deprecated_safe_fn = self.emit_deprecated_safe_fn_call(span, &kind); + if !deprecated_safe_fn { + // unsafe_op_in_unsafe_fn is disallowed + kind.emit_unsafe_op_in_unsafe_fn_lint( + self.tcx, self.hir_context, span, - CallToDeprecatedSafeFnRequiresUnsafe { - span, - function: with_no_trimmed_paths!(self.tcx.def_path_str(id)), - sub: CallToDeprecatedSafeFnRequiresUnsafeSub { - left: span.shrink_to_lo(), - right: span.shrink_to_hi(), - }, - }, - ) + self.suggest_unsafe_block, + ); + self.suggest_unsafe_block = false; } - _ => kind.emit_requires_unsafe_err( - self.tcx, - span, - self.hir_context, - unsafe_op_in_unsafe_fn_allowed, - ), - }, + } + SafetyContext::Safe => { + let deprecated_safe_fn = self.emit_deprecated_safe_fn_call(span, &kind); + if !deprecated_safe_fn { + kind.emit_requires_unsafe_err( + self.tcx, + span, + self.hir_context, + unsafe_op_in_unsafe_fn_allowed, + ); + } + } } } diff --git a/tests/ui/rust-2024/unsafe-env.e2021.stderr b/tests/ui/rust-2024/unsafe-env.e2021.stderr index cc40ec2e466b..90c1df192aa0 100644 --- a/tests/ui/rust-2024/unsafe-env.e2021.stderr +++ b/tests/ui/rust-2024/unsafe-env.e2021.stderr @@ -1,5 +1,24 @@ +error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block + --> $DIR/unsafe-env.rs:15:9 + | +LL | unsafe_fn(); + | ^^^^^^^^^^^ call to unsafe function + | + = note: for more information, see issue #71668 + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/unsafe-env.rs:9:1 + | +LL | unsafe fn unsafe_fn() { + | ^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/unsafe-env.rs:8:8 + | +LL | #[deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe function or block - --> $DIR/unsafe-env.rs:23:5 + --> $DIR/unsafe-env.rs:33:5 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -7,17 +26,17 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error: unnecessary `unsafe` block - --> $DIR/unsafe-env.rs:26:5 + --> $DIR/unsafe-env.rs:36:5 | LL | unsafe { | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-env.rs:11:8 + --> $DIR/unsafe-env.rs:21:8 | LL | #[deny(unused_unsafe)] | ^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-env.e2024.stderr b/tests/ui/rust-2024/unsafe-env.e2024.stderr index b43f817cf72a..5ecdf3cd7a74 100644 --- a/tests/ui/rust-2024/unsafe-env.e2024.stderr +++ b/tests/ui/rust-2024/unsafe-env.e2024.stderr @@ -1,5 +1,42 @@ +error[E0133]: call to unsafe function `std::env::set_var` is unsafe and requires unsafe block + --> $DIR/unsafe-env.rs:10:5 + | +LL | env::set_var("FOO", "BAR"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: for more information, see issue #71668 + = note: consult the function's documentation for information on how to avoid undefined behavior +note: an unsafe function restricts its caller, but its body is safe by default + --> $DIR/unsafe-env.rs:9:1 + | +LL | unsafe fn unsafe_fn() { + | ^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/unsafe-env.rs:8:8 + | +LL | #[deny(unsafe_op_in_unsafe_fn)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0133]: call to unsafe function `std::env::remove_var` is unsafe and requires unsafe block + --> $DIR/unsafe-env.rs:12:5 + | +LL | env::remove_var("FOO"); + | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: for more information, see issue #71668 + = note: consult the function's documentation for information on how to avoid undefined behavior + +error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block + --> $DIR/unsafe-env.rs:15:9 + | +LL | unsafe_fn(); + | ^^^^^^^^^^^ call to unsafe function + | + = note: for more information, see issue #71668 + = note: consult the function's documentation for information on how to avoid undefined behavior + error[E0133]: call to unsafe function `set_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:13:5 + --> $DIR/unsafe-env.rs:23:5 | LL | env::set_var("FOO", "BAR"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -7,7 +44,7 @@ LL | env::set_var("FOO", "BAR"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `remove_var` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:15:5 + --> $DIR/unsafe-env.rs:25:5 | LL | env::remove_var("FOO"); | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function @@ -15,7 +52,7 @@ LL | env::remove_var("FOO"); = note: consult the function's documentation for information on how to avoid undefined behavior error[E0133]: call to unsafe function `unsafe_fn` is unsafe and requires unsafe block - --> $DIR/unsafe-env.rs:23:5 + --> $DIR/unsafe-env.rs:33:5 | LL | unsafe_fn(); | ^^^^^^^^^^^ call to unsafe function @@ -23,17 +60,17 @@ LL | unsafe_fn(); = note: consult the function's documentation for information on how to avoid undefined behavior error: unnecessary `unsafe` block - --> $DIR/unsafe-env.rs:26:5 + --> $DIR/unsafe-env.rs:36:5 | LL | unsafe { | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/unsafe-env.rs:11:8 + --> $DIR/unsafe-env.rs:21:8 | LL | #[deny(unused_unsafe)] | ^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0133`. diff --git a/tests/ui/rust-2024/unsafe-env.rs b/tests/ui/rust-2024/unsafe-env.rs index a882f077b9bb..601f44e1d3ec 100644 --- a/tests/ui/rust-2024/unsafe-env.rs +++ b/tests/ui/rust-2024/unsafe-env.rs @@ -5,7 +5,17 @@ use std::env; -unsafe fn unsafe_fn() {} +#[deny(unsafe_op_in_unsafe_fn)] +unsafe fn unsafe_fn() { + env::set_var("FOO", "BAR"); + //[e2024]~^ ERROR call to unsafe function `std::env::set_var` is unsafe + env::remove_var("FOO"); + //[e2024]~^ ERROR call to unsafe function `std::env::remove_var` is unsafe + if false { + unsafe_fn(); + //~^ ERROR call to unsafe function `unsafe_fn` is unsafe + } +} fn safe_fn() {} #[deny(unused_unsafe)] From 3f892f87e679d594fc22a63495451c0bd694df9b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 6 Jun 2024 08:53:42 +1000 Subject: [PATCH 135/154] Clarify an `x fmt` error. --- src/bootstrap/src/core/build_steps/format.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 601e4e55e094..0caa39d78acc 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -118,7 +118,9 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) { pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) { if !paths.is_empty() { - eprintln!("fmt error: path arguments are not accepted"); + eprintln!( + "fmt error: path arguments are no longer accepted; use `--all` to format everything" + ); crate::exit!(1); }; if build.config.dry_run() { From 3a70a810d5d271f18489a7e5a8cbbd2e6262b1b7 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 23 May 2024 11:53:27 +0300 Subject: [PATCH 136/154] create libcxx-version tool for getting currently used libcxx version Signed-off-by: onur-ozkan --- src/tools/libcxx-version/main.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/tools/libcxx-version/main.cpp diff --git a/src/tools/libcxx-version/main.cpp b/src/tools/libcxx-version/main.cpp new file mode 100644 index 000000000000..d12078abbb83 --- /dev/null +++ b/src/tools/libcxx-version/main.cpp @@ -0,0 +1,28 @@ +// Detecting the standard library version manually using a bunch of shell commands is very +// complicated and fragile across different platforms. This program provides the major version +// of the standard library on any target platform without requiring any messy work. +// +// It's nothing more than specifying the name of the standard library implementation (either libstdc++ or libc++) +// and its major version. +// +// ignore-tidy-linelength + +#include + +int main() { + #ifdef _GLIBCXX_RELEASE + std::cout << "libstdc++ version: " << _GLIBCXX_RELEASE << std::endl; + #elif defined(_LIBCPP_VERSION) + // _LIBCPP_VERSION follows "XXYYZZ" format (e.g., 170001 for 17.0.1). + // ref: https://github.com/llvm/llvm-project/blob/f64732195c1030ee2627ff4e4142038e01df1d26/libcxx/include/__config#L51-L54 + // + // Since we use the major version from _GLIBCXX_RELEASE, we need to extract only the first 2 characters of _LIBCPP_VERSION + // to provide the major version for consistency. + std::cout << "libc++ version: " << std::to_string(_LIBCPP_VERSION).substr(0, 2) << std::endl; + #else + std::cerr << "Coudln't recognize the standard library version." << std::endl; + return 1; + #endif + + return 0; +} From 73ff1d4b25b7f996c159335af0ca5091b9f4554c Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 23 May 2024 11:59:25 +0300 Subject: [PATCH 137/154] check host's libstdc++ version when using ci llvm Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/tool.rs | 54 ++++++++++++++++++++++ src/bootstrap/src/core/sanity.rs | 36 ++++++++++++++- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 2db3f8f79364..4f7efcb05d89 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -10,6 +10,7 @@ use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, use crate::core::config::TargetSelection; use crate::utils::channel::GitInfo; use crate::utils::exec::BootstrapCommand; +use crate::utils::helpers::output; use crate::utils::helpers::{add_dylib_path, exe, t}; use crate::Compiler; use crate::Mode; @@ -804,6 +805,59 @@ impl Step for LlvmBitcodeLinker { } } +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub struct LibcxxVersionTool { + pub target: TargetSelection, +} + +#[derive(Debug, Clone)] +pub enum LibcxxVersion { + Gnu(usize), + #[allow(dead_code)] + Llvm(usize), +} + +impl Step for LibcxxVersionTool { + type Output = LibcxxVersion; + const DEFAULT: bool = false; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.never() + } + + fn run(self, builder: &Builder<'_>) -> LibcxxVersion { + let out_dir = builder.out.join(self.target.to_string()).join("libcxx-version"); + let _ = fs::remove_dir_all(&out_dir); + t!(fs::create_dir_all(&out_dir)); + + let compiler = builder.cxx(self.target).unwrap(); + let mut cmd = Command::new(compiler); + + let executable = out_dir.join("libcxx-version"); + cmd.arg("-o").arg(&executable).arg(builder.src.join("src/tools/libcxx-version/main.cpp")); + + builder.run_cmd(&mut cmd); + + if !executable.exists() { + panic!("Something went wrong. {} is not present", executable.display()); + } + + let version_output = output(&mut Command::new(executable)); + + let version_str = version_output.split_once("version:").unwrap().1; + let version = version_str.trim().parse::().unwrap(); + + if version_output.starts_with("libstdc++") { + LibcxxVersion::Gnu(version) + } else if version_output.starts_with("libc++") { + LibcxxVersion::Llvm(version) + } else { + panic!("Coudln't recognize the standard library version."); + } + } +} + macro_rules! tool_extended { (($sel:ident, $builder:ident), $($name:ident, diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index ead38ebc6d5e..6595c599eb1c 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -18,7 +18,8 @@ use std::process::Command; #[cfg(not(feature = "bootstrap-self-test"))] use std::collections::HashSet; -use crate::builder::Kind; +use crate::builder::{Builder, Kind}; +use crate::core::build_steps::tool; use crate::core::config::Target; use crate::utils::helpers::output; use crate::Build; @@ -38,6 +39,10 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[ // just a dummy comment so the list doesn't get onelined ]; +/// Minimum version threshold for libstdc++ required when using prebuilt LLVM +/// from CI (with`llvm.download-ci-llvm` option). +const LIBSTDCXX_MIN_VERSION_THRESHOLD: usize = 8; + impl Finder { pub fn new() -> Self { Self { cache: HashMap::new(), path: env::var_os("PATH").unwrap_or_default() } @@ -102,6 +107,35 @@ pub fn check(build: &mut Build) { cmd_finder.must_have("git"); } + // Ensure that a compatible version of libstdc++ is available on the system when using `llvm.download-ci-llvm`. + if !build.config.dry_run() && !build.build.is_msvc() && build.config.llvm_from_ci { + let builder = Builder::new(build); + let libcxx_version = builder.ensure(tool::LibcxxVersionTool { target: build.build }); + + match libcxx_version { + tool::LibcxxVersion::Gnu(version) => { + if LIBSTDCXX_MIN_VERSION_THRESHOLD > version { + eprintln!( + "\nYour system's libstdc++ version is too old for the `llvm.download-ci-llvm` option." + ); + eprintln!("Current version detected: '{}'", version); + eprintln!("Minimum required version: '{}'", LIBSTDCXX_MIN_VERSION_THRESHOLD); + eprintln!( + "Consider upgrading libstdc++ or disabling the `llvm.download-ci-llvm` option." + ); + crate::exit!(1); + } + } + tool::LibcxxVersion::Llvm(_) => { + eprintln!( + "\nYour system is using libc++, which is incompatible with the `llvm.download-ci-llvm` option." + ); + eprintln!("Disable `llvm.download-ci-llvm` or switch to libstdc++."); + crate::exit!(1); + } + } + } + // We need cmake, but only if we're actually building LLVM or sanitizers. let building_llvm = build .hosts From 1a07e58c0997e17cf62150ebc2bbf3af6ea4e807 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 23 May 2024 12:05:24 +0300 Subject: [PATCH 138/154] register libcxx-version in triagebot Signed-off-by: onur-ozkan --- triagebot.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 23e5c0a27f3a..55f63ef2567c 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -330,6 +330,7 @@ trigger_files = [ "src/tools/compiletest", "src/tools/tidy", "src/tools/rustdoc-gui-test", + "src/tools/libcxx-version", ] [autolabel."T-infra"] @@ -1117,6 +1118,7 @@ project-exploit-mitigations = [ "/src/tools/tidy" = ["bootstrap"] "/src/tools/x" = ["bootstrap"] "/src/tools/rustdoc-gui-test" = ["bootstrap", "@onur-ozkan"] +"/src/tools/libcxx-version" = ["@onur-ozkan"] # Enable tracking of PR review assignment # Documentation at: https://forge.rust-lang.org/triagebot/pr-assignment-tracking.html From a2407e84481fbbadd6d8d8e80726fa599533c465 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 23 May 2024 12:59:58 +0300 Subject: [PATCH 139/154] skip `src/tools/libcxx-version` from tidy Signed-off-by: onur-ozkan --- src/tools/libcxx-version/main.cpp | 2 -- src/tools/tidy/src/walk.rs | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/libcxx-version/main.cpp b/src/tools/libcxx-version/main.cpp index d12078abbb83..79df7ef457c4 100644 --- a/src/tools/libcxx-version/main.cpp +++ b/src/tools/libcxx-version/main.cpp @@ -4,8 +4,6 @@ // // It's nothing more than specifying the name of the standard library implementation (either libstdc++ or libc++) // and its major version. -// -// ignore-tidy-linelength #include diff --git a/src/tools/tidy/src/walk.rs b/src/tools/tidy/src/walk.rs index f68b7675c769..63a038341665 100644 --- a/src/tools/tidy/src/walk.rs +++ b/src/tools/tidy/src/walk.rs @@ -16,6 +16,7 @@ pub fn filter_dirs(path: &Path) -> bool { "library/stdarch", "src/tools/cargo", "src/tools/clippy", + "src/tools/libcxx-version", "src/tools/miri", "src/tools/rust-analyzer", "src/tools/rustc-perf", From 6bfdb040d95739e09b3067e5d09543030726aeb3 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 28 May 2024 08:18:35 +0300 Subject: [PATCH 140/154] add FIXME on libcxx check Signed-off-by: onur-ozkan --- src/bootstrap/src/core/sanity.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 6595c599eb1c..ff0c36f11441 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -127,11 +127,7 @@ pub fn check(build: &mut Build) { } } tool::LibcxxVersion::Llvm(_) => { - eprintln!( - "\nYour system is using libc++, which is incompatible with the `llvm.download-ci-llvm` option." - ); - eprintln!("Disable `llvm.download-ci-llvm` or switch to libstdc++."); - crate::exit!(1); + // FIXME: Handle libc++ version check. } } } From dd9902118c0cbbcfc35c246673b381072ac5b3a8 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 6 Jun 2024 07:06:51 +0300 Subject: [PATCH 141/154] use `bootstrap-self-test` feature on libstd check Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/tool.rs | 2 +- src/bootstrap/src/core/sanity.rs | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 4f7efcb05d89..05b19c0a6e33 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -810,10 +810,10 @@ pub struct LibcxxVersionTool { pub target: TargetSelection, } +#[allow(dead_code)] #[derive(Debug, Clone)] pub enum LibcxxVersion { Gnu(usize), - #[allow(dead_code)] Llvm(usize), } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index ff0c36f11441..e3556cb16b05 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -15,11 +15,14 @@ use std::fs; use std::path::PathBuf; use std::process::Command; +#[cfg(not(feature = "bootstrap-self-test"))] +use crate::builder::Builder; +#[cfg(not(feature = "bootstrap-self-test"))] +use crate::core::build_steps::tool; #[cfg(not(feature = "bootstrap-self-test"))] use std::collections::HashSet; -use crate::builder::{Builder, Kind}; -use crate::core::build_steps::tool; +use crate::builder::Kind; use crate::core::config::Target; use crate::utils::helpers::output; use crate::Build; @@ -41,6 +44,7 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[ /// Minimum version threshold for libstdc++ required when using prebuilt LLVM /// from CI (with`llvm.download-ci-llvm` option). +#[cfg(not(feature = "bootstrap-self-test"))] const LIBSTDCXX_MIN_VERSION_THRESHOLD: usize = 8; impl Finder { @@ -108,6 +112,7 @@ pub fn check(build: &mut Build) { } // Ensure that a compatible version of libstdc++ is available on the system when using `llvm.download-ci-llvm`. + #[cfg(not(feature = "bootstrap-self-test"))] if !build.config.dry_run() && !build.build.is_msvc() && build.config.llvm_from_ci { let builder = Builder::new(build); let libcxx_version = builder.ensure(tool::LibcxxVersionTool { target: build.build }); From 878107436a2c4ca60f1e87246fdb3480e1f2058b Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 5 Jun 2024 23:06:15 -0700 Subject: [PATCH 142/154] Raise `DEFAULT_MIN_STACK_SIZE` to at least 64KiB Prevent copy-paste errors from producing new starved-for-resources threaded platforms by raising `DEFAULT_MIN_STACK_SIZE` from 4096 bytes to at least 64KiB. Two platforms "affected" by this have no actual threads: - UEFI - "unsupported" Platforms that this actually affects: - wasm32-wasi with "atomics" enabled - wasm32-wasi-p1-threads Two exceptions: - SGX: a "secure code execution" platform, stays at 4096B - TEEOS: also a "secure code execution" platform, stays at 8192B I believe either of these may have sufficiently "interesting" semantics around threads, or significant external library support. Either would mean making any choices here for them is suspect. --- library/std/src/sys/pal/uefi/thread.rs | 2 +- library/std/src/sys/pal/unsupported/thread.rs | 2 +- library/std/src/sys/pal/wasi/thread.rs | 2 +- library/std/src/sys/pal/wasm/atomics/thread.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/std/src/sys/pal/uefi/thread.rs b/library/std/src/sys/pal/uefi/thread.rs index edc736978a12..7d4006ff4b2f 100644 --- a/library/std/src/sys/pal/uefi/thread.rs +++ b/library/std/src/sys/pal/uefi/thread.rs @@ -7,7 +7,7 @@ use crate::time::Duration; pub struct Thread(!); -pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; +pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements diff --git a/library/std/src/sys/pal/unsupported/thread.rs b/library/std/src/sys/pal/unsupported/thread.rs index ea939247199c..89f8bad7026e 100644 --- a/library/std/src/sys/pal/unsupported/thread.rs +++ b/library/std/src/sys/pal/unsupported/thread.rs @@ -6,7 +6,7 @@ use crate::time::Duration; pub struct Thread(!); -pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; +pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements diff --git a/library/std/src/sys/pal/wasi/thread.rs b/library/std/src/sys/pal/wasi/thread.rs index d45fb28b67e6..975eef2451f4 100644 --- a/library/std/src/sys/pal/wasi/thread.rs +++ b/library/std/src/sys/pal/wasi/thread.rs @@ -66,7 +66,7 @@ cfg_if::cfg_if! { } } -pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; +pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements diff --git a/library/std/src/sys/pal/wasm/atomics/thread.rs b/library/std/src/sys/pal/wasm/atomics/thread.rs index 49f936f14498..484bd08495ee 100644 --- a/library/std/src/sys/pal/wasm/atomics/thread.rs +++ b/library/std/src/sys/pal/wasm/atomics/thread.rs @@ -6,7 +6,7 @@ use crate::time::Duration; pub struct Thread(!); -pub const DEFAULT_MIN_STACK_SIZE: usize = 4096; +pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024; impl Thread { // unsafe: see thread::Builder::spawn_unchecked for safety requirements From 46b31e6630f4ceb5c5ecb1c85758685196e2ab06 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 6 Jun 2024 08:37:27 +0200 Subject: [PATCH 143/154] Update to LLVM 18.1.7 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index b31c30a9bb4d..5a5152f65395 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit b31c30a9bb4dbbd13c359d0e2bea7f65d20adf3f +Subproject commit 5a5152f653959d14d68613a3a8a033fb65eec021 From 7ad5ebc75c44b271e3a14cbe3a138e38d0bd39d3 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 6 Jun 2024 10:19:15 +0200 Subject: [PATCH 144/154] Migrate `run-make/manual-crate-name` to `rmake.rs` --- src/tools/tidy/src/allowed_run_make_makefiles.txt | 1 - tests/run-make/manual-crate-name/Makefile | 5 ----- tests/run-make/manual-crate-name/rmake.rs | 6 ++++++ 3 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 tests/run-make/manual-crate-name/Makefile create mode 100644 tests/run-make/manual-crate-name/rmake.rs diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index 600ca06fcdf3..51f0e99e5d07 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -136,7 +136,6 @@ run-make/lto-readonly-lib/Makefile run-make/lto-smoke-c/Makefile run-make/macos-deployment-target/Makefile run-make/macos-fat-archive/Makefile -run-make/manual-crate-name/Makefile run-make/manual-link/Makefile run-make/many-crates-but-no-match/Makefile run-make/metadata-dep-info/Makefile diff --git a/tests/run-make/manual-crate-name/Makefile b/tests/run-make/manual-crate-name/Makefile deleted file mode 100644 index c00e20c7c57d..000000000000 --- a/tests/run-make/manual-crate-name/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -include ../tools.mk - -all: - $(RUSTC) --crate-name foo bar.rs - rm $(TMPDIR)/libfoo.rlib diff --git a/tests/run-make/manual-crate-name/rmake.rs b/tests/run-make/manual-crate-name/rmake.rs new file mode 100644 index 000000000000..531f531abd26 --- /dev/null +++ b/tests/run-make/manual-crate-name/rmake.rs @@ -0,0 +1,6 @@ +use run_make_support::{rustc, tmp_dir}; + +fn main() { + rustc().input("bar.rs").crate_name("foo").run(); + assert!(tmp_dir().join("libfoo.rlib").is_file()); +} From c7ced1ba5305277673c3db45a183693577761734 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 6 Sep 2023 10:46:54 +0000 Subject: [PATCH 145/154] Make the panic info more useful --- compiler/rustc_macros/src/query.rs | 21 +++++++++++++++++-- .../rustc_query_system/src/dep_graph/graph.rs | 3 +-- src/tools/compiletest/src/runtest.rs | 1 + 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 25675e06e38d..ceff1da97636 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -314,6 +314,17 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { let mut query_description_stream = quote! {}; let mut query_cached_stream = quote! {}; let mut feedable_queries = quote! {}; + let mut errors = quote! {}; + + macro_rules! assert { + ( $cond:expr, $span:expr, $( $tt:tt )+ ) => { + if !$cond { + errors.extend( + Error::new($span, format!($($tt)+)).into_compile_error(), + ); + } + } + } for query in queries.0 { let Query { name, arg, modifiers, .. } = &query; @@ -369,10 +380,15 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { [#attribute_stream] fn #name(#arg) #result, }); - if modifiers.feedable.is_some() { - assert!(modifiers.anon.is_none(), "Query {name} cannot be both `feedable` and `anon`."); + if let Some(feedable) = &modifiers.feedable { + assert!( + modifiers.anon.is_none(), + feedable.span(), + "Query {name} cannot be both `feedable` and `anon`." + ); assert!( modifiers.eval_always.is_none(), + feedable.span(), "Query {name} cannot be both `feedable` and `eval_always`." ); feedable_queries.extend(quote! { @@ -407,5 +423,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { use super::*; #query_cached_stream } + #errors }) } diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs index 76227a78c3d6..66fb3136805e 100644 --- a/compiler/rustc_query_system/src/dep_graph/graph.rs +++ b/compiler/rustc_query_system/src/dep_graph/graph.rs @@ -64,7 +64,6 @@ pub struct MarkFrame<'a> { parent: Option<&'a MarkFrame<'a>>, } -#[derive(PartialEq)] enum DepNodeColor { Red, Green(DepNodeIndex), @@ -925,7 +924,7 @@ impl DepGraph { /// Returns true if the given node has been marked as red during the /// current compilation session. Used in various assertions pub fn is_red(&self, dep_node: &DepNode) -> bool { - self.node_color(dep_node) == Some(DepNodeColor::Red) + matches!(self.node_color(dep_node), Some(DepNodeColor::Red)) } /// Returns true if the given node has been marked as green during the diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 9bd0002a3d9a..3464e1893d03 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2469,6 +2469,7 @@ impl<'test> TestCx<'test> { } } + #[track_caller] fn fatal(&self, err: &str) -> ! { self.error(err); error!("fatal error, panic: {:?}", err); From 0a4176a8316332e37bd08741cc71a4773214941e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 6 Jun 2024 09:45:50 +0000 Subject: [PATCH 146/154] Revert "Rollup merge of #124976 - petrochenkov:usedcrates, r=oli-obk" This reverts commit eda4a35f365535af72118118a3597edf5a13c12d, reversing changes made to eb6b35b5bcb3c2a594cb29cd478aeb2893f49d30. --- .../rustc_codegen_ssa/src/back/symbol_export.rs | 2 +- compiler/rustc_codegen_ssa/src/base.rs | 4 ++-- compiler/rustc_interface/src/passes.rs | 2 +- .../rustc_metadata/src/dependency_format.rs | 12 ++++++------ .../src/rmeta/decoder/cstore_impl.rs | 4 ++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/hir/map/mod.rs | 6 +++--- compiler/rustc_middle/src/query/mod.rs | 17 ++++------------- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- compiler/rustc_middle/src/ty/trait_def.rs | 4 ++-- compiler/rustc_passes/src/diagnostic_items.rs | 2 +- compiler/rustc_passes/src/stability.rs | 4 ++-- compiler/rustc_passes/src/weak_lang_items.rs | 2 +- compiler/rustc_smir/src/rustc_smir/context.rs | 11 +++-------- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/core.rs | 2 +- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/passes/collect_trait_impls.rs | 2 +- src/librustdoc/scrape_examples.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- src/tools/miri/src/helpers.rs | 4 ++-- tests/ui/extern-flag/empty-extern-arg.stderr | 9 ++++++++- 23 files changed, 47 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 79d6641a0da1..a6df8950b351 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -400,7 +400,7 @@ fn upstream_monomorphizations_provider( tcx: TyCtxt<'_>, (): (), ) -> DefIdMap, CrateNum>> { - let cnums = tcx.used_crates(()); + let cnums = tcx.crates(()); let mut instances: DefIdMap> = Default::default(); diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index f372d3a05226..0b450c43924e 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -541,7 +541,7 @@ pub fn collect_debugger_visualizers_transitive( tcx.debugger_visualizers(LOCAL_CRATE) .iter() .chain( - tcx.used_crates(()) + tcx.crates(()) .iter() .filter(|&cnum| { let used_crate_source = tcx.used_crate_source(*cnum); @@ -851,7 +851,7 @@ impl CrateInfo { // `compiler_builtins` are always placed last to ensure that they're linked correctly. used_crates.extend(compiler_builtins); - let crates = tcx.used_crates(()); + let crates = tcx.crates(()); let n_crates = crates.len(); let mut info = CrateInfo { target_cpu, diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index a342577cffb8..d52286d5887d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -464,7 +464,7 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P } } - for &cnum in tcx.crates_including_speculative(()) { + for &cnum in tcx.crates(()) { let source = tcx.used_crate_source(cnum); if let Some((path, _)) = &source.dylib { files.push(escape_dep_filename(&path.display().to_string())); diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index bf9bbfb8cfab..9c69ab2344e5 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -144,7 +144,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { && sess.crt_static(Some(ty)) && !sess.target.crt_static_allows_dylibs) { - for &cnum in tcx.used_crates(()).iter() { + for &cnum in tcx.crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -165,7 +165,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // Sweep all crates for found dylibs. Add all dylibs, as well as their // dependencies, ensuring there are no conflicts. The only valid case for a // dependency to be relied upon twice is for both cases to rely on a dylib. - for &cnum in tcx.used_crates(()).iter() { + for &cnum in tcx.crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { continue; } @@ -183,7 +183,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { } // Collect what we've got so far in the return vector. - let last_crate = tcx.used_crates(()).len(); + let last_crate = tcx.crates(()).len(); let mut ret = (1..last_crate + 1) .map(|cnum| match formats.get(&CrateNum::new(cnum)) { Some(&RequireDynamic) => Linkage::Dynamic, @@ -197,7 +197,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // // If the crate hasn't been included yet and it's not actually required // (e.g., it's an allocator) then we skip it here as well. - for &cnum in tcx.used_crates(()).iter() { + for &cnum in tcx.crates(()).iter() { let src = tcx.used_crate_source(cnum); if src.dylib.is_none() && !formats.contains_key(&cnum) @@ -285,7 +285,7 @@ fn add_library( fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec) -> Option { let all_crates_available_as_rlib = tcx - .used_crates(()) + .crates(()) .iter() .copied() .filter_map(|cnum| { @@ -306,7 +306,7 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec) -> Option Linkage::Static, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f6b9c7ed9926..afee8d5646c8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -439,7 +439,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { // traversal, but not globally minimal across all crates. let bfs_queue = &mut VecDeque::new(); - for &cnum in tcx.crates_including_speculative(()) { + for &cnum in tcx.crates(()) { // Ignore crates without a corresponding local `extern crate` item. if tcx.missing_extern_crate_item(cnum) { continue; @@ -509,7 +509,7 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { tcx.arena .alloc_slice(&CStore::from_tcx(tcx).crate_dependencies_in_postorder(LOCAL_CRATE)) }, - crates_including_speculative: |tcx, ()| { + crates: |tcx, ()| { // The list of loaded crates is now frozen in query cache, // so make sure cstore is not mutably accessed from here on. tcx.untracked().cstore.freeze(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4f186981a76f..67c5bc8c786b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1899,7 +1899,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let deps = self .tcx - .crates_including_speculative(()) + .crates(()) .iter() .map(|&cnum| { let dep = CrateDep { diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 639c98155e70..3be2af417bfd 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -1040,7 +1040,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { let krate = tcx.hir_crate(()); let hir_body_hash = krate.opt_hir_hash.expect("HIR hash missing while computing crate hash"); - let upstream_crates = upstream_crates_for_hashing(tcx); + let upstream_crates = upstream_crates(tcx); let resolutions = tcx.resolutions(()); @@ -1109,9 +1109,9 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { Svh::new(crate_hash) } -fn upstream_crates_for_hashing(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { +fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { let mut upstream_crates: Vec<_> = tcx - .crates_including_speculative(()) + .crates(()) .iter() .map(|&cnum| { let stable_crate_id = tcx.stable_crate_id(cnum); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 3c4aae73bc49..0af32a6a8578 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1861,22 +1861,13 @@ rustc_queries! { eval_always desc { "calculating the stability index for the local crate" } } - /// All loaded crates, including those loaded purely for doc links or diagnostics. - /// (Diagnostics include lints, so speculatively loaded crates may occur in successful - /// compilation even without doc links.) - /// Should be used when encoding crate metadata (and therefore when generating crate hash, - /// depinfo and similar things), to avoid dangling crate references in other encoded data, - /// like source maps. - /// May also be used for diagnostics - if we are loading a crate anyway we can suggest some - /// items from it as well. - /// But otherwise, `used_crates` should generally be used. - query crates_including_speculative(_: ()) -> &'tcx [CrateNum] { + query crates(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching all foreign CrateNum instances" } } - /// Crates that are loaded non-speculatively (not for diagnostics or doc links). - /// Should be used to maintain observable language behavior, for example when collecting lang - /// items or impls from all crates, or collecting libraries to link. + // Crates that are loaded non-speculatively (not for diagnostics or doc links). + // FIXME: This is currently only used for collecting lang items, but should be used instead of + // `crates` in most other cases too. query used_crates(_: ()) -> &'tcx [CrateNum] { eval_always desc { "fetching `CrateNum`s for all crates loaded non-speculatively" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f9a22aa72bee..6b35b1f2d13c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1616,7 +1616,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn all_traits(self) -> impl Iterator + 'tcx { iter::once(LOCAL_CRATE) - .chain(self.used_crates(()).iter().copied()) + .chain(self.crates(()).iter().copied()) .flat_map(move |cnum| self.traits(cnum).iter().copied()) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3cfebaa6b57e..49d46eb3c4bf 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3232,7 +3232,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N let queue = &mut Vec::new(); let mut seen_defs: DefIdSet = Default::default(); - for &cnum in tcx.crates_including_speculative(()).iter() { + for &cnum in tcx.crates(()).iter() { let def_id = cnum.as_def_id(); // Ignore crates that are not direct dependencies. diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 37a34f283387..4dba97c3b5b8 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -206,7 +206,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait // Traits defined in the current crate can't have impls in upstream // crates, so we don't bother querying the cstore. if !trait_id.is_local() { - for &cnum in tcx.used_crates(()).iter() { + for &cnum in tcx.crates(()).iter() { for &(impl_def_id, simplified_self_ty) in tcx.implementations_of_trait((cnum, trait_id)).iter() { @@ -248,7 +248,7 @@ pub(super) fn incoherent_impls_provider( let mut impls = Vec::new(); let mut res = Ok(()); - for cnum in iter::once(LOCAL_CRATE).chain(tcx.used_crates(()).iter().copied()) { + for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) { let incoherent_impls = match tcx.crate_incoherent_impls((cnum, simp)) { Ok(impls) => impls, Err(e) => { diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 78653e5f95a6..906ecdfe5aba 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -82,7 +82,7 @@ fn all_diagnostic_items(tcx: TyCtxt<'_>, (): ()) -> DiagnosticItems { let mut items = DiagnosticItems::default(); // Collect diagnostic items in other crates. - for &cnum in tcx.crates_including_speculative(()).iter().chain(std::iter::once(&LOCAL_CRATE)) { + for &cnum in tcx.crates(()).iter().chain(std::iter::once(&LOCAL_CRATE)) { for (&name, &def_id) in &tcx.diagnostic_items(cnum).name_to_id { collect_item(tcx, &mut items, name, def_id); } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 31c709f2eb68..6bdfaf0c9089 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -1020,7 +1020,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { // stabilization diagnostic, but it can be avoided when there are no // `remaining_lib_features`. let mut all_implications = remaining_implications.clone(); - for &cnum in tcx.used_crates(()) { + for &cnum in tcx.crates(()) { all_implications .extend_unord(tcx.stability_implications(cnum).items().map(|(k, v)| (*k, *v))); } @@ -1033,7 +1033,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { &all_implications, ); - for &cnum in tcx.used_crates(()) { + for &cnum in tcx.crates(()) { if remaining_lib_features.is_empty() && remaining_implications.is_empty() { break; } diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index d80addf12364..90691ca17908 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -68,7 +68,7 @@ fn verify(tcx: TyCtxt<'_>, items: &lang_items::LanguageItems) { } let mut missing = FxHashSet::default(); - for &cnum in tcx.used_crates(()).iter() { + for &cnum in tcx.crates(()).iter() { for &item in tcx.missing_lang_items(cnum).iter() { missing.insert(item); } diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs index 8b09c5aef2f9..a8688c88601c 100644 --- a/compiler/rustc_smir/src/rustc_smir/context.rs +++ b/compiler/rustc_smir/src/rustc_smir/context.rs @@ -126,7 +126,7 @@ impl<'tcx> Context for TablesWrapper<'tcx> { let mut tables = self.0.borrow_mut(); let tcx = tables.tcx; iter::once(LOCAL_CRATE) - .chain(tables.tcx.used_crates(()).iter().copied()) + .chain(tables.tcx.crates(()).iter().copied()) .flat_map(|cnum| tcx.trait_impls_in_crate(cnum).iter()) .map(|impl_def_id| tables.impl_def(*impl_def_id)) .collect() @@ -201,19 +201,14 @@ impl<'tcx> Context for TablesWrapper<'tcx> { fn external_crates(&self) -> Vec { let tables = self.0.borrow(); - tables - .tcx - .used_crates(()) - .iter() - .map(|crate_num| smir_crate(tables.tcx, *crate_num)) - .collect() + 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(tables.tcx.used_crates(()).iter()) + .chain(tables.tcx.crates(()).iter()) .filter_map(|crate_num| { let crate_name = tables.tcx.crate_name(*crate_num).to_string(); (name == crate_name).then(|| smir_crate(tables.tcx, *crate_num)) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 28d3d5644432..69678b727c11 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -1936,7 +1936,7 @@ impl PrimitiveType { let mut primitive_locations = FxHashMap::default(); // NOTE: technically this misses crates that are only passed with `--extern` and not loaded when checking the crate. // This is a degenerate case that I don't plan to support. - for &crate_num in tcx.crates_including_speculative(()) { + for &crate_num in tcx.crates(()) { let e = ExternalCrate { crate_num }; let crate_name = e.name(tcx); debug!(?crate_num, ?crate_name); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index ccd5dadb20a0..ce098a1bcfbf 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -347,7 +347,7 @@ pub(crate) fn run_global_ctxt( show_coverage, }; - for cnum in tcx.crates_including_speculative(()) { + for cnum in tcx.crates(()) { crate::visit_lib::lib_embargo_visit_item(&mut ctxt, cnum.as_def_id()); } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 28ddf76a3a69..a3b88a880f2a 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -155,7 +155,7 @@ impl Cache { // Cache where all our extern crates are located // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code - for &crate_num in tcx.crates_including_speculative(()) { + for &crate_num in tcx.crates(()) { let e = ExternalCrate { crate_num }; let name = e.name(tcx); diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 22daac9efb15..c92cf9d3e80d 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -47,7 +47,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> // External trait impls. { let _prof_timer = tcx.sess.prof.generic_activity("build_extern_trait_impls"); - for &cnum in tcx.crates_including_speculative(()) { + for &cnum in tcx.crates(()) { for &impl_def_id in tcx.trait_impls_in_crate(cnum) { cx.with_param_env(impl_def_id, |cx| { inline::build_impl(cx, impl_def_id, None, &mut new_items_external); diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index 64753a58a2bf..e9b380fdeac6 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -283,7 +283,7 @@ pub(crate) fn run( // Collect CrateIds corresponding to provided target crates // If two different versions of the crate in the dependency tree, then examples will be collected from both. let all_crates = tcx - .crates_including_speculative(()) + .crates(()) .iter() .chain([&LOCAL_CRATE]) .map(|crate_num| (crate_num, tcx.crate_name(*crate_num))) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 1147dce6215f..2f6bf9209677 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -647,7 +647,7 @@ fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec, path: &[&str]) -> Vec { fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator + '_ { - tcx.crates_including_speculative(()) + tcx.crates(()) .iter() .copied() .filter(move |&num| tcx.crate_name(num) == name) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 5c3b8f2d2a05..c3282c1af036 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -126,7 +126,7 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option) // the one in the sysroot and the one locally built by `cargo test`.) // FIXME: can we prefer the one from the sysroot? 'crates: for krate in - tcx.used_crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name) + tcx.crates(()).iter().filter(|&&krate| tcx.crate_name(krate).as_str() == crate_name) { let mut cur_item = DefId { krate: *krate, index: CRATE_DEF_INDEX }; // Go over the modules. @@ -1364,7 +1364,7 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec { .map(|crates| crates.split(',').map(|krate| krate.to_string()).collect::>()) .unwrap_or_default(); let mut local_crates = Vec::new(); - for &crate_num in tcx.crates_including_speculative(()) { + for &crate_num in tcx.crates(()) { let name = tcx.crate_name(crate_num); let name = name.as_str(); if local_crate_names.iter().any(|local_name| local_name == name) { diff --git a/tests/ui/extern-flag/empty-extern-arg.stderr b/tests/ui/extern-flag/empty-extern-arg.stderr index 6ad3effe0e26..2785b12a0aef 100644 --- a/tests/ui/extern-flag/empty-extern-arg.stderr +++ b/tests/ui/extern-flag/empty-extern-arg.stderr @@ -1,6 +1,13 @@ error: extern location for std does not exist: +error: `#[panic_handler]` function required, but not found + +error: unwinding panics are not supported without std + | + = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding + = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem + error: requires `sized` lang_item -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors From 9ddf5726f00707015a622a33733c7a8c60cb22fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Wed, 29 May 2024 09:29:16 +0000 Subject: [PATCH 147/154] add non-regression run-make test for issues 125474, 125484, and 125646 --- .../dependency.rs | 1 + .../issue-125484-used-dependencies/main.rs | 9 +++++++++ .../issue-125484-used-dependencies/rmake.rs | 18 ++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 tests/run-make/issue-125484-used-dependencies/dependency.rs create mode 100644 tests/run-make/issue-125484-used-dependencies/main.rs create mode 100644 tests/run-make/issue-125484-used-dependencies/rmake.rs diff --git a/tests/run-make/issue-125484-used-dependencies/dependency.rs b/tests/run-make/issue-125484-used-dependencies/dependency.rs new file mode 100644 index 000000000000..d15abba59766 --- /dev/null +++ b/tests/run-make/issue-125484-used-dependencies/dependency.rs @@ -0,0 +1 @@ +// Empty diff --git a/tests/run-make/issue-125484-used-dependencies/main.rs b/tests/run-make/issue-125484-used-dependencies/main.rs new file mode 100644 index 000000000000..0c1a1f8208ad --- /dev/null +++ b/tests/run-make/issue-125484-used-dependencies/main.rs @@ -0,0 +1,9 @@ +pub type Foo = something::same::Thing; + +mod something { + pub mod same { + pub struct Thing; + } +} + +fn main() {} diff --git a/tests/run-make/issue-125484-used-dependencies/rmake.rs b/tests/run-make/issue-125484-used-dependencies/rmake.rs new file mode 100644 index 000000000000..b75e82b42db7 --- /dev/null +++ b/tests/run-make/issue-125484-used-dependencies/rmake.rs @@ -0,0 +1,18 @@ +// Non-regression test for issues #125474, #125484, #125646, with the repro taken from #125484. Some +// queries use "used dependencies" while others use "speculatively loaded dependencies", and an +// indexing ICE appeared in some cases when these were unexpectedly used in the same context. + +// FIXME: this should probably be a UI test instead of a run-make test, but I *cannot* find a way to +// make compiletest annotations reproduce the ICE with the minimizations from issues #125474 and +// #125484. + +use run_make_support::{rustc, tmp_dir}; + +fn main() { + // The dependency is not itself significant, apart from sharing a name with one of main's + // modules. + rustc().crate_name("same").crate_type("rlib").input("dependency.rs").run(); + + // Here, an ICE would happen when building the linker command. + rustc().input("main.rs").extern_("same", tmp_dir().join("libsame.rlib")).run(); +} From dc91ad05e374c0f5de7f669e5003c2ab9ceaaf46 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jun 2024 17:31:01 +1000 Subject: [PATCH 148/154] Port `tests/run-make-fulldeps/obtain-borrowck` to ui-fulldeps --- .../obtain-borrowck/Makefile | 26 ------------------- .../auxiliary/obtain-borrowck-input.rs} | 2 ++ .../obtain-borrowck.rs} | 7 +++++ .../obtain-borrowck.run.stdout} | 0 4 files changed, 9 insertions(+), 26 deletions(-) delete mode 100644 tests/run-make-fulldeps/obtain-borrowck/Makefile rename tests/{run-make-fulldeps/obtain-borrowck/test.rs => ui-fulldeps/auxiliary/obtain-borrowck-input.rs} (94%) rename tests/{run-make-fulldeps/obtain-borrowck/driver.rs => ui-fulldeps/obtain-borrowck.rs} (96%) rename tests/{run-make-fulldeps/obtain-borrowck/output.stdout => ui-fulldeps/obtain-borrowck.run.stdout} (100%) diff --git a/tests/run-make-fulldeps/obtain-borrowck/Makefile b/tests/run-make-fulldeps/obtain-borrowck/Makefile deleted file mode 100644 index 233f5c9eaf49..000000000000 --- a/tests/run-make-fulldeps/obtain-borrowck/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -include ../../run-make/tools.mk - -# This example shows how to implement a rustc driver that retrieves MIR bodies -# together with the borrow checker information. - -# How to run this -# $ ./x.py test tests/run-make-fulldeps/obtain-borrowck - -DRIVER_BINARY := "$(TMPDIR)"/driver -SYSROOT := $(shell $(RUSTC) --print sysroot) - -ifdef IS_WINDOWS -LIBSTD := -L "$(SYSROOT)\\lib\\rustlib\\$(TARGET)\\lib" -else -LIBSTD := -endif - -all: - $(RUSTC) driver.rs -o "$(DRIVER_BINARY)" - $(TARGET_RPATH_ENV) "$(DRIVER_BINARY)" --sysroot $(SYSROOT) $(LIBSTD) test.rs -o "$(TMPDIR)/driver_test" > "$(TMPDIR)"/output.stdout - -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/output.stdout output.stdout -else - $(DIFF) output.stdout "$(TMPDIR)"/output.stdout -endif diff --git a/tests/run-make-fulldeps/obtain-borrowck/test.rs b/tests/ui-fulldeps/auxiliary/obtain-borrowck-input.rs similarity index 94% rename from tests/run-make-fulldeps/obtain-borrowck/test.rs rename to tests/ui-fulldeps/auxiliary/obtain-borrowck-input.rs index f7b4b41feaf9..7213e06792a4 100644 --- a/tests/run-make-fulldeps/obtain-borrowck/test.rs +++ b/tests/ui-fulldeps/auxiliary/obtain-borrowck-input.rs @@ -1,3 +1,5 @@ +#![allow(dead_code)] + trait X { fn provided(&self) -> usize { 5 diff --git a/tests/run-make-fulldeps/obtain-borrowck/driver.rs b/tests/ui-fulldeps/obtain-borrowck.rs similarity index 96% rename from tests/run-make-fulldeps/obtain-borrowck/driver.rs rename to tests/ui-fulldeps/obtain-borrowck.rs index e67ec8690f81..e6c703addd92 100644 --- a/tests/run-make-fulldeps/obtain-borrowck/driver.rs +++ b/tests/ui-fulldeps/obtain-borrowck.rs @@ -1,3 +1,10 @@ +//@ edition: 2021 +//@ run-pass +//@ check-run-results +//@ run-flags: --sysroot {{sysroot-base}} --edition=2021 {{src-base}}/auxiliary/obtain-borrowck-input.rs +//@ ignore-stage1 (requires matching sysroot built with in-tree compiler) +// ignore-tidy-linelength + #![feature(rustc_private)] //! This program implements a rustc driver that retrieves MIR bodies with diff --git a/tests/run-make-fulldeps/obtain-borrowck/output.stdout b/tests/ui-fulldeps/obtain-borrowck.run.stdout similarity index 100% rename from tests/run-make-fulldeps/obtain-borrowck/output.stdout rename to tests/ui-fulldeps/obtain-borrowck.run.stdout From 2692d44d8300592d575f81f6f05d0bab8aeabf62 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jun 2024 18:16:14 +1000 Subject: [PATCH 149/154] compiletest: Allow multiple `//@ run-flags:` headers --- src/tools/compiletest/src/header.rs | 8 +++++--- src/tools/compiletest/src/runtest.rs | 10 ++++++---- src/tools/rustdoc-gui-test/src/main.rs | 4 +--- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 91d11c1ae171..736e103fdf22 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -94,7 +94,7 @@ pub struct TestProps { // Extra flags to pass to the compiler pub compile_flags: Vec, // Extra flags to pass when the compiled code is run (such as --bench) - pub run_flags: Option, + pub run_flags: Vec, // If present, the name of a file that this test should match when // pretty-printed pub pp_exact: Option, @@ -262,7 +262,7 @@ impl TestProps { error_patterns: vec![], regex_error_patterns: vec![], compile_flags: vec![], - run_flags: None, + run_flags: vec![], pp_exact: None, aux_builds: vec![], aux_bins: vec![], @@ -399,7 +399,9 @@ impl TestProps { config.parse_and_update_revisions(ln, &mut self.revisions); - config.set_name_value_directive(ln, RUN_FLAGS, &mut self.run_flags, |r| r); + if let Some(flags) = config.parse_name_value_directive(ln, RUN_FLAGS) { + self.run_flags.extend(split_flags(&flags)); + } if self.pp_exact.is_none() { self.pp_exact = config.parse_pp_exact(ln, testfile); diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 9bd0002a3d9a..05a038a1f092 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2355,7 +2355,7 @@ impl<'test> TestCx<'test> { args.push(exe_file.into_os_string()); // Add the arguments in the run_flags directive - args.extend(self.split_maybe_args(&self.props.run_flags)); + args.extend(self.props.run_flags.iter().map(OsString::from)); let prog = args.remove(0); ProcArgs { prog, args } @@ -4173,10 +4173,12 @@ impl<'test> TestCx<'test> { } fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String { - let rflags = self.props.run_flags.as_ref(); + // Crude heuristic to detect when the output should have JSON-specific + // normalization steps applied. + let rflags = self.props.run_flags.join(" "); let cflags = self.props.compile_flags.join(" "); - let json = rflags - .map_or(false, |s| s.contains("--format json") || s.contains("--format=json")) + let json = rflags.contains("--format json") + || rflags.contains("--format=json") || cflags.contains("--error-format json") || cflags.contains("--error-format pretty-json") || cflags.contains("--error-format=json") diff --git a/src/tools/rustdoc-gui-test/src/main.rs b/src/tools/rustdoc-gui-test/src/main.rs index 0ddd2c66cf9e..bf581279f2ac 100644 --- a/src/tools/rustdoc-gui-test/src/main.rs +++ b/src/tools/rustdoc-gui-test/src/main.rs @@ -123,9 +123,7 @@ If you want to install the `browser-ui-test` dependency, run `npm install browse cargo.env("RUSTDOCFLAGS", test_props.compile_flags.join(" ")); } - if let Some(flags) = &test_props.run_flags { - cargo.arg(flags); - } + cargo.args(&test_props.run_flags); } if try_run(&mut cargo, config.verbose).is_err() { From 9c46479a6ad881472c64a22ae033dca320e7213e Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Thu, 6 Jun 2024 20:13:39 +0300 Subject: [PATCH 150/154] use windows compatible executable name for libcxx-version Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/tool.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 05b19c0a6e33..1b55fc85da42 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -834,7 +834,7 @@ impl Step for LibcxxVersionTool { let compiler = builder.cxx(self.target).unwrap(); let mut cmd = Command::new(compiler); - let executable = out_dir.join("libcxx-version"); + let executable = out_dir.join(exe("libcxx-version", self.target)); cmd.arg("-o").arg(&executable).arg(builder.src.join("src/tools/libcxx-version/main.cpp")); builder.run_cmd(&mut cmd); From 6e1121b492b61ba5aab14004a9ef1227a1358c21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 6 Jun 2024 18:35:46 +0200 Subject: [PATCH 151/154] Do not use relative paths to Rust source root in run-make tests --- src/tools/run-make-support/src/lib.rs | 5 +++-- tests/run-make/alloc-no-oom-handling/rmake.rs | 4 ++-- tests/run-make/alloc-no-rc/rmake.rs | 4 ++-- tests/run-make/alloc-no-sync/rmake.rs | 4 ++-- tests/run-make/core-no-fp-fmt-parse/rmake.rs | 4 ++-- tests/run-make/core-no-oom-handling/rmake.rs | 4 ++-- tests/run-make/rustdoc-scrape-examples-remap/scrape.rs | 2 +- tests/run-make/rustdoc-themes/rmake.rs | 4 ++-- 8 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index d4b2f88fecfc..d74a0272a627 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -83,11 +83,12 @@ pub fn python_command() -> Command { pub fn htmldocck() -> Command { let mut python = python_command(); - python.arg(source_path().join("src/etc/htmldocck.py")); + python.arg(source_root().join("src/etc/htmldocck.py")); python } -pub fn source_path() -> PathBuf { +/// Path to the root rust-lang/rust source checkout. +pub fn source_root() -> PathBuf { env_var("S").into() } diff --git a/tests/run-make/alloc-no-oom-handling/rmake.rs b/tests/run-make/alloc-no-oom-handling/rmake.rs index 4bca5d1f1efb..89a6636d9a0c 100644 --- a/tests/run-make/alloc-no-oom-handling/rmake.rs +++ b/tests/run-make/alloc-no-oom-handling/rmake.rs @@ -2,14 +2,14 @@ // when the unstable no_global_oom_handling feature is turned on. // See https://github.com/rust-lang/rust/pull/84266 -use run_make_support::rustc; +use run_make_support::{rustc, source_root}; fn main() { rustc() .edition("2021") .arg("-Dwarnings") .crate_type("rlib") - .input("../../../library/alloc/src/lib.rs") + .input(source_root().join("library/alloc/src/lib.rs")) .cfg("no_global_oom_handling") .run(); } diff --git a/tests/run-make/alloc-no-rc/rmake.rs b/tests/run-make/alloc-no-rc/rmake.rs index 8ff73324b083..12171c2148f1 100644 --- a/tests/run-make/alloc-no-rc/rmake.rs +++ b/tests/run-make/alloc-no-rc/rmake.rs @@ -2,14 +2,14 @@ // when the unstable no_rc feature is turned on. // See https://github.com/rust-lang/rust/pull/84266 -use run_make_support::rustc; +use run_make_support::{rustc, source_root}; fn main() { rustc() .edition("2021") .arg("-Dwarnings") .crate_type("rlib") - .input("../../../library/alloc/src/lib.rs") + .input(source_root().join("library/alloc/src/lib.rs")) .cfg("no_rc") .run(); } diff --git a/tests/run-make/alloc-no-sync/rmake.rs b/tests/run-make/alloc-no-sync/rmake.rs index 3a3ceed68679..29f204f30673 100644 --- a/tests/run-make/alloc-no-sync/rmake.rs +++ b/tests/run-make/alloc-no-sync/rmake.rs @@ -2,14 +2,14 @@ // when the unstable no_sync feature is turned on. // See https://github.com/rust-lang/rust/pull/84266 -use run_make_support::rustc; +use run_make_support::{rustc, source_root}; fn main() { rustc() .edition("2021") .arg("-Dwarnings") .crate_type("rlib") - .input("../../../library/alloc/src/lib.rs") + .input(source_root().join("library/alloc/src/lib.rs")) .cfg("no_sync") .run(); } diff --git a/tests/run-make/core-no-fp-fmt-parse/rmake.rs b/tests/run-make/core-no-fp-fmt-parse/rmake.rs index aef28fd25281..3586922f28ec 100644 --- a/tests/run-make/core-no-fp-fmt-parse/rmake.rs +++ b/tests/run-make/core-no-fp-fmt-parse/rmake.rs @@ -1,14 +1,14 @@ // This test checks that the core library of Rust can be compiled without enabling // support for formatting and parsing floating-point numbers. -use run_make_support::rustc; +use run_make_support::{rustc, source_root}; fn main() { rustc() .edition("2021") .arg("-Dwarnings") .crate_type("rlib") - .input("../../../library/core/src/lib.rs") + .input(source_root().join("library/core/src/lib.rs")) .cfg("no_fp_fmt_parse") .run(); } diff --git a/tests/run-make/core-no-oom-handling/rmake.rs b/tests/run-make/core-no-oom-handling/rmake.rs index 75767421cd1f..3ebbf63ab7d6 100644 --- a/tests/run-make/core-no-oom-handling/rmake.rs +++ b/tests/run-make/core-no-oom-handling/rmake.rs @@ -2,14 +2,14 @@ // when the no_global_oom_handling feature is turned on. // See https://github.com/rust-lang/rust/pull/110649 -use run_make_support::{rustc, tmp_dir}; +use run_make_support::{rustc, source_root, tmp_dir}; fn main() { rustc() .edition("2021") .arg("-Dwarnings") .crate_type("rlib") - .input("../../../library/core/src/lib.rs") + .input(source_root().join("library/core/src/lib.rs")) .sysroot(tmp_dir().join("fakeroot")) .cfg("no_global_oom_handling") .run(); diff --git a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs index 563e3aca9aed..b372c25447d0 100644 --- a/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs +++ b/tests/run-make/rustdoc-scrape-examples-remap/scrape.rs @@ -1,4 +1,4 @@ -use run_make_support::{htmldocck, rustc, rustdoc, source_path, tmp_dir}; +use run_make_support::{htmldocck, rustc, rustdoc, source_root, tmp_dir}; use std::fs::read_dir; use std::path::Path; diff --git a/tests/run-make/rustdoc-themes/rmake.rs b/tests/run-make/rustdoc-themes/rmake.rs index e9da4e259400..d6ddd45b4a45 100644 --- a/tests/run-make/rustdoc-themes/rmake.rs +++ b/tests/run-make/rustdoc-themes/rmake.rs @@ -1,13 +1,13 @@ // Test that rustdoc will properly load in a theme file and display it in the theme selector. -use run_make_support::{htmldocck, rustdoc, source_path, tmp_dir}; +use run_make_support::{htmldocck, rustdoc, source_root, tmp_dir}; fn main() { let out_dir = tmp_dir().join("rustdoc-themes"); let test_css = out_dir.join("test.css"); let no_script = - std::fs::read_to_string(source_path().join("src/librustdoc/html/static/css/noscript.css")) + std::fs::read_to_string(source_root().join("src/librustdoc/html/static/css/noscript.css")) .unwrap(); let mut test_content = String::new(); From a8084dcec1d2d36c286ca0e2c384e7bf5cfeffce Mon Sep 17 00:00:00 2001 From: Caio Date: Thu, 6 Jun 2024 16:30:05 -0300 Subject: [PATCH 152/154] [RFC-2011] Allow `core_intrinsics` when activated --- compiler/rustc_builtin_macros/src/assert/context.rs | 1 - library/core/src/macros/mod.rs | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index d244897f8a5d..a98ed996df6e 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -58,7 +58,6 @@ impl<'cx, 'a> Context<'cx, 'a> { /// Builds the whole `assert!` expression. For example, `let elem = 1; assert!(elem == 1);` expands to: /// /// ```rust - /// #![feature(generic_assert_internals)] /// let elem = 1; /// { /// #[allow(unused_imports)] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 9bbaf62a5caa..395e04cf26e9 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1534,7 +1534,12 @@ pub(crate) mod builtin { #[rustc_builtin_macro] #[macro_export] #[rustc_diagnostic_item = "assert_macro"] - #[allow_internal_unstable(panic_internals, edition_panic, generic_assert_internals)] + #[allow_internal_unstable( + core_intrinsics, + panic_internals, + edition_panic, + generic_assert_internals + )] macro_rules! assert { ($cond:expr $(,)?) => {{ /* compiler built-in */ }}; ($cond:expr, $($arg:tt)+) => {{ /* compiler built-in */ }}; From 58ba77f4aa46ca94f643eebe8f61a44f56c8abd5 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 7 Jun 2024 15:55:08 +1000 Subject: [PATCH 153/154] compiletest: Don't pass `--out-dir` if the compile flags include `-o` --- src/tools/compiletest/src/runtest.rs | 3 +++ tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 2c425a07b2ac..a7511a6f457d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -2254,6 +2254,9 @@ impl<'test> TestCx<'test> { } match output_file { + // If the test's compile flags specify an output path with `-o`, + // avoid a compiler warning about `--out-dir` being ignored. + _ if self.props.compile_flags.iter().any(|flag| flag == "-o") => {} TargetLocation::ThisFile(path) => { rustc.arg("-o").arg(path); } diff --git a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr index 5775a4032c39..48cae82feb03 100644 --- a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr +++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.stderr @@ -1,6 +1,4 @@ -warning: ignoring --out-dir flag due to -o flag - error: io error modifying ./does-not-exist/ -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error From 7c9b469895692f25475e387d2cbe33cecbdb43a9 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 5 Jun 2024 20:12:18 +1000 Subject: [PATCH 154/154] Port `tests/run-make-fulldeps/hotplug_codegen_backend` to ui-fulldeps --- .../src/compiler-flags/codegen-backend.md | 5 ++-- src/tools/compiletest/src/header.rs | 9 +++++++ src/tools/compiletest/src/runtest.rs | 10 ++++++++ tests/run-make-fulldeps/README.md | 4 +++ .../hotplug_codegen_backend/Makefile | 25 ------------------- .../hotplug_codegen_backend/some_crate.rs | 2 -- .../codegen-backend/auxiliary}/the_backend.rs | 6 +++-- .../codegen-backend/hotplug.bindep.stdout | 4 +++ .../codegen-backend/hotplug.dep.stdout | 3 +++ .../codegen-backend/hotplug.normal.stdout | 1 + tests/ui-fulldeps/codegen-backend/hotplug.rs | 20 +++++++++++++++ 11 files changed, 58 insertions(+), 31 deletions(-) create mode 100644 tests/run-make-fulldeps/README.md delete mode 100644 tests/run-make-fulldeps/hotplug_codegen_backend/Makefile delete mode 100644 tests/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs rename tests/{run-make-fulldeps/hotplug_codegen_backend => ui-fulldeps/codegen-backend/auxiliary}/the_backend.rs (95%) create mode 100644 tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout create mode 100644 tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout create mode 100644 tests/ui-fulldeps/codegen-backend/hotplug.normal.stdout create mode 100644 tests/ui-fulldeps/codegen-backend/hotplug.rs diff --git a/src/doc/unstable-book/src/compiler-flags/codegen-backend.md b/src/doc/unstable-book/src/compiler-flags/codegen-backend.md index 67634be69931..7e4be9841f47 100644 --- a/src/doc/unstable-book/src/compiler-flags/codegen-backend.md +++ b/src/doc/unstable-book/src/compiler-flags/codegen-backend.md @@ -12,8 +12,9 @@ backend. The library must be of crate type `dylib` and must contain a function named `__rustc_codegen_backend` with a signature of `fn() -> Box`. ## Example -See also the [`hotplug_codegen_backend`](https://github.com/rust-lang/rust/tree/master/tests/run-make-fulldeps/hotplug_codegen_backend) test -for a full example. +See also the [`codegen-backend/hotplug`] test for a working example. + +[`codegen-backend/hotplug`]: https://github.com/rust-lang/rust/tree/master/tests/ui-fulldeps/codegen-backend/hotplug.rs ```rust,ignore (partial-example) use rustc_codegen_ssa::traits::CodegenBackend; diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 736e103fdf22..fd4ab72bbf46 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -107,6 +107,9 @@ pub struct TestProps { // Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies // to build and pass with the `--extern` flag. pub aux_crates: Vec<(String, String)>, + /// Similar to `aux_builds`, but also passes the resulting dylib path to + /// `-Zcodegen-backend`. + pub aux_codegen_backend: Option, // Environment settings to use for compiling pub rustc_env: Vec<(String, String)>, // Environment variables to unset prior to compiling. @@ -231,6 +234,7 @@ mod directives { pub const AUX_BIN: &'static str = "aux-bin"; pub const AUX_BUILD: &'static str = "aux-build"; pub const AUX_CRATE: &'static str = "aux-crate"; + pub const AUX_CODEGEN_BACKEND: &'static str = "aux-codegen-backend"; pub const EXEC_ENV: &'static str = "exec-env"; pub const RUSTC_ENV: &'static str = "rustc-env"; pub const UNSET_EXEC_ENV: &'static str = "unset-exec-env"; @@ -267,6 +271,7 @@ impl TestProps { aux_builds: vec![], aux_bins: vec![], aux_crates: vec![], + aux_codegen_backend: None, revisions: vec![], rustc_env: vec![ ("RUSTC_ICE".to_string(), "0".to_string()), @@ -446,6 +451,9 @@ impl TestProps { &mut self.aux_crates, Config::parse_aux_crate, ); + if let Some(r) = config.parse_name_value_directive(ln, AUX_CODEGEN_BACKEND) { + self.aux_codegen_backend = Some(r.trim().to_owned()); + } config.push_name_value_directive( ln, EXEC_ENV, @@ -722,6 +730,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ "assembly-output", "aux-bin", "aux-build", + "aux-codegen-backend", "aux-crate", "build-aux-docs", "build-fail", diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index a7511a6f457d..28c766f7e17d 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1833,6 +1833,16 @@ impl<'test> TestCx<'test> { )); } } + + // Build any `//@ aux-codegen-backend`, and pass the resulting library + // to `-Zcodegen-backend` when compiling the test file. + if let Some(aux_file) = &self.props.aux_codegen_backend { + let aux_type = self.build_auxiliary(of, aux_file, aux_dir, false); + if let Some(lib_name) = get_lib_name(aux_file.trim_end_matches(".rs"), aux_type) { + let lib_path = aux_dir.join(&lib_name); + rustc.arg(format!("-Zcodegen-backend={}", lib_path.display())); + } + } } fn compose_and_run_compiler(&self, mut rustc: Command, input: Option) -> ProcRes { diff --git a/tests/run-make-fulldeps/README.md b/tests/run-make-fulldeps/README.md new file mode 100644 index 000000000000..dd1788390220 --- /dev/null +++ b/tests/run-make-fulldeps/README.md @@ -0,0 +1,4 @@ +If this directory is empty, Git won't create it, and compiletest will complain +that it can't find a nonexistent test suite directory. + +FIXME(#126111): Remove `run-make-fulldeps` from bootstrap. diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/Makefile b/tests/run-make-fulldeps/hotplug_codegen_backend/Makefile deleted file mode 100644 index 3a5a66b6755e..000000000000 --- a/tests/run-make-fulldeps/hotplug_codegen_backend/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -include ../../run-make/tools.mk - -# ignore-stage1 - -# This test both exists as a check that -Zcodegen-backend is capable of loading external codegen -# backends and that this external codegen backend is only included in the dep info if -# -Zbinary-dep-depinfo is used. - -all: - $(RUSTC) the_backend.rs --crate-name the_backend --crate-type dylib \ - -o $(TMPDIR)/the_backend.dylib - - $(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \ - -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \ - --emit link,dep-info - grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib - # don't declare a dependency on the codegen backend if -Zbinary-dep-depinfo isn't used. - grep -v "the_backend.dylib" $(TMPDIR)/some_crate.d - - $(RUSTC) some_crate.rs --crate-name some_crate --crate-type lib -o $(TMPDIR)/some_crate \ - -Z codegen-backend=$(TMPDIR)/the_backend.dylib -Z unstable-options \ - --emit link,dep-info -Zbinary-dep-depinfo - grep -x "This has been \"compiled\" successfully." $(TMPDIR)/libsome_crate.rlib - # but declare a dependency on the codegen backend if -Zbinary-dep-depinfo it used. - grep "the_backend.dylib" $(TMPDIR)/some_crate.d diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs b/tests/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs deleted file mode 100644 index da27b7f3463d..000000000000 --- a/tests/run-make-fulldeps/hotplug_codegen_backend/some_crate.rs +++ /dev/null @@ -1,2 +0,0 @@ -#![feature(no_core)] -#![no_core] diff --git a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs similarity index 95% rename from tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs rename to tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs index 07466440aabf..f273bbc99a8a 100644 --- a/tests/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs @@ -1,3 +1,5 @@ +//@ edition: 2021 + #![feature(rustc_private)] #![deny(warnings)] @@ -78,11 +80,11 @@ impl CodegenBackend for TheBackend { match output_name { OutFileName::Real(ref path) => { let mut out_file = ::std::fs::File::create(path).unwrap(); - write!(out_file, "This has been \"compiled\" successfully.").unwrap(); + writeln!(out_file, "This has been 'compiled' successfully.").unwrap(); } OutFileName::Stdout => { let mut stdout = std::io::stdout(); - write!(stdout, "This has been \"compiled\" successfully.").unwrap(); + writeln!(stdout, "This has been 'compiled' successfully.").unwrap(); } } } diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout b/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout new file mode 100644 index 000000000000..4d58fd503d0a --- /dev/null +++ b/tests/ui-fulldeps/codegen-backend/hotplug.bindep.stdout @@ -0,0 +1,4 @@ +$TEST_BUILD_DIR/codegen-backend/hotplug.bindep/libhotplug.rlib: $DIR/hotplug.rs $TEST_BUILD_DIR/codegen-backend/hotplug.bindep/auxiliary/libthe_backend.so + +$DIR/hotplug.rs: +$TEST_BUILD_DIR/codegen-backend/hotplug.bindep/auxiliary/libthe_backend.so: diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout b/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout new file mode 100644 index 000000000000..48b7534d8faf --- /dev/null +++ b/tests/ui-fulldeps/codegen-backend/hotplug.dep.stdout @@ -0,0 +1,3 @@ +$TEST_BUILD_DIR/codegen-backend/hotplug.dep/libhotplug.rlib: $DIR/hotplug.rs + +$DIR/hotplug.rs: diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.normal.stdout b/tests/ui-fulldeps/codegen-backend/hotplug.normal.stdout new file mode 100644 index 000000000000..1aa032de9e49 --- /dev/null +++ b/tests/ui-fulldeps/codegen-backend/hotplug.normal.stdout @@ -0,0 +1 @@ +This has been 'compiled' successfully. diff --git a/tests/ui-fulldeps/codegen-backend/hotplug.rs b/tests/ui-fulldeps/codegen-backend/hotplug.rs new file mode 100644 index 000000000000..dc0fb3f9efd0 --- /dev/null +++ b/tests/ui-fulldeps/codegen-backend/hotplug.rs @@ -0,0 +1,20 @@ +//@ edition: 2021 +//@ build-pass +//@ ignore-stage1 (requires matching sysroot built with in-tree compiler) + +//@ aux-codegen-backend: the_backend.rs +//@ normalize-stdout-test: "libthe_backend.dylib" -> "libthe_backend.so" +//@ normalize-stdout-test: "the_backend.dll" -> "libthe_backend.so" + +//@ revisions: normal dep bindep +//@ compile-flags: --crate-type=lib +//@ [normal] compile-flags: --emit=link=- +//@ [dep] compile-flags: --emit=link,dep-info=- +//@ [bindep] compile-flags: --emit=link,dep-info=- -Zbinary-dep-depinfo + +#![feature(no_core)] +#![no_core] + +// This test both exists as a check that -Zcodegen-backend is capable of loading external codegen +// backends and that this external codegen backend is only included in the dep info if +// -Zbinary-dep-depinfo is used.