From 7f9a541059b1bf5322e94668792e933a48975917 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:45:41 +0200 Subject: [PATCH 1/8] remove pointless rustc_const_unstable on trait impls --- library/core/src/ptr/alignment.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 19fe03d57cc..834cec9dcfc 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -199,7 +199,6 @@ impl From for usize { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl cmp::Ord for Alignment { #[inline] @@ -208,7 +207,6 @@ impl cmp::Ord for Alignment { } } -#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")] #[unstable(feature = "ptr_alignment_type", issue = "102070")] impl cmp::PartialOrd for Alignment { #[inline] From 332fa6aa6ed70e285c155d112a30027947cad12b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 16:35:34 +0200 Subject: [PATCH 2/8] add FIXME(const-hack) --- .../rustc_mir_transform/src/pass_manager.rs | 6 ++--- .../alloc/src/collections/vec_deque/mod.rs | 4 ++-- library/alloc/src/raw_vec.rs | 15 +----------- library/alloc/src/vec/in_place_collect.rs | 2 +- library/alloc/src/vec/into_iter.rs | 2 +- library/alloc/src/vec/mod.rs | 2 +- library/core/src/char/convert.rs | 2 +- library/core/src/char/methods.rs | 2 +- library/core/src/num/mod.rs | 2 +- library/core/src/option.rs | 24 ++++++------------- library/core/src/slice/index.rs | 9 ++++--- library/core/src/slice/mod.rs | 6 ++--- library/core/src/str/converts.rs | 4 ++-- library/core/src/str/error.rs | 2 +- library/core/src/time.rs | 2 ++ library/core/src/unicode/unicode_data.rs | 6 ++--- library/core/tests/hash/mod.rs | 7 ++---- library/std/src/sys/pal/windows/args.rs | 2 +- 18 files changed, 38 insertions(+), 61 deletions(-) diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 28d4e1a1c91..e5f145ea31a 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -42,7 +42,7 @@ fn to_profiler_name(type_name: &'static str) -> &'static str { // const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` const fn c_name(name: &'static str) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. + // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable. // and inline into call site let bytes = name.as_bytes(); let mut i = bytes.len(); @@ -61,7 +61,7 @@ const fn c_name(name: &'static str) -> &'static str { /// loop that goes over each available MIR and applies `run_pass`. pub(super) trait MirPass<'tcx> { fn name(&self) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. + // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable. // See copypaste in `MirLint` const { let name = std::any::type_name::(); @@ -89,7 +89,7 @@ pub(super) trait MirPass<'tcx> { /// disabled (via the `Lint` adapter). pub(super) trait MirLint<'tcx> { fn name(&self) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. + // FIXME(const-hack) Simplify the implementation once more `str` methods get const-stable. // See copypaste in `MirPass` const { let name = std::any::type_name::(); diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index dc725ec0f56..8c9db063105 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -554,8 +554,8 @@ impl VecDeque { #[rustc_const_stable(feature = "const_vec_deque_new", since = "1.68.0")] #[must_use] pub const fn new() -> VecDeque { - // FIXME: This should just be `VecDeque::new_in(Global)` once that hits stable. - VecDeque { head: 0, len: 0, buf: RawVec::NEW } + // FIXME(const-hack): This should just be `VecDeque::new_in(Global)` once that hits stable. + VecDeque { head: 0, len: 0, buf: RawVec::new() } } /// Creates an empty deque with space for at least `capacity` elements. diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index a651ba067e4..436e0596e3d 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -96,13 +96,6 @@ struct RawVecInner { } impl RawVec { - /// HACK(Centril): This exists because stable `const fn` can only call stable `const fn`, so - /// they cannot call `Self::new()`. - /// - /// If you change `RawVec::new` or dependencies, please take care to not introduce anything - /// that would truly const-call something unstable. - pub const NEW: Self = Self::new(); - /// Creates the biggest possible `RawVec` (on the system heap) /// without allocating. If `T` has positive size, then this makes a /// `RawVec` with capacity `0`. If `T` is zero-sized, then it makes a @@ -111,7 +104,7 @@ impl RawVec { #[must_use] #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] pub const fn new() -> Self { - Self { inner: RawVecInner::new::(), _marker: PhantomData } + Self::new_in(Global) } /// Creates a `RawVec` (on the system heap) with exactly the @@ -149,12 +142,6 @@ impl RawVec { } impl RawVecInner { - #[must_use] - #[rustc_const_stable(feature = "raw_vec_internals_const", since = "1.81")] - const fn new() -> Self { - Self::new_in(Global, core::mem::align_of::()) - } - #[cfg(not(any(no_global_oom_handling, test)))] #[must_use] #[inline] diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs index d119e6ca397..26048439945 100644 --- a/library/alloc/src/vec/in_place_collect.rs +++ b/library/alloc/src/vec/in_place_collect.rs @@ -191,7 +191,7 @@ const fn in_place_collectible( const fn needs_realloc(src_cap: usize, dst_cap: usize) -> bool { if const { mem::align_of::() != mem::align_of::() } { - // FIXME: use unreachable! once that works in const + // FIXME(const-hack): use unreachable! once that works in const panic!("in_place_collectible() prevents this"); } diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs index fad8abad493..487d5cc7224 100644 --- a/library/alloc/src/vec/into_iter.rs +++ b/library/alloc/src/vec/into_iter.rs @@ -142,7 +142,7 @@ impl IntoIter { // struct and then overwriting &mut self. // this creates less assembly self.cap = 0; - self.buf = RawVec::NEW.non_null(); + self.buf = RawVec::new().non_null(); self.ptr = self.buf; self.end = self.buf.as_ptr(); diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 162791ba59d..ff084edba8d 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -419,7 +419,7 @@ impl Vec { #[stable(feature = "rust1", since = "1.0.0")] #[must_use] pub const fn new() -> Self { - Vec { buf: RawVec::NEW, len: 0 } + Vec { buf: RawVec::new(), len: 0 } } /// Constructs a new, empty `Vec` with at least the specified capacity. diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs index f0c2636307f..73ab4f1e52a 100644 --- a/library/core/src/char/convert.rs +++ b/library/core/src/char/convert.rs @@ -11,7 +11,7 @@ use crate::ub_checks::assert_unsafe_precondition; #[must_use] #[inline] pub(super) const fn from_u32(i: u32) -> Option { - // FIXME: once Result::ok is const fn, use it here + // FIXME(const-hack): once Result::ok is const fn, use it here match char_try_from_u32(i) { Ok(c) => Some(c), Err(_) => None, diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 41a19665779..6e7494af12f 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -386,7 +386,7 @@ impl char { // Force the 6th bit to be set to ensure ascii is lower case. digit = (self as u32 | 0b10_0000).wrapping_sub('a' as u32).saturating_add(10); } - // FIXME: once then_some is const fn, use it here + // FIXME(const-hack): once then_some is const fn, use it here if digit < radix { Some(digit) } else { None } } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 37c9db7f474..dca644ebef4 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -6,7 +6,7 @@ use crate::str::FromStr; use crate::ub_checks::assert_unsafe_precondition; use crate::{ascii, intrinsics, mem}; -// Used because the `?` operator is not allowed in a const context. +// FIXME(const-hack): Used because the `?` operator is not allowed in a const context. macro_rules! try_opt { ($e:expr) => { match $e { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 212e4f02154..18604a8ae35 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -739,6 +739,7 @@ impl Option { #[stable(feature = "pin", since = "1.33.0")] #[rustc_const_unstable(feature = "const_option_ext", issue = "91930")] pub const fn as_pin_ref(self: Pin<&Self>) -> Option> { + // FIXME(const-hack): use `map` once that is possible match Pin::get_ref(self).as_ref() { // SAFETY: `x` is guaranteed to be pinned because it comes from `self` // which is pinned. @@ -758,6 +759,7 @@ impl Option { // SAFETY: `get_unchecked_mut` is never used to move the `Option` inside `self`. // `x` is guaranteed to be pinned because it comes from `self` which is pinned. unsafe { + // FIXME(const-hack): use `map` once that is possible match Pin::get_unchecked_mut(self).as_mut() { Some(x) => Some(Pin::new_unchecked(x)), None => None, @@ -1290,10 +1292,7 @@ impl Option { where T: Deref, { - match self.as_ref() { - Some(t) => Some(t.deref()), - None => None, - } + self.as_ref().map(|t| t.deref()) } /// Converts from `Option` (or `&mut Option`) to `Option<&mut T::Target>`. @@ -1316,10 +1315,7 @@ impl Option { where T: DerefMut, { - match self.as_mut() { - Some(t) => Some(t.deref_mut()), - None => None, - } + self.as_mut().map(|t| t.deref_mut()) } ///////////////////////////////////////////////////////////////////////// @@ -1633,13 +1629,7 @@ impl Option { #[inline] #[stable(feature = "option_entry", since = "1.20.0")] pub fn get_or_insert(&mut self, value: T) -> &mut T { - if let None = *self { - *self = Some(value); - } - - // SAFETY: a `None` variant for `self` would have been replaced by a `Some` - // variant in the code above. - unsafe { self.as_mut().unwrap_unchecked() } + self.get_or_insert_with(|| value) } /// Inserts the default value into the option if it is [`None`], then @@ -1725,7 +1715,7 @@ impl Option { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_option", issue = "67441")] pub const fn take(&mut self) -> Option { - // FIXME replace `mem::replace` by `mem::take` when the latter is const ready + // FIXME(const-hack) replace `mem::replace` by `mem::take` when the latter is const ready mem::replace(self, None) } @@ -1894,7 +1884,7 @@ impl Option<&T> { where T: Copy, { - // FIXME: this implementation, which sidesteps using `Option::map` since it's not const + // FIXME(const-hack): this implementation, which sidesteps using `Option::map` since it's not const // ready yet, should be reverted when possible to avoid code repetition match self { Some(&v) => Some(v), diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index de1492e82ce..7adcee1ed6b 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -33,10 +33,11 @@ where #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, len), slice_start_index_len_fail_ct, slice_start_index_len_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_start_index_len_fail_rt(index: usize, len: usize) -> ! { @@ -54,10 +55,11 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, len), slice_end_index_len_fail_ct, slice_end_index_len_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_end_index_len_fail_rt(index: usize, len: usize) -> ! { @@ -75,10 +77,11 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[track_caller] #[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_index_order_fail(index: usize, end: usize) -> ! { + // FIXME(const-hack): once integer formatting in panics is possible, we + // should use the same implementation at compiletime and runtime. const_eval_select((index, end), slice_index_order_fail_ct, slice_index_order_fail_rt) } -// FIXME const-hack #[inline] #[track_caller] fn slice_index_order_fail_rt(index: usize, end: usize) -> ! { diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index 166189f4b6c..3a02966a168 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -529,7 +529,7 @@ impl [T] { None } else { // SAFETY: We manually verified the bounds of the slice. - // FIXME: Without const traits, we need this instead of `get_unchecked`. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. let last = unsafe { self.split_at_unchecked(self.len() - N).1 }; // SAFETY: We explicitly check for the correct number of elements, @@ -563,7 +563,7 @@ impl [T] { None } else { // SAFETY: We manually verified the bounds of the slice. - // FIXME: Without const traits, we need this instead of `get_unchecked`. + // FIXME(const-hack): Without const traits, we need this instead of `get_unchecked`. let last = unsafe { self.split_at_mut_unchecked(self.len() - N).1 }; // SAFETY: We explicitly check for the correct number of elements, @@ -1952,7 +1952,7 @@ impl [T] { #[inline] #[must_use] pub const unsafe fn split_at_unchecked(&self, mid: usize) -> (&[T], &[T]) { - // HACK: the const function `from_raw_parts` is used to make this + // FIXME(const-hack): the const function `from_raw_parts` is used to make this // function const; previously the implementation used // `(self.get_unchecked(..mid), self.get_unchecked(mid..))` diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs index 1956a04829d..dcddc40ba4b 100644 --- a/library/core/src/str/converts.rs +++ b/library/core/src/str/converts.rs @@ -85,7 +85,7 @@ use crate::{mem, ptr}; #[rustc_allow_const_fn_unstable(str_internals)] #[rustc_diagnostic_item = "str_from_utf8"] pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { - // FIXME: This should use `?` again, once it's `const` + // FIXME(const-hack): This should use `?` again, once it's `const` match run_utf8_validation(v) { Ok(_) => { // SAFETY: validation succeeded. @@ -129,7 +129,7 @@ pub const fn from_utf8(v: &[u8]) -> Result<&str, Utf8Error> { #[rustc_const_unstable(feature = "const_str_from_utf8", issue = "91006")] #[rustc_diagnostic_item = "str_from_utf8_mut"] pub const fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> { - // This should use `?` again, once it's `const` + // FIXME(const-hack): This should use `?` again, once it's `const` match run_utf8_validation(v) { Ok(_) => { // SAFETY: validation succeeded. diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs index a11b5add42e..4c8231a2286 100644 --- a/library/core/src/str/error.rs +++ b/library/core/src/str/error.rs @@ -100,7 +100,7 @@ impl Utf8Error { #[must_use] #[inline] pub const fn error_len(&self) -> Option { - // FIXME: This should become `map` again, once it's `const` + // FIXME(const-hack): This should become `map` again, once it's `const` match self.error_len { Some(len) => Some(len as usize), None => None, diff --git a/library/core/src/time.rs b/library/core/src/time.rs index c19eeedb354..65560dfcf9d 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -213,6 +213,7 @@ impl Duration { // SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range Duration { secs, nanos: unsafe { Nanoseconds(nanos) } } } else { + // FIXME(const-hack): use `.expect` once that is possible. let secs = match secs.checked_add((nanos / NANOS_PER_SEC) as u64) { Some(secs) => secs, None => panic!("overflow in Duration::new"), @@ -768,6 +769,7 @@ impl Duration { let total_nanos = self.nanos.0 as u64 * rhs as u64; let extra_secs = total_nanos / (NANOS_PER_SEC as u64); let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; + // FIXME(const-hack): use `and_then` once that is possible. if let Some(s) = self.secs.checked_mul(rhs as u64) { if let Some(secs) = s.checked_add(extra_secs) { debug_assert!(nanos < NANOS_PER_SEC); diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index 1b3d6729663..9783e816084 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -18,16 +18,14 @@ const fn bitset_search< let bucket_idx = (needle / 64) as usize; let chunk_map_idx = bucket_idx / CHUNK_SIZE; let chunk_piece = bucket_idx % CHUNK_SIZE; - // FIXME: const-hack: Revert to `slice::get` after `const_slice_index` - // feature stabilizes. + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. let chunk_idx = if chunk_map_idx < chunk_idx_map.len() { chunk_idx_map[chunk_map_idx] } else { return false; }; let idx = bitset_chunk_idx[chunk_idx as usize][chunk_piece] as usize; - // FIXME: const-hack: Revert to `slice::get` after `const_slice_index` - // feature stabilizes. + // FIXME(const-hack): Revert to `slice::get` when slice indexing becomes possible in const. let word = if idx < bitset_canonical.len() { bitset_canonical[idx] } else { diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs index bdd1c2579de..03826fc4c92 100644 --- a/library/core/tests/hash/mod.rs +++ b/library/core/tests/hash/mod.rs @@ -16,11 +16,8 @@ impl Default for MyHasher { impl Hasher for MyHasher { fn write(&mut self, buf: &[u8]) { - // FIXME(const_trait_impl): change to for loop - let mut i = 0; - while i < buf.len() { - self.hash += buf[i] as u64; - i += 1; + for byte in buf { + self.hash += *byte as u64; } } fn write_str(&mut self, s: &str) { diff --git a/library/std/src/sys/pal/windows/args.rs b/library/std/src/sys/pal/windows/args.rs index 66e75a83571..77d82678f1d 100644 --- a/library/std/src/sys/pal/windows/args.rs +++ b/library/std/src/sys/pal/windows/args.rs @@ -20,7 +20,7 @@ use crate::{fmt, io, iter, vec}; /// This is the const equivalent to `NonZero::new(n).unwrap()` /// -/// FIXME: This can be removed once `Option::unwrap` is stably const. +/// FIXME(const-hack): This can be removed once `Option::unwrap` is stably const. /// See the `const_option` feature (#67441). const fn non_zero_u16(n: u16) -> NonZero { match NonZero::new(n) { From 7a3a317618885a8949c8b95c9a38f3f9729b1f3c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Sep 2024 08:54:01 +0200 Subject: [PATCH 3/8] remove const_slice_index annotations, it never had a feature gate anyway --- library/core/src/lib.rs | 1 - library/core/src/slice/index.rs | 10 ---------- library/core/src/slice/memchr.rs | 1 - library/core/src/str/traits.rs | 6 ------ tests/ui/consts/const-eval/ub-slice-get-unchecked.rs | 2 -- .../ui/consts/const-eval/ub-slice-get-unchecked.stderr | 2 +- 6 files changed, 1 insertion(+), 21 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index bda38254362..5b5d5d1a961 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -149,7 +149,6 @@ #![feature(const_size_of_val_raw)] #![feature(const_slice_from_raw_parts_mut)] #![feature(const_slice_from_ref)] -#![feature(const_slice_index)] #![feature(const_slice_split_at_mut)] #![feature(const_str_from_utf8_unchecked_mut)] #![feature(const_strict_overflow_ops)] diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs index 7adcee1ed6b..bc8571c8503 100644 --- a/library/core/src/slice/index.rs +++ b/library/core/src/slice/index.rs @@ -31,7 +31,6 @@ where #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_start_index_len_fail(index: usize, len: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -53,7 +52,6 @@ const fn slice_start_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_end_index_len_fail(index: usize, len: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -75,7 +73,6 @@ const fn slice_end_index_len_fail_ct(_: usize, _: usize) -> ! { #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)] #[cfg_attr(feature = "panic_immediate_abort", inline)] #[track_caller] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] const fn slice_index_order_fail(index: usize, end: usize) -> ! { // FIXME(const-hack): once integer formatting in panics is possible, we // should use the same implementation at compiletime and runtime. @@ -249,7 +246,6 @@ pub unsafe trait SliceIndex: private_slice_index::Sealed { /// The methods `index` and `index_mut` panic if the index is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for usize { type Output = T; @@ -389,7 +385,6 @@ unsafe impl SliceIndex<[T]> for ops::IndexRange { /// - the start of the range is greater than the end of the range or /// - the end of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::Range { type Output = [T]; @@ -525,7 +520,6 @@ unsafe impl SliceIndex<[T]> for range::Range { /// The methods `index` and `index_mut` panic if the end of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeTo { type Output = [T]; @@ -564,7 +558,6 @@ unsafe impl SliceIndex<[T]> for ops::RangeTo { /// The methods `index` and `index_mut` panic if the start of the range is out of bounds. #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeFrom { type Output = [T]; @@ -647,7 +640,6 @@ unsafe impl SliceIndex<[T]> for range::RangeFrom { } #[stable(feature = "slice_get_slice_impls", since = "1.15.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeFull { type Output = [T]; @@ -687,7 +679,6 @@ unsafe impl SliceIndex<[T]> for ops::RangeFull { /// - the start of the range is greater than the end of the range or /// - the end of the range is out of bounds. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeInclusive { type Output = [T]; @@ -769,7 +760,6 @@ unsafe impl SliceIndex<[T]> for range::RangeInclusive { /// The methods `index` and `index_mut` panic if the end of the range is out of bounds. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex<[T]> for ops::RangeToInclusive { type Output = [T]; diff --git a/library/core/src/slice/memchr.rs b/library/core/src/slice/memchr.rs index da7ceb2dd0a..be19c3d3bc1 100644 --- a/library/core/src/slice/memchr.rs +++ b/library/core/src/slice/memchr.rs @@ -51,7 +51,6 @@ const fn memchr_naive(x: u8, text: &[u8]) -> Option { } #[rustc_allow_const_fn_unstable(const_cmp)] -#[rustc_allow_const_fn_unstable(const_slice_index)] #[rustc_allow_const_fn_unstable(const_align_offset)] #[rustc_const_stable(feature = "const_memchr", since = "1.65.0")] const fn memchr_aligned(x: u8, text: &[u8]) -> Option { diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index b69c476ae5e..77c70b978fd 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -92,7 +92,6 @@ const fn str_index_overflow_fail() -> ! { /// /// Equivalent to `&self[0 .. len]` or `&mut self[0 .. len]`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeFull { type Output = str; #[inline] @@ -157,7 +156,6 @@ unsafe impl SliceIndex for ops::RangeFull { /// // &s[3 .. 100]; /// ``` #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::Range { type Output = str; #[inline] @@ -429,7 +427,6 @@ unsafe impl SliceIndex for (ops::Bound, ops::Bound) { /// Panics if `end` does not point to the starting byte offset of a /// character (as defined by `is_char_boundary`), or if `end > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeTo { type Output = str; #[inline] @@ -498,7 +495,6 @@ unsafe impl SliceIndex for ops::RangeTo { /// Panics if `begin` does not point to the starting byte offset of /// a character (as defined by `is_char_boundary`), or if `begin > len`. #[stable(feature = "str_checked_slicing", since = "1.20.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeFrom { type Output = str; #[inline] @@ -625,7 +621,6 @@ unsafe impl SliceIndex for range::RangeFrom { /// to the ending byte offset of a character (`end + 1` is either a starting /// byte offset or equal to `len`), if `begin > end`, or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeInclusive { type Output = str; #[inline] @@ -714,7 +709,6 @@ unsafe impl SliceIndex for range::RangeInclusive { /// (`end + 1` is either a starting byte offset as defined by /// `is_char_boundary`, or equal to `len`), or if `end >= len`. #[stable(feature = "inclusive_range", since = "1.26.0")] -#[rustc_const_unstable(feature = "const_slice_index", issue = "none")] unsafe impl SliceIndex for ops::RangeToInclusive { type Output = str; #[inline] diff --git a/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs b/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs index 3800abddd42..e805ac01c9d 100644 --- a/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs +++ b/tests/ui/consts/const-eval/ub-slice-get-unchecked.rs @@ -1,7 +1,5 @@ //@ known-bug: #110395 -#![feature(const_slice_index)] - const A: [(); 5] = [(), (), (), (), ()]; // Since the indexing is on a ZST, the addresses are all fine, diff --git a/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr b/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr index de96821e8b9..94aa3ee4d7a 100644 --- a/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr +++ b/tests/ui/consts/const-eval/ub-slice-get-unchecked.stderr @@ -1,5 +1,5 @@ error[E0015]: cannot call non-const fn `core::slice::::get_unchecked::>` in constants - --> $DIR/ub-slice-get-unchecked.rs:9:29 + --> $DIR/ub-slice-get-unchecked.rs:7:29 | LL | const B: &[()] = unsafe { A.get_unchecked(3..1) }; | ^^^^^^^^^^^^^^^^^^^ From d4fc76cbf386eeeb184bf0411af670912e9bc70d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 10 Sep 2024 16:19:40 +1000 Subject: [PATCH 4/8] Introduce `'ra` lifetime name. `rustc_resolve` allocates many things in `ResolverArenas`. The lifetime used for references into the arena is mostly `'a`, and sometimes `'b`. This commit changes it to `'ra`, which is much more descriptive. The commit also changes the order of lifetimes on a couple of structs so that '`ra` is second last, before `'tcx`, and does other minor renamings such as `'r` to `'a`. --- .../rustc_resolve/src/build_reduced_graph.rs | 92 +++--- compiler/rustc_resolve/src/check_unused.rs | 8 +- compiler/rustc_resolve/src/def_collector.rs | 8 +- compiler/rustc_resolve/src/diagnostics.rs | 52 ++-- .../src/effective_visibilities.rs | 33 +- compiler/rustc_resolve/src/ident.rs | 106 +++---- compiler/rustc_resolve/src/imports.rs | 72 ++--- compiler/rustc_resolve/src/late.rs | 259 ++++++++-------- .../rustc_resolve/src/late/diagnostics.rs | 4 +- compiler/rustc_resolve/src/lib.rs | 287 +++++++++--------- compiler/rustc_resolve/src/macros.rs | 32 +- 11 files changed, 482 insertions(+), 471 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 3ea782b62f1..f87f3cdde4c 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -39,10 +39,10 @@ use crate::{ type Res = def::Res; -impl<'a, Id: Into> ToNameBinding<'a> - for (Module<'a>, ty::Visibility, Span, LocalExpnId) +impl<'ra, Id: Into> ToNameBinding<'ra> + for (Module<'ra>, ty::Visibility, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { + fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> { arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Module(self.0), ambiguity: None, @@ -54,8 +54,8 @@ impl<'a, Id: Into> ToNameBinding<'a> } } -impl<'a, Id: Into> ToNameBinding<'a> for (Res, ty::Visibility, Span, LocalExpnId) { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a> { +impl<'ra, Id: Into> ToNameBinding<'ra> for (Res, ty::Visibility, Span, LocalExpnId) { + fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> { arenas.alloc_name_binding(NameBindingData { kind: NameBindingKind::Res(self.0), ambiguity: None, @@ -67,12 +67,12 @@ impl<'a, Id: Into> ToNameBinding<'a> for (Res, ty::Visibility, Span, } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined; /// otherwise, reports an error. - pub(crate) fn define(&mut self, parent: Module<'a>, ident: Ident, ns: Namespace, def: T) + pub(crate) fn define(&mut self, parent: Module<'ra>, ident: Ident, ns: Namespace, def: T) where - T: ToNameBinding<'a>, + T: ToNameBinding<'ra>, { let binding = def.to_name_binding(self.arenas); let key = self.new_disambiguated_key(ident, ns); @@ -97,7 +97,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Reachable macros with block module parents exist due to `#[macro_export] macro_rules!`, /// but they cannot use def-site hygiene, so the assumption holds /// (). - pub(crate) fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'a> { + pub(crate) fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'ra> { loop { match self.get_module(def_id) { Some(module) => return module, @@ -106,14 +106,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - pub(crate) fn expect_module(&mut self, def_id: DefId) -> Module<'a> { + pub(crate) fn expect_module(&mut self, def_id: DefId) -> Module<'ra> { self.get_module(def_id).expect("argument `DefId` is not a module") } /// If `def_id` refers to a module (in resolver's sense, i.e. a module item, crate root, enum, /// or trait), then this function returns that module's resolver representation, otherwise it /// returns `None`. - pub(crate) fn get_module(&mut self, def_id: DefId) -> Option> { + pub(crate) fn get_module(&mut self, def_id: DefId) -> Option> { if let module @ Some(..) = self.module_map.get(&def_id) { return module.copied(); } @@ -143,7 +143,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'a> { + pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'ra> { match expn_id.expn_data().macro_def_id { Some(def_id) => self.macro_def_scope(def_id), None => expn_id @@ -153,7 +153,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - pub(crate) fn macro_def_scope(&mut self, def_id: DefId) -> Module<'a> { + pub(crate) fn macro_def_scope(&mut self, def_id: DefId) -> Module<'ra> { if let Some(id) = def_id.as_local() { self.local_macro_def_scopes[&id] } else { @@ -186,15 +186,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn build_reduced_graph( &mut self, fragment: &AstFragment, - parent_scope: ParentScope<'a>, - ) -> MacroRulesScopeRef<'a> { + parent_scope: ParentScope<'ra>, + ) -> MacroRulesScopeRef<'ra> { collect_definitions(self, fragment, parent_scope.expansion); let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); visitor.parent_scope.macro_rules } - pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'a>) { + pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'ra>) { for child in self.tcx.module_children(module.def_id()) { let parent_scope = ParentScope::module(module, self); self.build_reduced_graph_for_external_crate_res(child, parent_scope) @@ -205,7 +205,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn build_reduced_graph_for_external_crate_res( &mut self, child: &ModChild, - parent_scope: ParentScope<'a>, + parent_scope: ParentScope<'ra>, ) { let parent = parent_scope.module; let ModChild { ident, res, vis, ref reexport_chain } = *child; @@ -273,18 +273,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } -struct BuildReducedGraphVisitor<'a, 'b, 'tcx> { - r: &'b mut Resolver<'a, 'tcx>, - parent_scope: ParentScope<'a>, +struct BuildReducedGraphVisitor<'a, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, + parent_scope: ParentScope<'ra>, } -impl<'a, 'tcx> AsMut> for BuildReducedGraphVisitor<'a, '_, 'tcx> { - fn as_mut(&mut self) -> &mut Resolver<'a, 'tcx> { +impl<'ra, 'tcx> AsMut> for BuildReducedGraphVisitor<'_, 'ra, 'tcx> { + fn as_mut(&mut self) -> &mut Resolver<'ra, 'tcx> { self.r } } -impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { fn res(&self, def_id: impl Into) -> Res { let def_id = def_id.into(); Res::Def(self.r.tcx.def_kind(def_id), def_id) @@ -424,7 +424,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn add_import( &mut self, module_path: Vec, - kind: ImportKind<'a>, + kind: ImportKind<'ra>, span: Span, item: &ast::Item, root_span: Span, @@ -752,7 +752,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } /// Constructs the reduced graph for one item. - fn build_reduced_graph_for_item(&mut self, item: &'b Item) { + fn build_reduced_graph_for_item(&mut self, item: &'a Item) { let parent_scope = &self.parent_scope; let parent = parent_scope.module; let expansion = parent_scope.expansion; @@ -918,7 +918,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { item: &Item, local_def_id: LocalDefId, vis: ty::Visibility, - parent: Module<'a>, + parent: Module<'ra>, ) { let ident = item.ident; let sp = item.span; @@ -1040,7 +1040,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn add_macro_use_binding( &mut self, name: Symbol, - binding: NameBinding<'a>, + binding: NameBinding<'ra>, span: Span, allow_shadowing: bool, ) { @@ -1050,7 +1050,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } /// Returns `true` if we should consider the underlying `extern crate` to be used. - fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool { + fn process_macro_use_imports(&mut self, item: &Item, module: Module<'ra>) -> bool { let mut import_all = None; let mut single_imports = Vec::new(); for attr in &item.attrs { @@ -1188,7 +1188,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { /// Visit invocation in context in which it can emit a named item (possibly `macro_rules`) /// directly into its parent scope's module. - fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'a> { + fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'ra> { let invoc_id = self.visit_invoc(id); self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id); self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id)) @@ -1221,7 +1221,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> { + fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'ra> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; let feed = self.r.feed(item.id); @@ -1308,7 +1308,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { macro_rules! method { ($visit:ident: $ty:ty, $invoc:path, $walk:ident) => { - fn $visit(&mut self, node: &'b $ty) { + fn $visit(&mut self, node: &'a $ty) { if let $invoc(..) = node.kind { self.visit_invoc(node.id); } else { @@ -1318,12 +1318,12 @@ macro_rules! method { }; } -impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> { method!(visit_expr: ast::Expr, ast::ExprKind::MacCall, walk_expr); method!(visit_pat: ast::Pat, ast::PatKind::MacCall, walk_pat); method!(visit_ty: ast::Ty, ast::TyKind::MacCall, walk_ty); - fn visit_item(&mut self, item: &'b Item) { + fn visit_item(&mut self, item: &'a Item) { let orig_module_scope = self.parent_scope.module; self.parent_scope.macro_rules = match item.kind { ItemKind::MacroDef(..) => { @@ -1357,7 +1357,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.parent_scope.module = orig_module_scope; } - fn visit_stmt(&mut self, stmt: &'b ast::Stmt) { + fn visit_stmt(&mut self, stmt: &'a ast::Stmt) { if let ast::StmtKind::MacCall(..) = stmt.kind { self.parent_scope.macro_rules = self.visit_invoc_in_module(stmt.id); } else { @@ -1365,7 +1365,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_foreign_item(&mut self, foreign_item: &'b ForeignItem) { + fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) { if let ForeignItemKind::MacCall(_) = foreign_item.kind { self.visit_invoc_in_module(foreign_item.id); return; @@ -1375,7 +1375,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { visit::walk_item(self, foreign_item); } - fn visit_block(&mut self, block: &'b Block) { + fn visit_block(&mut self, block: &'a Block) { let orig_current_module = self.parent_scope.module; let orig_current_macro_rules_scope = self.parent_scope.macro_rules; self.build_reduced_graph_for_block(block); @@ -1384,7 +1384,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.parent_scope.macro_rules = orig_current_macro_rules_scope; } - fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) { + fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { if let AssocItemKind::MacCall(_) = item.kind { match ctxt { AssocCtxt::Trait => { @@ -1440,7 +1440,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { visit::walk_assoc_item(self, item, ctxt); } - fn visit_attribute(&mut self, attr: &'b ast::Attribute) { + fn visit_attribute(&mut self, attr: &'a ast::Attribute) { if !attr.is_doc_comment() && attr::is_builtin_attr(attr) { self.r .builtin_attrs @@ -1449,7 +1449,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { visit::walk_attribute(self, attr); } - fn visit_arm(&mut self, arm: &'b ast::Arm) { + fn visit_arm(&mut self, arm: &'a ast::Arm) { if arm.is_placeholder { self.visit_invoc(arm.id); } else { @@ -1457,7 +1457,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_expr_field(&mut self, f: &'b ast::ExprField) { + fn visit_expr_field(&mut self, f: &'a ast::ExprField) { if f.is_placeholder { self.visit_invoc(f.id); } else { @@ -1465,7 +1465,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_pat_field(&mut self, fp: &'b ast::PatField) { + fn visit_pat_field(&mut self, fp: &'a ast::PatField) { if fp.is_placeholder { self.visit_invoc(fp.id); } else { @@ -1473,7 +1473,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_generic_param(&mut self, param: &'b ast::GenericParam) { + fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { if param.is_placeholder { self.visit_invoc(param.id); } else { @@ -1481,7 +1481,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_param(&mut self, p: &'b ast::Param) { + fn visit_param(&mut self, p: &'a ast::Param) { if p.is_placeholder { self.visit_invoc(p.id); } else { @@ -1489,7 +1489,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } } - fn visit_field_def(&mut self, sf: &'b ast::FieldDef) { + fn visit_field_def(&mut self, sf: &'a ast::FieldDef) { if sf.is_placeholder { self.visit_invoc(sf.id); } else { @@ -1501,7 +1501,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Constructs the reduced graph for one variant. Variants exist in the // type and value namespaces. - fn visit_variant(&mut self, variant: &'b ast::Variant) { + fn visit_variant(&mut self, variant: &'a ast::Variant) { if variant.is_placeholder { self.visit_invoc_in_module(variant.id); return; @@ -1542,7 +1542,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { visit::walk_variant(self, variant); } - fn visit_crate(&mut self, krate: &'b ast::Crate) { + fn visit_crate(&mut self, krate: &'a ast::Crate) { if krate.is_placeholder { self.visit_invoc_in_module(krate.id); } else { diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 1cee876b80f..8c434007f2c 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -52,8 +52,8 @@ impl UnusedImport { } } -struct UnusedImportCheckVisitor<'a, 'b, 'tcx> { - r: &'a mut Resolver<'b, 'tcx>, +struct UnusedImportCheckVisitor<'a, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, /// All the (so far) unused imports, grouped path list unused_imports: FxIndexMap, extern_crate_items: Vec, @@ -78,7 +78,7 @@ struct ExternCrateToLint { renames: bool, } -impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { // We have information about whether `use` (import) items are actually // used now. If an import is not used at all, we signal a lint error. fn check_import(&mut self, id: ast::NodeId) { @@ -212,7 +212,7 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> { } } -impl<'a, 'b, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> { fn visit_item(&mut self, item: &'a ast::Item) { match item.kind { // Ignore is_public import statements because there's no way to be sure diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 0fedb998463..87054dd04f5 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -25,15 +25,15 @@ pub(crate) fn collect_definitions( } /// Creates `DefId`s for nodes in the AST. -struct DefCollector<'a, 'b, 'tcx> { - resolver: &'a mut Resolver<'b, 'tcx>, +struct DefCollector<'a, 'ra, 'tcx> { + resolver: &'a mut Resolver<'ra, 'tcx>, parent_def: LocalDefId, impl_trait_context: ImplTraitContext, in_attr: bool, expansion: LocalExpnId, } -impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { fn create_def( &mut self, node_id: NodeId, @@ -119,7 +119,7 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { } } -impl<'a, 'b, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'b, 'tcx> { +impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { fn visit_item(&mut self, i: &'a Item) { // Pick the def data. This need not be unique, but the more // information we encapsulate into, the better diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index bcbdf627b56..f349713f22d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -123,7 +123,7 @@ fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span { sm.span_until_whitespace(impl_span) } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> { self.tcx.dcx() } @@ -208,8 +208,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { parent: Module<'_>, ident: Ident, ns: Namespace, - new_binding: NameBinding<'a>, - old_binding: NameBinding<'a>, + new_binding: NameBinding<'ra>, + old_binding: NameBinding<'ra>, ) { // Error on the second of two conflicting names if old_binding.span.lo() > new_binding.span.lo() { @@ -531,7 +531,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn add_module_candidates( &mut self, - module: Module<'a>, + module: Module<'ra>, names: &mut Vec, filter_fn: &impl Fn(Res) -> bool, ctxt: Option, @@ -553,7 +553,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn report_error( &mut self, span: Span, - resolution_error: ResolutionError<'a>, + resolution_error: ResolutionError<'ra>, ) -> ErrorGuaranteed { self.into_struct_error(span, resolution_error).emit() } @@ -561,7 +561,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn into_struct_error( &mut self, span: Span, - resolution_error: ResolutionError<'a>, + resolution_error: ResolutionError<'ra>, ) -> Diag<'_> { match resolution_error { ResolutionError::GenericParamsFromOuterItem( @@ -1020,8 +1020,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Lookup typo candidate in scope for a macro or import. fn early_lookup_typo_candidate( &mut self, - scope_set: ScopeSet<'a>, - parent_scope: &ParentScope<'a>, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, ident: Ident, filter_fn: &impl Fn(Res) -> bool, ) -> Option { @@ -1156,8 +1156,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, lookup_ident: Ident, namespace: Namespace, - parent_scope: &ParentScope<'a>, - start_module: Module<'a>, + parent_scope: &ParentScope<'ra>, + start_module: Module<'ra>, crate_path: ThinVec, filter_fn: FilterFn, ) -> Vec @@ -1343,7 +1343,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, lookup_ident: Ident, namespace: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, filter_fn: FilterFn, ) -> Vec where @@ -1421,7 +1421,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, err: &mut Diag<'_>, macro_kind: MacroKind, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ident: Ident, krate: &Crate, ) { @@ -1749,7 +1749,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'a>) { + fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) { let PrivacyError { ident, binding, outermost_res, parent_scope, single_nested, dedup_span } = *privacy_error; @@ -1954,7 +1954,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn find_similarly_named_module_or_crate( &mut self, ident: Symbol, - current_module: Module<'a>, + current_module: Module<'ra>, ) -> Option { let mut candidates = self .extern_prelude @@ -1982,11 +1982,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import - parent_scope: &ParentScope<'a>, - ribs: Option<&PerNS>>>, - ignore_binding: Option>, - ignore_import: Option>, - module: Option>, + parent_scope: &ParentScope<'ra>, + ribs: Option<&PerNS>>>, + ignore_binding: Option>, + ignore_import: Option>, + module: Option>, failed_segment_idx: usize, ident: Ident, ) -> (String, Option) { @@ -2228,7 +2228,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, span: Span, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { debug!("make_path_suggestion: span={:?} path={:?}", span, path); @@ -2263,7 +2263,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn make_missing_self_suggestion( &mut self, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { // Replace first ident with `self` and check if that is valid. path[0].ident.name = kw::SelfLower; @@ -2282,7 +2282,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn make_missing_crate_suggestion( &mut self, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = kw::Crate; @@ -2313,7 +2313,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn make_missing_super_suggestion( &mut self, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { // Replace first ident with `crate` and check if that is valid. path[0].ident.name = kw::Super; @@ -2335,7 +2335,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn make_external_crate_suggestion( &mut self, mut path: Vec, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, ) -> Option<(Vec, Option)> { if path[1].ident.span.is_rust_2015() { return None; @@ -2378,8 +2378,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// ``` pub(crate) fn check_for_module_export_macro( &mut self, - import: Import<'a>, - module: ModuleOrUniformRoot<'a>, + import: Import<'ra>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ) -> Option<(Option, Option)> { let ModuleOrUniformRoot::Module(mut crate_module) = module else { diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 5ee495da2d9..c91eed0e39b 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -11,9 +11,9 @@ use tracing::info; use crate::{NameBinding, NameBindingKind, Resolver}; #[derive(Clone, Copy)] -enum ParentId<'a> { +enum ParentId<'ra> { Def(LocalDefId), - Import(NameBinding<'a>), + Import(NameBinding<'ra>), } impl ParentId<'_> { @@ -25,13 +25,13 @@ impl ParentId<'_> { } } -pub(crate) struct EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { - r: &'r mut Resolver<'a, 'tcx>, +pub(crate) struct EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, def_effective_visibilities: EffectiveVisibilities, /// While walking import chains we need to track effective visibilities per-binding, and def id /// keys in `Resolver::effective_visibilities` are not enough for that, because multiple /// bindings can correspond to a single def id in imports. So we keep a separate table. - import_effective_visibilities: EffectiveVisibilities>, + import_effective_visibilities: EffectiveVisibilities>, // It's possible to recalculate this at any point, but it's relatively expensive. current_private_vis: Visibility, changed: bool, @@ -63,14 +63,14 @@ impl Resolver<'_, '_> { } } -impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { +impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { /// Fills the `Resolver::effective_visibilities` table with public & exported items /// For now, this doesn't resolve macros (FIXME) and cannot resolve Impl, as we /// need access to a TyCtxt for that. Returns the set of ambiguous re-exports. pub(crate) fn compute_effective_visibilities<'c>( - r: &'r mut Resolver<'a, 'tcx>, + r: &'a mut Resolver<'ra, 'tcx>, krate: &'c Crate, - ) -> FxHashSet> { + ) -> FxHashSet> { let mut visitor = EffectiveVisibilitiesVisitor { r, def_effective_visibilities: Default::default(), @@ -127,7 +127,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { // leading to it into the table. They are used by the `ambiguous_glob_reexports` // lint. For all bindings added to the table this way `is_ambiguity` returns true. let is_ambiguity = - |binding: NameBinding<'a>, warn: bool| binding.ambiguity.is_some() && !warn; + |binding: NameBinding<'ra>, warn: bool| binding.ambiguity.is_some() && !warn; let mut parent_id = ParentId::Def(module_id); let mut warn_ambiguity = binding.warn_ambiguity; while let NameBindingKind::Import { binding: nested_binding, .. } = binding.kind { @@ -153,7 +153,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } - fn effective_vis_or_private(&mut self, parent_id: ParentId<'a>) -> EffectiveVisibility { + fn effective_vis_or_private(&mut self, parent_id: ParentId<'ra>) -> EffectiveVisibility { // Private nodes are only added to the table for caching, they could be added or removed at // any moment without consequences, so we don't set `changed` to true when adding them. *match parent_id { @@ -190,7 +190,7 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } - fn update_import(&mut self, binding: NameBinding<'a>, parent_id: ParentId<'a>) { + fn update_import(&mut self, binding: NameBinding<'ra>, parent_id: ParentId<'ra>) { let nominal_vis = binding.vis.expect_local(); let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); @@ -205,7 +205,12 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { ); } - fn update_def(&mut self, def_id: LocalDefId, nominal_vis: Visibility, parent_id: ParentId<'a>) { + fn update_def( + &mut self, + def_id: LocalDefId, + nominal_vis: Visibility, + parent_id: ParentId<'ra>, + ) { let Some(cheap_private_vis) = self.may_update(nominal_vis, parent_id) else { return }; let inherited_eff_vis = self.effective_vis_or_private(parent_id); let tcx = self.r.tcx; @@ -224,8 +229,8 @@ impl<'r, 'a, 'tcx> EffectiveVisibilitiesVisitor<'r, 'a, 'tcx> { } } -impl<'r, 'ast, 'tcx> Visitor<'ast> for EffectiveVisibilitiesVisitor<'ast, 'r, 'tcx> { - fn visit_item(&mut self, item: &'ast ast::Item) { +impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { + fn visit_item(&mut self, item: &'a ast::Item) { let def_id = self.r.local_def_id(item.id); // Update effective visibilities of nested items. // If it's a mod, also make the visitor walk all of its items diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 87f8e51f282..1602db2f196 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -38,16 +38,16 @@ impl From for bool { } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// A generic scope visitor. /// Visits scopes in order to resolve some identifier in them or perform other actions. /// If the callback returns `Some` result, we stop visiting scopes and return it. pub(crate) fn visit_scopes( &mut self, - scope_set: ScopeSet<'a>, - parent_scope: &ParentScope<'a>, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, ctxt: SyntaxContext, - mut visitor: impl FnMut(&mut Self, Scope<'a>, UsePrelude, SyntaxContext) -> Option, + mut visitor: impl FnMut(&mut Self, Scope<'ra>, UsePrelude, SyntaxContext) -> Option, ) -> Option { // General principles: // 1. Not controlled (user-defined) names should have higher priority than controlled names @@ -218,10 +218,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn hygienic_lexical_parent( &mut self, - module: Module<'a>, + module: Module<'ra>, ctxt: &mut SyntaxContext, derive_fallback_lint_id: Option, - ) -> Option<(Module<'a>, Option)> { + ) -> Option<(Module<'ra>, Option)> { if !module.expansion.outer_expn_is_descendant_of(*ctxt) { return Some((self.expn_def_scope(ctxt.remove_mark()), None)); } @@ -286,11 +286,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, mut ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ribs: &[Rib<'a>], - ignore_binding: Option>, - ) -> Option> { + ribs: &[Rib<'ra>], + ignore_binding: Option>, + ) -> Option> { assert!(ns == TypeNS || ns == ValueNS); let orig_ident = ident; if ident.name == kw::Empty { @@ -381,13 +381,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn early_resolve_ident_in_lexical_scope( &mut self, orig_ident: Ident, - scope_set: ScopeSet<'a>, - parent_scope: &ParentScope<'a>, + scope_set: ScopeSet<'ra>, + parent_scope: &ParentScope<'ra>, finalize: Option, force: bool, - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, Determinacy> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, Determinacy> { bitflags::bitflags! { #[derive(Clone, Copy)] struct Flags: u8 { @@ -742,12 +742,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn maybe_resolve_ident_in_module( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, - ignore_import: Option>, - ) -> Result, Determinacy> { + parent_scope: &ParentScope<'ra>, + ignore_import: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None, ignore_import) .map_err(|(determinacy, _)| determinacy) } @@ -755,14 +755,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] pub(crate) fn resolve_ident_in_module( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, Determinacy> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_ext( module, ident, @@ -778,14 +778,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn resolve_ident_in_module_ext( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, mut ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, (Determinacy, Weak)> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, (Determinacy, Weak)> { let tmp_parent_scope; let mut adjusted_parent_scope = parent_scope; match module { @@ -818,14 +818,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn resolve_ident_in_module_unadjusted( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, Determinacy> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, Determinacy> { self.resolve_ident_in_module_unadjusted_ext( module, ident, @@ -844,17 +844,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn resolve_ident_in_module_unadjusted_ext( &mut self, - module: ModuleOrUniformRoot<'a>, + module: ModuleOrUniformRoot<'ra>, ident: Ident, ns: Namespace, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, restricted_shadowing: bool, finalize: Option, // This binding should be ignored during in-module resolution, so that we don't get // "self-confirming" import resolutions during import validation and checking. - ignore_binding: Option>, - ignore_import: Option>, - ) -> Result, (Determinacy, Weak)> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> Result, (Determinacy, Weak)> { let module = match module { ModuleOrUniformRoot::Module(module) => module, ModuleOrUniformRoot::CrateRootAndExternPrelude => { @@ -970,7 +970,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { return Ok(binding); } - let check_usable = |this: &mut Self, binding: NameBinding<'a>| { + let check_usable = |this: &mut Self, binding: NameBinding<'ra>| { let usable = this.is_accessible_from(binding.vis, parent_scope.module); if usable { Ok(binding) } else { Err((Determined, Weak::No)) } }; @@ -1151,7 +1151,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { mut res: Res, finalize: Option, original_rib_ident_def: Ident, - all_ribs: &[Rib<'a>], + all_ribs: &[Rib<'ra>], ) -> Res { debug!("validate_res_from_ribs({:?})", res); let ribs = &all_ribs[rib_index + 1..]; @@ -1436,9 +1436,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import - parent_scope: &ParentScope<'a>, - ignore_import: Option>, - ) -> PathResult<'a> { + parent_scope: &ParentScope<'ra>, + ignore_import: Option>, + ) -> PathResult<'ra> { self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None, ignore_import) } @@ -1447,11 +1447,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ignore_binding: Option>, - ignore_import: Option>, - ) -> PathResult<'a> { + ignore_binding: Option>, + ignore_import: Option>, + ) -> PathResult<'ra> { self.resolve_path_with_ribs( path, opt_ns, @@ -1467,12 +1467,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &[Segment], opt_ns: Option, // `None` indicates a module path in import - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, finalize: Option, - ribs: Option<&PerNS>>>, - ignore_binding: Option>, - ignore_import: Option>, - ) -> PathResult<'a> { + ribs: Option<&PerNS>>>, + ignore_binding: Option>, + ignore_import: Option>, + ) -> PathResult<'ra> { let mut module = None; let mut allow_super = true; let mut second_binding = None; diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 42171edf757..2edff67f96a 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -43,7 +43,7 @@ type Res = def::Res; /// Contains data for specific kinds of imports. #[derive(Clone)] -pub(crate) enum ImportKind<'a> { +pub(crate) enum ImportKind<'ra> { Single { /// `source` in `use prefix::source as target`. source: Ident, @@ -51,9 +51,9 @@ pub(crate) enum ImportKind<'a> { /// It will directly use `source` when the format is `use prefix::source`. target: Ident, /// Bindings to which `source` refers to. - source_bindings: PerNS, Determinacy>>>, + source_bindings: PerNS, Determinacy>>>, /// Bindings introduced by `target`. - target_bindings: PerNS>>>, + target_bindings: PerNS>>>, /// `true` for `...::{self [as target]}` imports, `false` otherwise. type_ns_only: bool, /// Did this import result from a nested import? ie. `use foo::{bar, baz};` @@ -93,7 +93,7 @@ pub(crate) enum ImportKind<'a> { /// Manually implement `Debug` for `ImportKind` because the `source/target_bindings` /// contain `Cell`s which can introduce infinite loops while printing. -impl<'a> std::fmt::Debug for ImportKind<'a> { +impl<'ra> std::fmt::Debug for ImportKind<'ra> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use ImportKind::*; match self { @@ -142,8 +142,8 @@ impl<'a> std::fmt::Debug for ImportKind<'a> { /// One import. #[derive(Debug, Clone)] -pub(crate) struct ImportData<'a> { - pub kind: ImportKind<'a>, +pub(crate) struct ImportData<'ra> { + pub kind: ImportKind<'ra>, /// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id` /// (if it exists) except in the case of "nested" use trees, in which case @@ -171,18 +171,18 @@ pub(crate) struct ImportData<'a> { /// Span of the *root* use tree (see `root_id`). pub root_span: Span, - pub parent_scope: ParentScope<'a>, + pub parent_scope: ParentScope<'ra>, pub module_path: Vec, /// The resolution of `module_path`. - pub imported_module: Cell>>, + pub imported_module: Cell>>, pub vis: ty::Visibility, } /// All imports are unique and allocated on a same arena, /// so we can use referential equality to compare them. -pub(crate) type Import<'a> = Interned<'a, ImportData<'a>>; +pub(crate) type Import<'ra> = Interned<'ra, ImportData<'ra>>; -impl<'a> ImportData<'a> { +impl<'ra> ImportData<'ra> { pub(crate) fn is_glob(&self) -> bool { matches!(self.kind, ImportKind::Glob { .. }) } @@ -217,18 +217,18 @@ impl<'a> ImportData<'a> { /// Records information about the resolution of a name in a namespace of a module. #[derive(Clone, Default, Debug)] -pub(crate) struct NameResolution<'a> { +pub(crate) struct NameResolution<'ra> { /// Single imports that may define the name in the namespace. /// Imports are arena-allocated, so it's ok to use pointers as keys. - pub single_imports: FxHashSet>, + pub single_imports: FxHashSet>, /// The least shadowable known binding for this name, or None if there are no known bindings. - pub binding: Option>, - pub shadowed_glob: Option>, + pub binding: Option>, + pub shadowed_glob: Option>, } -impl<'a> NameResolution<'a> { +impl<'ra> NameResolution<'ra> { /// Returns the binding for the name if it is known or None if it not known. - pub(crate) fn binding(&self) -> Option> { + pub(crate) fn binding(&self) -> Option> { self.binding.and_then(|binding| { if !binding.is_glob_import() || self.single_imports.is_empty() { Some(binding) @@ -270,10 +270,14 @@ fn pub_use_of_private_extern_crate_hack( } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Given a binding and an import that resolves to it, /// return the corresponding binding defined by the import. - pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> { + pub(crate) fn import( + &self, + binding: NameBinding<'ra>, + import: Import<'ra>, + ) -> NameBinding<'ra> { let import_vis = import.vis.to_def_id(); let vis = if binding.vis.is_at_least(import_vis, self.tcx) || pub_use_of_private_extern_crate_hack(import, binding).is_some() @@ -305,11 +309,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// `update` indicates if the definition is a redefinition of an existing binding. pub(crate) fn try_define( &mut self, - module: Module<'a>, + module: Module<'ra>, key: BindingKey, - binding: NameBinding<'a>, + binding: NameBinding<'ra>, warn_ambiguity: bool, - ) -> Result<(), NameBinding<'a>> { + ) -> Result<(), NameBinding<'ra>> { let res = binding.res(); self.check_reserved_macro_name(key.ident, res); self.set_binding_parent_module(binding, module); @@ -394,16 +398,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn new_ambiguity_binding( &self, ambiguity_kind: AmbiguityKind, - primary_binding: NameBinding<'a>, - secondary_binding: NameBinding<'a>, + primary_binding: NameBinding<'ra>, + secondary_binding: NameBinding<'ra>, warn_ambiguity: bool, - ) -> NameBinding<'a> { + ) -> NameBinding<'ra> { let ambiguity = Some((secondary_binding, ambiguity_kind)); let data = NameBindingData { ambiguity, warn_ambiguity, ..*primary_binding }; self.arenas.alloc_name_binding(data) } - fn new_warn_ambiguity_binding(&self, binding: NameBinding<'a>) -> NameBinding<'a> { + fn new_warn_ambiguity_binding(&self, binding: NameBinding<'ra>) -> NameBinding<'ra> { assert!(binding.is_ambiguity_recursive()); self.arenas.alloc_name_binding(NameBindingData { warn_ambiguity: true, ..*binding }) } @@ -412,13 +416,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // If the resolution becomes a success, define it in the module's glob importers. fn update_resolution( &mut self, - module: Module<'a>, + module: Module<'ra>, key: BindingKey, warn_ambiguity: bool, f: F, ) -> T where - F: FnOnce(&mut Resolver<'a, 'tcx>, &mut NameResolution<'a>) -> T, + F: FnOnce(&mut Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> T, { // Ensure that `resolution` isn't borrowed when defining in the module's glob importers, // during which the resolution might end up getting re-defined via a glob cycle. @@ -466,7 +470,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics. - fn import_dummy_binding(&mut self, import: Import<'a>, is_indeterminate: bool) { + fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool) { if let ImportKind::Single { target, ref target_bindings, .. } = import.kind { if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none())) { @@ -599,7 +603,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pub(crate) fn check_hidden_glob_reexports( &mut self, - exported_ambiguities: FxHashSet>, + exported_ambiguities: FxHashSet>, ) { for module in self.arenas.local_modules().iter() { for (key, resolution) in self.resolutions(*module).borrow().iter() { @@ -759,7 +763,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Meanwhile, if resolve successful, the resolved bindings are written /// into the module. - fn resolve_import(&mut self, import: Import<'a>) -> usize { + fn resolve_import(&mut self, import: Import<'ra>) -> usize { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", Segment::names_to_string(&import.module_path), @@ -847,7 +851,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// /// Optionally returns an unresolved import error. This error is buffered and used to /// consolidate multiple unresolved import errors into a single diagnostic. - fn finalize_import(&mut self, import: Import<'a>) -> Option { + fn finalize_import(&mut self, import: Import<'ra>) -> Option { let ignore_binding = match &import.kind { ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(), _ => None, @@ -1323,7 +1327,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) -> bool { + pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool { // This function is only called for single imports. let ImportKind::Single { source, target, ref source_bindings, ref target_bindings, id, .. @@ -1398,7 +1402,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false } - fn resolve_glob_import(&mut self, import: Import<'a>) { + fn resolve_glob_import(&mut self, import: Import<'ra>) { // This function is only called for glob imports. let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() }; @@ -1458,7 +1462,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Miscellaneous post-processing, including recording re-exports, // reporting conflicts, and reporting unresolved imports. - fn finalize_resolutions_in(&mut self, module: Module<'a>) { + fn finalize_resolutions_in(&mut self, module: Module<'ra>) { // Since import resolution is finished, globs will not define any more names. *module.globs.borrow_mut() = Vec::new(); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 917cb81aa51..8ebfe328e3e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -172,7 +172,7 @@ enum RecordPartialRes { /// The rib kind restricts certain accesses, /// e.g. to a `Res::Local` of an outer item. #[derive(Copy, Clone, Debug)] -pub(crate) enum RibKind<'a> { +pub(crate) enum RibKind<'ra> { /// No restriction needs to be applied. Normal, @@ -195,7 +195,7 @@ pub(crate) enum RibKind<'a> { ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>), /// We passed through a module. - Module(Module<'a>), + Module(Module<'ra>), /// We passed through a `macro_rules!` statement MacroDefinition(DefId), @@ -260,13 +260,13 @@ impl RibKind<'_> { /// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When /// resolving, the name is looked up from inside out. #[derive(Debug)] -pub(crate) struct Rib<'a, R = Res> { +pub(crate) struct Rib<'ra, R = Res> { pub bindings: IdentMap, - pub kind: RibKind<'a>, + pub kind: RibKind<'ra>, } -impl<'a, R> Rib<'a, R> { - fn new(kind: RibKind<'a>) -> Rib<'a, R> { +impl<'ra, R> Rib<'ra, R> { + fn new(kind: RibKind<'ra>) -> Rib<'ra, R> { Rib { bindings: Default::default(), kind } } } @@ -584,8 +584,8 @@ impl MaybeExported<'_> { /// Used for recording UnnecessaryQualification. #[derive(Debug)] -pub(crate) struct UnnecessaryQualification<'a> { - pub binding: LexicalScopeBinding<'a>, +pub(crate) struct UnnecessaryQualification<'ra> { + pub binding: LexicalScopeBinding<'ra>, pub node_id: NodeId, pub path_span: Span, pub removal_span: Span, @@ -659,20 +659,20 @@ struct DiagMetadata<'ast> { current_elision_failures: Vec, } -struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { - r: &'b mut Resolver<'a, 'tcx>, +struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, /// The module that represents the current item scope. - parent_scope: ParentScope<'a>, + parent_scope: ParentScope<'ra>, /// The current set of local scopes for types and values. - ribs: PerNS>>, + ribs: PerNS>>, /// Previous popped `rib`, only used for diagnostic. - last_block_rib: Option>, + last_block_rib: Option>, /// The current set of local scopes, for labels. - label_ribs: Vec>, + label_ribs: Vec>, /// The current set of local scopes for lifetimes. lifetime_ribs: Vec, @@ -685,7 +685,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { lifetime_elision_candidates: Option>, /// The trait that the current context can refer to. - current_trait_ref: Option<(Module<'a>, TraitRef)>, + current_trait_ref: Option<(Module<'ra>, TraitRef)>, /// Fields used to add information to diagnostic errors. diag_metadata: Box>, @@ -702,7 +702,7 @@ struct LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. -impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, 'tcx> { +impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn visit_attribute(&mut self, _: &'ast Attribute) { // We do not want to resolve expressions that appear in attributes, // as they do not correspond to actual code. @@ -1316,8 +1316,8 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } } -impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { - fn new(resolver: &'b mut Resolver<'a, 'tcx>) -> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { +impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { + fn new(resolver: &'a mut Resolver<'ra, 'tcx>) -> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // During late resolution we only track the module component of the parent scope, // although it may be useful to track other components as well for diagnostics. let graph_root = resolver.graph_root; @@ -1347,7 +1347,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { &mut self, ident: Ident, ns: Namespace, - ) -> Option> { + ) -> Option> { self.r.resolve_ident_in_lexical_scope( ident, ns, @@ -1363,8 +1363,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ident: Ident, ns: Namespace, finalize: Option, - ignore_binding: Option>, - ) -> Option> { + ignore_binding: Option>, + ) -> Option> { self.r.resolve_ident_in_lexical_scope( ident, ns, @@ -1380,7 +1380,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { path: &[Segment], opt_ns: Option, // `None` indicates a module path in import finalize: Option, - ) -> PathResult<'a> { + ) -> PathResult<'ra> { self.r.resolve_path_with_ribs( path, opt_ns, @@ -1414,7 +1414,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn with_rib( &mut self, ns: Namespace, - kind: RibKind<'a>, + kind: RibKind<'ra>, work: impl FnOnce(&mut Self) -> T, ) -> T { self.ribs[ns].push(Rib::new(kind)); @@ -2266,14 +2266,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Visits a type to find all the &references, and determines the /// set of lifetimes for all of those references where the referent /// contains Self. - struct FindReferenceVisitor<'r, 'a, 'tcx> { - r: &'r Resolver<'a, 'tcx>, + struct FindReferenceVisitor<'a, 'ra, 'tcx> { + r: &'a Resolver<'ra, 'tcx>, impl_self: Option, lifetime: Set1, } - impl<'a> Visitor<'a> for FindReferenceVisitor<'_, '_, '_> { - fn visit_ty(&mut self, ty: &'a Ty) { + impl<'ra> Visitor<'ra> for FindReferenceVisitor<'_, '_, '_> { + fn visit_ty(&mut self, ty: &'ra Ty) { trace!("FindReferenceVisitor considering ty={:?}", ty); if let TyKind::Ref(lt, _) = ty.kind { // See if anything inside the &thing contains Self @@ -2299,13 +2299,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // A type may have an expression as a const generic argument. // We do not want to recurse into those. - fn visit_expr(&mut self, _: &'a Expr) {} + fn visit_expr(&mut self, _: &'ra Expr) {} } /// Visitor which checks the referent of a &Thing to see if the /// Thing contains Self - struct SelfVisitor<'r, 'a, 'tcx> { - r: &'r Resolver<'a, 'tcx>, + struct SelfVisitor<'a, 'ra, 'tcx> { + r: &'a Resolver<'ra, 'tcx>, impl_self: Option, self_found: bool, } @@ -2327,8 +2327,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } } - impl<'a> Visitor<'a> for SelfVisitor<'_, '_, '_> { - fn visit_ty(&mut self, ty: &'a Ty) { + impl<'ra> Visitor<'ra> for SelfVisitor<'_, '_, '_> { + fn visit_ty(&mut self, ty: &'ra Ty) { trace!("SelfVisitor considering ty={:?}", ty); if self.is_self_ty(ty) { trace!("SelfVisitor found Self"); @@ -2339,7 +2339,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // A type may have an expression as a const generic argument. // We do not want to recurse into those. - fn visit_expr(&mut self, _: &'a Expr) {} + fn visit_expr(&mut self, _: &'ra Expr) {} } let impl_self = self @@ -2371,7 +2371,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved /// label and reports an error if the label is not found or is unreachable. - fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'a>> { + fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'ra>> { let mut suggestion = None; for i in (0..self.label_ribs.len()).rev() { @@ -2712,7 +2712,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { fn with_generic_param_rib<'c, F>( &'c mut self, params: &'c [GenericParam], - kind: RibKind<'a>, + kind: RibKind<'ra>, lifetime_kind: LifetimeRibKind, f: F, ) where @@ -2878,7 +2878,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { } } - fn with_label_rib(&mut self, kind: RibKind<'a>, f: impl FnOnce(&mut Self)) { + fn with_label_rib(&mut self, kind: RibKind<'ra>, f: impl FnOnce(&mut Self)) { self.label_ribs.push(Rib::new(kind)); f(self); self.label_ribs.pop(); @@ -3306,7 +3306,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { seen_trait_items: &mut FxHashMap, err: F, ) where - F: FnOnce(Ident, String, Option) -> ResolutionError<'a>, + F: FnOnce(Ident, String, Option) -> ResolutionError<'ra>, { // If there is a TraitRef in scope for an impl, then the method must be in the trait. let Some((module, _)) = self.current_trait_ref else { @@ -4010,101 +4010,102 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { // about possible missing imports. // // Similar thing, for types, happens in `report_errors` above. - let report_errors_for_call = |this: &mut Self, parent_err: Spanned>| { - // Before we start looking for candidates, we have to get our hands - // on the type user is trying to perform invocation on; basically: - // we're transforming `HashMap::new` into just `HashMap`. - let (following_seg, prefix_path) = match path.split_last() { - Some((last, path)) if !path.is_empty() => (Some(last), path), - _ => return Some(parent_err), - }; - - let (mut err, candidates) = this.smart_resolve_report_errors( - prefix_path, - following_seg, - path_span, - PathSource::Type, - None, - ); - - // There are two different error messages user might receive at - // this point: - // - E0412 cannot find type `{}` in this scope - // - E0433 failed to resolve: use of undeclared type or module `{}` - // - // The first one is emitted for paths in type-position, and the - // latter one - for paths in expression-position. - // - // Thus (since we're in expression-position at this point), not to - // confuse the user, we want to keep the *message* from E0433 (so - // `parent_err`), but we want *hints* from E0412 (so `err`). - // - // And that's what happens below - we're just mixing both messages - // into a single one. - let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); - - // overwrite all properties with the parent's error message - err.messages = take(&mut parent_err.messages); - err.code = take(&mut parent_err.code); - swap(&mut err.span, &mut parent_err.span); - err.children = take(&mut parent_err.children); - err.sort_span = parent_err.sort_span; - err.is_lint = parent_err.is_lint.clone(); - - // merge the parent's suggestions with the typo suggestions - fn append_result(res1: &mut Result, E>, res2: Result, E>) { - match res1 { - Ok(vec1) => match res2 { - Ok(mut vec2) => vec1.append(&mut vec2), - Err(e) => *res1 = Err(e), - }, - Err(_) => (), + let report_errors_for_call = + |this: &mut Self, parent_err: Spanned>| { + // Before we start looking for candidates, we have to get our hands + // on the type user is trying to perform invocation on; basically: + // we're transforming `HashMap::new` into just `HashMap`. + let (following_seg, prefix_path) = match path.split_last() { + Some((last, path)) if !path.is_empty() => (Some(last), path), + _ => return Some(parent_err), }; - } - append_result(&mut err.suggestions, parent_err.suggestions.clone()); - parent_err.cancel(); + let (mut err, candidates) = this.smart_resolve_report_errors( + prefix_path, + following_seg, + path_span, + PathSource::Type, + None, + ); - let def_id = this.parent_scope.module.nearest_parent_mod(); + // There are two different error messages user might receive at + // this point: + // - E0412 cannot find type `{}` in this scope + // - E0433 failed to resolve: use of undeclared type or module `{}` + // + // The first one is emitted for paths in type-position, and the + // latter one - for paths in expression-position. + // + // Thus (since we're in expression-position at this point), not to + // confuse the user, we want to keep the *message* from E0433 (so + // `parent_err`), but we want *hints* from E0412 (so `err`). + // + // And that's what happens below - we're just mixing both messages + // into a single one. + let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node); - if this.should_report_errs() { - if candidates.is_empty() { - if path.len() == 2 - && let [segment] = prefix_path - { - // Delay to check whether methond name is an associated function or not - // ``` - // let foo = Foo {}; - // foo::bar(); // possibly suggest to foo.bar(); - //``` - err.stash(segment.ident.span, rustc_errors::StashKey::CallAssocMethod); + // overwrite all properties with the parent's error message + err.messages = take(&mut parent_err.messages); + err.code = take(&mut parent_err.code); + swap(&mut err.span, &mut parent_err.span); + err.children = take(&mut parent_err.children); + err.sort_span = parent_err.sort_span; + err.is_lint = parent_err.is_lint.clone(); + + // merge the parent's suggestions with the typo suggestions + fn append_result(res1: &mut Result, E>, res2: Result, E>) { + match res1 { + Ok(vec1) => match res2 { + Ok(mut vec2) => vec1.append(&mut vec2), + Err(e) => *res1 = Err(e), + }, + Err(_) => (), + }; + } + append_result(&mut err.suggestions, parent_err.suggestions.clone()); + + parent_err.cancel(); + + let def_id = this.parent_scope.module.nearest_parent_mod(); + + if this.should_report_errs() { + if candidates.is_empty() { + if path.len() == 2 + && let [segment] = prefix_path + { + // Delay to check whether methond name is an associated function or not + // ``` + // let foo = Foo {}; + // foo::bar(); // possibly suggest to foo.bar(); + //``` + err.stash(segment.ident.span, rustc_errors::StashKey::CallAssocMethod); + } else { + // When there is no suggested imports, we can just emit the error + // and suggestions immediately. Note that we bypass the usually error + // reporting routine (ie via `self.r.report_error`) because we need + // to post-process the `ResolutionError` above. + err.emit(); + } } else { - // When there is no suggested imports, we can just emit the error - // and suggestions immediately. Note that we bypass the usually error - // reporting routine (ie via `self.r.report_error`) because we need - // to post-process the `ResolutionError` above. - err.emit(); + // If there are suggested imports, the error reporting is delayed + this.r.use_injections.push(UseError { + err, + candidates, + def_id, + instead: false, + suggestion: None, + path: prefix_path.into(), + is_call: source.is_call(), + }); } } else { - // If there are suggested imports, the error reporting is delayed - this.r.use_injections.push(UseError { - err, - candidates, - def_id, - instead: false, - suggestion: None, - path: prefix_path.into(), - is_call: source.is_call(), - }); + err.cancel(); } - } else { - err.cancel(); - } - // We don't return `Some(parent_err)` here, because the error will - // be already printed either immediately or as part of the `use` injections - None - }; + // We don't return `Some(parent_err)` here, because the error will + // be already printed either immediately or as part of the `use` injections + None + }; let partial_res = match self.resolve_qpath_anywhere( qself, @@ -4205,7 +4206,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// A wrapper around [`Resolver::report_error`]. /// /// This doesn't emit errors for function bodies if this is rustdoc. - fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'a>) { + fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'ra>) { if self.should_report_errs() { self.r.report_error(span, resolution_error); } @@ -4229,7 +4230,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { span: Span, defer_to_typeck: bool, finalize: Finalize, - ) -> Result, Spanned>> { + ) -> Result, Spanned>> { let mut fin_res = None; for (i, &ns) in [primary_ns, TypeNS, ValueNS].iter().enumerate() { @@ -4271,7 +4272,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { path: &[Segment], ns: Namespace, finalize: Finalize, - ) -> Result, Spanned>> { + ) -> Result, Spanned>> { debug!( "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})", qself, path, ns, finalize, @@ -4922,8 +4923,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { /// Walks the whole crate in DFS order, visiting each item, counting the declared number of /// lifetime generic parameters and function parameters. -struct ItemInfoCollector<'a, 'b, 'tcx> { - r: &'b mut Resolver<'a, 'tcx>, +struct ItemInfoCollector<'a, 'ra, 'tcx> { + r: &'a mut Resolver<'ra, 'tcx>, } impl ItemInfoCollector<'_, '_, '_> { @@ -4990,7 +4991,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { visit::walk_crate(&mut ItemInfoCollector { r: self }, krate); let mut late_resolution_visitor = LateResolutionVisitor::new(self); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 8f516c2db09..fb658407f61 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -170,7 +170,7 @@ impl TypoCandidate { } } -impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { +impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn make_base_error( &mut self, path: &[Segment], @@ -2278,7 +2278,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { false } - fn find_module(&mut self, def_id: DefId) -> Option<(Module<'a>, ImportSuggestion)> { + fn find_module(&mut self, def_id: DefId) -> Option<(Module<'ra>, ImportSuggestion)> { let mut result = None; let mut seen_modules = FxHashSet::default(); let root_did = self.r.graph_root.def_id(); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 8ffd00d1b2e..872535627a5 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -113,14 +113,14 @@ impl Determinacy { /// This enum is currently used only for early resolution (imports and macros), /// but not for late resolution yet. #[derive(Clone, Copy, Debug)] -enum Scope<'a> { +enum Scope<'ra> { DeriveHelpers(LocalExpnId), DeriveHelpersCompat, - MacroRules(MacroRulesScopeRef<'a>), + MacroRules(MacroRulesScopeRef<'ra>), CrateRoot, // The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK` // lint if it should be reported. - Module(Module<'a>, Option), + Module(Module<'ra>, Option), MacroUsePrelude, BuiltinAttrs, ExternPrelude, @@ -134,7 +134,7 @@ enum Scope<'a> { /// This enum is currently used only for early resolution (imports and macros), /// but not for late resolution yet. #[derive(Clone, Copy, Debug)] -enum ScopeSet<'a> { +enum ScopeSet<'ra> { /// All scopes with the given namespace. All(Namespace), /// Crate root, then extern prelude (used for mixed 2015-2018 mode in macros). @@ -143,7 +143,7 @@ enum ScopeSet<'a> { Macro(MacroKind), /// All scopes with the given namespace, used for partially performing late resolution. /// The node id enables lints and is used for reporting them. - Late(Namespace, Module<'a>, Option), + Late(Namespace, Module<'ra>, Option), } /// Everything you need to know about a name's location to resolve it. @@ -151,17 +151,17 @@ enum ScopeSet<'a> { /// This struct is currently used only for early resolution (imports and macros), /// but not for late resolution yet. #[derive(Clone, Copy, Debug)] -struct ParentScope<'a> { - module: Module<'a>, +struct ParentScope<'ra> { + module: Module<'ra>, expansion: LocalExpnId, - macro_rules: MacroRulesScopeRef<'a>, - derives: &'a [ast::Path], + macro_rules: MacroRulesScopeRef<'ra>, + derives: &'ra [ast::Path], } -impl<'a> ParentScope<'a> { +impl<'ra> ParentScope<'ra> { /// Creates a parent scope with the passed argument used as the module scope component, /// and other scope components set to default empty values. - fn module(module: Module<'a>, resolver: &Resolver<'a, '_>) -> ParentScope<'a> { + fn module(module: Module<'ra>, resolver: &Resolver<'ra, '_>) -> ParentScope<'ra> { ParentScope { module, expansion: LocalExpnId::ROOT, @@ -203,7 +203,7 @@ struct BindingError { } #[derive(Debug)] -enum ResolutionError<'a> { +enum ResolutionError<'ra> { /// Error E0401: can't use type or const parameters from outer item. GenericParamsFromOuterItem(Res, HasGenericParams, DefKind), /// Error E0403: the name is already used for a type or const parameter in this generic @@ -216,7 +216,7 @@ enum ResolutionError<'a> { /// Error E0438: const is not a member of trait. ConstNotMemberOfTrait(Ident, String, Option), /// Error E0408: variable `{}` is not bound in all patterns. - VariableNotBoundInPattern(BindingError, ParentScope<'a>), + VariableNotBoundInPattern(BindingError, ParentScope<'ra>), /// Error E0409: variable `{}` is bound in inconsistent ways within the same match arm. VariableBoundWithDifferentMode(Symbol, Span), /// Error E0415: identifier is bound more than once in this parameter list. @@ -236,7 +236,7 @@ enum ResolutionError<'a> { segment: Option, label: String, suggestion: Option, - module: Option>, + module: Option>, }, /// Error E0434: can't capture dynamic environment in a fn item. CannotCaptureDynamicEnvironmentInFnItem, @@ -377,12 +377,12 @@ impl<'a> From<&'a ast::PathSegment> for Segment { /// items are visible in their whole block, while `Res`es only from the place they are defined /// forward. #[derive(Debug, Copy, Clone)] -enum LexicalScopeBinding<'a> { - Item(NameBinding<'a>), +enum LexicalScopeBinding<'ra> { + Item(NameBinding<'ra>), Res(Res), } -impl<'a> LexicalScopeBinding<'a> { +impl<'ra> LexicalScopeBinding<'ra> { fn res(self) -> Res { match self { LexicalScopeBinding::Item(binding) => binding.res(), @@ -392,9 +392,9 @@ impl<'a> LexicalScopeBinding<'a> { } #[derive(Copy, Clone, PartialEq, Debug)] -enum ModuleOrUniformRoot<'a> { +enum ModuleOrUniformRoot<'ra> { /// Regular module. - Module(Module<'a>), + Module(Module<'ra>), /// Virtual module that denotes resolution in crate root with fallback to extern prelude. CrateRootAndExternPrelude, @@ -410,8 +410,8 @@ enum ModuleOrUniformRoot<'a> { } #[derive(Debug)] -enum PathResult<'a> { - Module(ModuleOrUniformRoot<'a>), +enum PathResult<'ra> { + Module(ModuleOrUniformRoot<'ra>), NonModule(PartialRes), Indeterminate, Failed { @@ -432,20 +432,20 @@ enum PathResult<'a> { /// ``` /// /// In this case, `module` will point to `a`. - module: Option>, + module: Option>, /// The segment name of target segment_name: Symbol, }, } -impl<'a> PathResult<'a> { +impl<'ra> PathResult<'ra> { fn failed( ident: Ident, is_error_from_last_segment: bool, finalize: bool, - module: Option>, + module: Option>, label_and_suggestion: impl FnOnce() -> (String, Option), - ) -> PathResult<'a> { + ) -> PathResult<'ra> { let (label, suggestion) = if finalize { label_and_suggestion() } else { (String::new(), None) }; PathResult::Failed { @@ -518,7 +518,7 @@ impl BindingKey { } } -type Resolutions<'a> = RefCell>>>; +type Resolutions<'ra> = RefCell>>>; /// One node in the tree of modules. /// @@ -531,15 +531,15 @@ type Resolutions<'a> = RefCell { +struct ModuleData<'ra> { /// The direct parent module (it may not be a `mod`, however). - parent: Option>, + parent: Option>, /// What kind of module this is, because this may not be a `mod`. kind: ModuleKind, /// Mapping between names and their (possibly in-progress) resolutions in this module. /// Resolutions in modules from other crates are not populated until accessed. - lazy_resolutions: Resolutions<'a>, + lazy_resolutions: Resolutions<'ra>, /// True if this is a module from other crate that needs to be populated on access. populate_on_access: Cell, @@ -549,11 +549,11 @@ struct ModuleData<'a> { /// Whether `#[no_implicit_prelude]` is active. no_implicit_prelude: bool, - glob_importers: RefCell>>, - globs: RefCell>>, + glob_importers: RefCell>>, + globs: RefCell>>, /// Used to memoize the traits in this module for faster searches through all traits in scope. - traits: RefCell)]>>>, + traits: RefCell)]>>>, /// Span of the module itself. Used for error reporting. span: Span, @@ -565,11 +565,11 @@ struct ModuleData<'a> { /// so we can use referential equality to compare them. #[derive(Clone, Copy, PartialEq, Eq, Hash)] #[rustc_pass_by_value] -struct Module<'a>(Interned<'a, ModuleData<'a>>); +struct Module<'ra>(Interned<'ra, ModuleData<'ra>>); -impl<'a> ModuleData<'a> { +impl<'ra> ModuleData<'ra> { fn new( - parent: Option>, + parent: Option>, kind: ModuleKind, expansion: ExpnId, span: Span, @@ -595,11 +595,11 @@ impl<'a> ModuleData<'a> { } } -impl<'a> Module<'a> { +impl<'ra> Module<'ra> { fn for_each_child<'tcx, R, F>(self, resolver: &mut R, mut f: F) where - R: AsMut>, - F: FnMut(&mut R, Ident, Namespace, NameBinding<'a>), + R: AsMut>, + F: FnMut(&mut R, Ident, Namespace, NameBinding<'ra>), { for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() { if let Some(binding) = name_resolution.borrow().binding { @@ -611,7 +611,7 @@ impl<'a> Module<'a> { /// This modifies `self` in place. The traits will be stored in `self.traits`. fn ensure_traits<'tcx, R>(self, resolver: &mut R) where - R: AsMut>, + R: AsMut>, { let mut traits = self.traits.borrow_mut(); if traits.is_none() { @@ -656,7 +656,7 @@ impl<'a> Module<'a> { matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _)) } - fn nearest_item_scope(self) -> Module<'a> { + fn nearest_item_scope(self) -> Module<'ra> { match self.kind { ModuleKind::Def(DefKind::Enum | DefKind::Trait, ..) => { self.parent.expect("enum or trait module without a parent") @@ -686,15 +686,15 @@ impl<'a> Module<'a> { } } -impl<'a> std::ops::Deref for Module<'a> { - type Target = ModuleData<'a>; +impl<'ra> std::ops::Deref for Module<'ra> { + type Target = ModuleData<'ra>; fn deref(&self) -> &Self::Target { &self.0 } } -impl<'a> fmt::Debug for Module<'a> { +impl<'ra> fmt::Debug for Module<'ra> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.res()) } @@ -702,9 +702,9 @@ impl<'a> fmt::Debug for Module<'a> { /// Records a possibly-private value, type, or module definition. #[derive(Clone, Copy, Debug)] -struct NameBindingData<'a> { - kind: NameBindingKind<'a>, - ambiguity: Option<(NameBinding<'a>, AmbiguityKind)>, +struct NameBindingData<'ra> { + kind: NameBindingKind<'ra>, + ambiguity: Option<(NameBinding<'ra>, AmbiguityKind)>, /// Produce a warning instead of an error when reporting ambiguities inside this binding. /// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required. warn_ambiguity: bool, @@ -715,26 +715,26 @@ struct NameBindingData<'a> { /// All name bindings are unique and allocated on a same arena, /// so we can use referential equality to compare them. -type NameBinding<'a> = Interned<'a, NameBindingData<'a>>; +type NameBinding<'ra> = Interned<'ra, NameBindingData<'ra>>; -trait ToNameBinding<'a> { - fn to_name_binding(self, arenas: &'a ResolverArenas<'a>) -> NameBinding<'a>; +trait ToNameBinding<'ra> { + fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra>; } -impl<'a> ToNameBinding<'a> for NameBinding<'a> { - fn to_name_binding(self, _: &'a ResolverArenas<'a>) -> NameBinding<'a> { +impl<'ra> ToNameBinding<'ra> for NameBinding<'ra> { + fn to_name_binding(self, _: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> { self } } #[derive(Clone, Copy, Debug)] -enum NameBindingKind<'a> { +enum NameBindingKind<'ra> { Res(Res), - Module(Module<'a>), - Import { binding: NameBinding<'a>, import: Import<'a> }, + Module(Module<'ra>), + Import { binding: NameBinding<'ra>, import: Import<'ra> }, } -impl<'a> NameBindingKind<'a> { +impl<'ra> NameBindingKind<'ra> { /// Is this a name binding of an import? fn is_import(&self) -> bool { matches!(*self, NameBindingKind::Import { .. }) @@ -742,12 +742,12 @@ impl<'a> NameBindingKind<'a> { } #[derive(Debug)] -struct PrivacyError<'a> { +struct PrivacyError<'ra> { ident: Ident, - binding: NameBinding<'a>, + binding: NameBinding<'ra>, dedup_span: Span, outermost_res: Option<(Res, Ident)>, - parent_scope: ParentScope<'a>, + parent_scope: ParentScope<'ra>, /// Is the format `use a::{b,c}`? single_nested: bool, } @@ -812,18 +812,18 @@ enum AmbiguityErrorMisc { None, } -struct AmbiguityError<'a> { +struct AmbiguityError<'ra> { kind: AmbiguityKind, ident: Ident, - b1: NameBinding<'a>, - b2: NameBinding<'a>, + b1: NameBinding<'ra>, + b2: NameBinding<'ra>, misc1: AmbiguityErrorMisc, misc2: AmbiguityErrorMisc, warning: bool, } -impl<'a> NameBindingData<'a> { - fn module(&self) -> Option> { +impl<'ra> NameBindingData<'ra> { + fn module(&self) -> Option> { match self.kind { NameBindingKind::Module(module) => Some(module), NameBindingKind::Import { binding, .. } => binding.module(), @@ -947,8 +947,8 @@ impl<'a> NameBindingData<'a> { } #[derive(Default, Clone)] -struct ExternPreludeEntry<'a> { - binding: Option>, +struct ExternPreludeEntry<'ra> { + binding: Option>, introduced_by_item: bool, } @@ -985,16 +985,16 @@ impl MacroData { /// The main resolver class. /// /// This is the visitor that walks the whole crate. -pub struct Resolver<'a, 'tcx> { +pub struct Resolver<'ra, 'tcx> { tcx: TyCtxt<'tcx>, /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. expn_that_defined: FxHashMap, - graph_root: Module<'a>, + graph_root: Module<'ra>, - prelude: Option>, - extern_prelude: FxHashMap>, + prelude: Option>, + extern_prelude: FxHashMap>, /// N.B., this is used only for better diagnostics, not name resolution itself. field_names: LocalDefIdMap>, @@ -1004,10 +1004,10 @@ pub struct Resolver<'a, 'tcx> { field_visibility_spans: FxHashMap>, /// All imports known to succeed or fail. - determined_imports: Vec>, + determined_imports: Vec>, /// All non-determined imports. - indeterminate_imports: Vec>, + indeterminate_imports: Vec>, // Spans for local variables found during pattern resolution. // Used for suggestions during error reporting. @@ -1018,7 +1018,7 @@ pub struct Resolver<'a, 'tcx> { /// Resolutions for import nodes, which have multiple resolutions in different namespaces. import_res_map: NodeMap>>, /// An import will be inserted into this map if it has been used. - import_use_map: FxHashMap, Used>, + import_use_map: FxHashMap, Used>, /// Resolutions for labels (node IDs of their corresponding blocks or loops). label_res_map: NodeMap, /// Resolutions for lifetimes. @@ -1045,13 +1045,13 @@ pub struct Resolver<'a, 'tcx> { /// /// There will be an anonymous module created around `g` with the ID of the /// entry block for `f`. - block_map: NodeMap>, + block_map: NodeMap>, /// A fake module that contains no definition and no prelude. Used so that /// some AST passes can generate identifiers that only resolve to local or /// lang items. - empty_module: Module<'a>, - module_map: FxHashMap>, - binding_parent_modules: FxHashMap, Module<'a>>, + empty_module: Module<'ra>, + module_map: FxHashMap>, + binding_parent_modules: FxHashMap, Module<'ra>>, underscore_disambiguator: u32, /// Disambiguator for anonymous adts. @@ -1065,57 +1065,57 @@ pub struct Resolver<'a, 'tcx> { maybe_unused_trait_imports: FxIndexSet, /// Privacy errors are delayed until the end in order to deduplicate them. - privacy_errors: Vec>, + privacy_errors: Vec>, /// Ambiguity errors are delayed for deduplication. - ambiguity_errors: Vec>, + ambiguity_errors: Vec>, /// `use` injections are delayed for better placement and deduplication. use_injections: Vec>, /// Crate-local macro expanded `macro_export` referred to by a module-relative path. macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>, - arenas: &'a ResolverArenas<'a>, - dummy_binding: NameBinding<'a>, - builtin_types_bindings: FxHashMap>, - builtin_attrs_bindings: FxHashMap>, - registered_tool_bindings: FxHashMap>, + arenas: &'ra ResolverArenas<'ra>, + dummy_binding: NameBinding<'ra>, + builtin_types_bindings: FxHashMap>, + builtin_attrs_bindings: FxHashMap>, + registered_tool_bindings: FxHashMap>, /// Binding for implicitly declared names that come with a module, /// like `self` (not yet used), or `crate`/`$crate` (for root modules). - module_self_bindings: FxHashMap, NameBinding<'a>>, + module_self_bindings: FxHashMap, NameBinding<'ra>>, used_extern_options: FxHashSet, macro_names: FxHashSet, builtin_macros: FxHashMap, registered_tools: &'tcx RegisteredTools, - macro_use_prelude: FxHashMap>, + macro_use_prelude: FxHashMap>, macro_map: FxHashMap, dummy_ext_bang: Lrc, dummy_ext_derive: Lrc, non_macro_attr: MacroData, - local_macro_def_scopes: FxHashMap>, - ast_transform_scopes: FxHashMap>, + local_macro_def_scopes: FxHashMap>, + ast_transform_scopes: FxHashMap>, unused_macros: FxHashMap, unused_macro_rules: FxHashMap<(LocalDefId, usize), (Ident, Span)>, proc_macro_stubs: FxHashSet, /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: - Vec<(Ident, MacroKind, ParentScope<'a>, Option>)>, + Vec<(Ident, MacroKind, ParentScope<'ra>, Option>)>, multi_segment_macro_resolutions: - Vec<(Vec, Span, MacroKind, ParentScope<'a>, Option, Namespace)>, - builtin_attrs: Vec<(Ident, ParentScope<'a>)>, + Vec<(Vec, Span, MacroKind, ParentScope<'ra>, Option, Namespace)>, + builtin_attrs: Vec<(Ident, ParentScope<'ra>)>, /// `derive(Copy)` marks items they are applied to so they are treated specially later. /// Derive macros cannot modify the item themselves and have to store the markers in the global /// context, so they attach the markers to derive container IDs using this resolver table. containers_deriving_copy: FxHashSet, /// Parent scopes in which the macros were invoked. /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere. - invocation_parent_scopes: FxHashMap>, + invocation_parent_scopes: FxHashMap>, /// `macro_rules` scopes *produced* by expanding the macro invocations, /// include all the `macro_rules` items and other invocations generated by them. - output_macro_rules_scopes: FxHashMap>, + output_macro_rules_scopes: FxHashMap>, /// `macro_rules` scopes produced by `macro_rules` item definitions. - macro_rules_scopes: FxHashMap>, + macro_rules_scopes: FxHashMap>, /// Helper attributes that are in scope for the given expansion. - helper_attrs: FxHashMap)>>, + helper_attrs: FxHashMap)>>, /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute /// with the given `ExpnId`. derive_data: FxHashMap, @@ -1123,9 +1123,9 @@ pub struct Resolver<'a, 'tcx> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, - potentially_unused_imports: Vec>, + potentially_unused_imports: Vec>, - potentially_unnecessary_qualifications: Vec>, + potentially_unnecessary_qualifications: Vec>, /// Table for mapping struct IDs into struct constructor IDs, /// it's not used during normal resolution, only for better error reporting. @@ -1186,28 +1186,29 @@ pub struct Resolver<'a, 'tcx> { current_crate_outer_attr_insert_span: Span, } -/// Nothing really interesting here; it just provides memory for the rest of the crate. +/// This provides memory for the rest of the crate. The `'ra` lifetime that is +/// used by many types in this crate is an abbreviation of `ResolverArenas`. #[derive(Default)] -pub struct ResolverArenas<'a> { - modules: TypedArena>, - local_modules: RefCell>>, - imports: TypedArena>, - name_resolutions: TypedArena>>, +pub struct ResolverArenas<'ra> { + modules: TypedArena>, + local_modules: RefCell>>, + imports: TypedArena>, + name_resolutions: TypedArena>>, ast_paths: TypedArena, dropless: DroplessArena, } -impl<'a> ResolverArenas<'a> { +impl<'ra> ResolverArenas<'ra> { fn new_module( - &'a self, - parent: Option>, + &'ra self, + parent: Option>, kind: ModuleKind, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - module_map: &mut FxHashMap>, - module_self_bindings: &mut FxHashMap, NameBinding<'a>>, - ) -> Module<'a> { + module_map: &mut FxHashMap>, + module_self_bindings: &mut FxHashMap, NameBinding<'ra>>, + ) -> Module<'ra> { let module = Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new( parent, kind, @@ -1227,37 +1228,37 @@ impl<'a> ResolverArenas<'a> { } module } - fn local_modules(&'a self) -> std::cell::Ref<'a, Vec>> { + fn local_modules(&'ra self) -> std::cell::Ref<'ra, Vec>> { self.local_modules.borrow() } - fn alloc_name_binding(&'a self, name_binding: NameBindingData<'a>) -> NameBinding<'a> { + fn alloc_name_binding(&'ra self, name_binding: NameBindingData<'ra>) -> NameBinding<'ra> { Interned::new_unchecked(self.dropless.alloc(name_binding)) } - fn alloc_import(&'a self, import: ImportData<'a>) -> Import<'a> { + fn alloc_import(&'ra self, import: ImportData<'ra>) -> Import<'ra> { Interned::new_unchecked(self.imports.alloc(import)) } - fn alloc_name_resolution(&'a self) -> &'a RefCell> { + fn alloc_name_resolution(&'ra self) -> &'ra RefCell> { self.name_resolutions.alloc(Default::default()) } - fn alloc_macro_rules_scope(&'a self, scope: MacroRulesScope<'a>) -> MacroRulesScopeRef<'a> { + fn alloc_macro_rules_scope(&'ra self, scope: MacroRulesScope<'ra>) -> MacroRulesScopeRef<'ra> { Interned::new_unchecked(self.dropless.alloc(Cell::new(scope))) } fn alloc_macro_rules_binding( - &'a self, - binding: MacroRulesBinding<'a>, - ) -> &'a MacroRulesBinding<'a> { + &'ra self, + binding: MacroRulesBinding<'ra>, + ) -> &'ra MacroRulesBinding<'ra> { self.dropless.alloc(binding) } - fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] { + fn alloc_ast_paths(&'ra self, paths: &[ast::Path]) -> &'ra [ast::Path] { self.ast_paths.alloc_from_iter(paths.iter().cloned()) } - fn alloc_pattern_spans(&'a self, spans: impl Iterator) -> &'a [Span] { + fn alloc_pattern_spans(&'ra self, spans: impl Iterator) -> &'ra [Span] { self.dropless.alloc_from_iter(spans) } } -impl<'a, 'tcx> AsMut> for Resolver<'a, 'tcx> { - fn as_mut(&mut self) -> &mut Resolver<'a, 'tcx> { +impl<'ra, 'tcx> AsMut> for Resolver<'ra, 'tcx> { + fn as_mut(&mut self) -> &mut Resolver<'ra, 'tcx> { self } } @@ -1341,14 +1342,14 @@ impl<'tcx> Resolver<'_, 'tcx> { } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub fn new( tcx: TyCtxt<'tcx>, attrs: &[ast::Attribute], crate_span: Span, current_crate_outer_attr_insert_span: Span, - arenas: &'a ResolverArenas<'a>, - ) -> Resolver<'a, 'tcx> { + arenas: &'ra ResolverArenas<'ra>, + ) -> Resolver<'ra, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); let mut module_map = FxHashMap::default(); let mut module_self_bindings = FxHashMap::default(); @@ -1541,12 +1542,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn new_module( &mut self, - parent: Option>, + parent: Option>, kind: ModuleKind, expn_id: ExpnId, span: Span, no_implicit_prelude: bool, - ) -> Module<'a> { + ) -> Module<'ra> { let module_map = &mut self.module_map; let module_self_bindings = &mut self.module_self_bindings; self.arenas.new_module( @@ -1578,7 +1579,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self.lint_buffer } - pub fn arenas() -> ResolverArenas<'a> { + pub fn arenas() -> ResolverArenas<'ra> { Default::default() } @@ -1719,8 +1720,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn traits_in_scope( &mut self, - current_trait: Option>, - parent_scope: &ParentScope<'a>, + current_trait: Option>, + parent_scope: &ParentScope<'ra>, ctxt: SyntaxContext, assoc_item: Option<(Symbol, Namespace)>, ) -> Vec { @@ -1754,7 +1755,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn traits_in_module( &mut self, - module: Module<'a>, + module: Module<'ra>, assoc_item: Option<(Symbol, Namespace)>, found_traits: &mut Vec, ) { @@ -1776,7 +1777,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // associated items. fn trait_may_have_item( &mut self, - trait_module: Option>, + trait_module: Option>, assoc_item: Option<(Symbol, Namespace)>, ) -> bool { match (trait_module, assoc_item) { @@ -1822,7 +1823,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { BindingKey { ident, ns, disambiguator } } - fn resolutions(&mut self, module: Module<'a>) -> &'a Resolutions<'a> { + fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> { if module.populate_on_access.get() { module.populate_on_access.set(false); self.build_reduced_graph_external(module); @@ -1832,9 +1833,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolution( &mut self, - module: Module<'a>, + module: Module<'ra>, key: BindingKey, - ) -> &'a RefCell> { + ) -> &'ra RefCell> { *self .resolutions(module) .borrow_mut() @@ -1860,14 +1861,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { false } - fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'a>, used: Used) { + fn record_use(&mut self, ident: Ident, used_binding: NameBinding<'ra>, used: Used) { self.record_use_inner(ident, used_binding, used, used_binding.warn_ambiguity); } fn record_use_inner( &mut self, ident: Ident, - used_binding: NameBinding<'a>, + used_binding: NameBinding<'ra>, used: Used, warn_ambiguity: bool, ) { @@ -1929,7 +1930,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_crate_root(&mut self, ident: Ident) -> Module<'a> { + fn resolve_crate_root(&mut self, ident: Ident) -> Module<'ra> { debug!("resolve_crate_root({:?})", ident); let mut ctxt = ident.span.ctxt(); let mark = if ident.name == kw::DollarCrate { @@ -2002,7 +2003,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { module } - fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> { + fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'ra>) -> Module<'ra> { let mut module = self.expect_module(module.nearest_parent_mod()); while module.span.ctxt().normalize_to_macros_2_0() != *ctxt { let parent = module.parent.unwrap_or_else(|| self.expn_def_scope(ctxt.remove_mark())); @@ -2026,12 +2027,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn is_accessible_from( &self, vis: ty::Visibility>, - module: Module<'a>, + module: Module<'ra>, ) -> bool { vis.is_accessible_from(module.nearest_parent_mod(), self.tcx) } - fn set_binding_parent_module(&mut self, binding: NameBinding<'a>, module: Module<'a>) { + fn set_binding_parent_module(&mut self, binding: NameBinding<'ra>, module: Module<'ra>) { if let Some(old_module) = self.binding_parent_modules.insert(binding, module) { if module != old_module { span_bug!(binding.span, "parent module is reset for binding"); @@ -2041,8 +2042,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn disambiguate_macro_rules_vs_modularized( &self, - macro_rules: NameBinding<'a>, - modularized: NameBinding<'a>, + macro_rules: NameBinding<'ra>, + modularized: NameBinding<'ra>, ) -> bool { // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules" // is disambiguated to mitigate regressions from macro modularization. @@ -2059,7 +2060,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option> { + fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option> { if ident.is_path_segment_keyword() { // Make sure `self`, `super` etc produce an error when passed to here. return None; @@ -2108,7 +2109,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path_str: &str, ns: Namespace, - parent_scope: ParentScope<'a>, + parent_scope: ParentScope<'ra>, ) -> Option { let mut segments = Vec::from_iter(path_str.split("::").map(Ident::from_str).map(Segment::from_ident)); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 7203fbe4a0c..8a81f068a1c 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -52,10 +52,10 @@ type Res = def::Res; /// Binding produced by a `macro_rules` item. /// Not modularized, can shadow previous `macro_rules` bindings, etc. #[derive(Debug)] -pub(crate) struct MacroRulesBinding<'a> { - pub(crate) binding: NameBinding<'a>, +pub(crate) struct MacroRulesBinding<'ra> { + pub(crate) binding: NameBinding<'ra>, /// `macro_rules` scope into which the `macro_rules` item was planted. - pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'a>, + pub(crate) parent_macro_rules_scope: MacroRulesScopeRef<'ra>, pub(crate) ident: Ident, } @@ -65,11 +65,11 @@ pub(crate) struct MacroRulesBinding<'a> { /// Some macro invocations need to introduce `macro_rules` scopes too because they /// can potentially expand into macro definitions. #[derive(Copy, Clone, Debug)] -pub(crate) enum MacroRulesScope<'a> { +pub(crate) enum MacroRulesScope<'ra> { /// Empty "root" scope at the crate start containing no names. Empty, /// The scope introduced by a `macro_rules!` macro definition. - Binding(&'a MacroRulesBinding<'a>), + Binding(&'ra MacroRulesBinding<'ra>), /// The scope introduced by a macro invocation that can potentially /// create a `macro_rules!` macro definition. Invocation(LocalExpnId), @@ -81,7 +81,7 @@ pub(crate) enum MacroRulesScope<'a> { /// This helps to avoid uncontrollable growth of `macro_rules!` scope chains, /// which usually grow linearly with the number of macro invocations /// in a module (including derives) and hurt performance. -pub(crate) type MacroRulesScopeRef<'a> = Interned<'a, Cell>>; +pub(crate) type MacroRulesScopeRef<'ra> = Interned<'ra, Cell>>; /// Macro namespace is separated into two sub-namespaces, one for bang macros and /// one for attribute-like macros (attributes, derives). @@ -177,7 +177,7 @@ fn soft_custom_inner_attributes_gate(path: &ast::Path, invoc: &Invocation) -> bo false } -impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { +impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { fn next_node_id(&mut self) -> NodeId { self.next_node_id() } @@ -528,7 +528,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// Resolve macro path with error reporting and recovery. /// Uses dummy syntax extensions for unresolved macros or macros with unexpected resolutions /// for better error recovery. @@ -538,7 +538,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { kind: MacroKind, supports_macro_expansion: SupportsMacroExpansion, inner_attr: bool, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, node_id: NodeId, force: bool, soft_custom_inner_attributes_gate: bool, @@ -704,10 +704,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, path: &ast::Path, kind: Option, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, trace: bool, force: bool, - ignore_import: Option>, + ignore_import: Option>, ) -> Result<(Option>, Res), Determinacy> { self.resolve_macro_or_delegation_path( path, @@ -725,12 +725,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { &mut self, ast_path: &ast::Path, kind: Option, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, trace: bool, force: bool, deleg_impl: Option, invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, - ignore_import: Option>, + ignore_import: Option>, ) -> Result<(Option>, Res), Determinacy> { let path_span = ast_path.span; let mut path = Segment::from_path(ast_path); @@ -1045,7 +1045,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn prohibit_imported_non_macro_attrs( &self, - binding: Option>, + binding: Option>, res: Option, span: Span, ) { @@ -1065,9 +1065,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn report_out_of_scope_macro_calls( &mut self, path: &ast::Path, - parent_scope: &ParentScope<'a>, + parent_scope: &ParentScope<'ra>, invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, - binding: Option>, + binding: Option>, ) { if let Some((mod_def_id, node_id)) = invoc_in_mod_inert_attr && let Some(binding) = binding From a7a35956687b726f86aa158cb65448fcfd1d6e93 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 11 Sep 2024 17:16:14 +1000 Subject: [PATCH 5/8] coverage: Separate creation of edge counters from building their sum --- .../src/coverage/counters.rs | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index 1c240366afa..fea61513800 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -315,20 +315,20 @@ impl<'a> MakeBcbCounters<'a> { // For each out-edge other than the one that was chosen to get an expression, // ensure that it has a counter (existing counter/expression or a new counter), // and accumulate the corresponding counters into a single sum expression. - let sum_of_all_other_out_edges: BcbCounter = { - let _span = debug_span!("sum_of_all_other_out_edges", ?expression_to_bcb).entered(); - successors - .iter() - .copied() - // Skip the chosen edge, since we'll calculate its count from this sum. - .filter(|&to_bcb| to_bcb != expression_to_bcb) - .fold(None, |accum, to_bcb| { - let _span = debug_span!("to_bcb", ?accum, ?to_bcb).entered(); - let edge_counter = self.get_or_make_edge_counter(from_bcb, to_bcb); - Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) - }) - .expect("there must be at least one other out-edge") - }; + let other_out_edge_counters = successors + .iter() + .copied() + // Skip the chosen edge, since we'll calculate its count from this sum. + .filter(|&to_bcb| to_bcb != expression_to_bcb) + .map(|to_bcb| self.get_or_make_edge_counter(from_bcb, to_bcb)) + .collect::>(); + let sum_of_all_other_out_edges: BcbCounter = other_out_edge_counters + .iter() + .copied() + .fold(None, |accum, edge_counter| { + Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) + }) + .expect("there must be at least one other out-edge"); // Now create an expression for the chosen edge, by taking the counter // for its source node and subtracting the sum of its sibling out-edges. @@ -375,20 +375,18 @@ impl<'a> MakeBcbCounters<'a> { // A BCB with multiple incoming edges can compute its count by ensuring that counters // exist for each of those edges, and then adding them up to get a total count. - let sum_of_in_edges: BcbCounter = { - let _span = debug_span!("sum_of_in_edges", ?bcb).entered(); - // We avoid calling `self.bcb_predecessors` here so that we can - // call methods on `&mut self` inside the fold. - self.basic_coverage_blocks.predecessors[bcb] - .iter() - .copied() - .fold(None, |accum, from_bcb| { - let _span = debug_span!("from_bcb", ?accum, ?from_bcb).entered(); - let edge_counter = self.get_or_make_edge_counter(from_bcb, bcb); - Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) - }) - .expect("there must be at least one in-edge") - }; + let in_edge_counters = self.basic_coverage_blocks.predecessors[bcb] + .iter() + .copied() + .map(|from_bcb| self.get_or_make_edge_counter(from_bcb, bcb)) + .collect::>(); + let sum_of_in_edges: BcbCounter = in_edge_counters + .iter() + .copied() + .fold(None, |accum, edge_counter| { + Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) + }) + .expect("there must be at least one in-edge"); debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}"); self.coverage_counters.set_bcb_counter(bcb, sum_of_in_edges) From 2344133ba6abfe54e48cafecca2dff53a9484b07 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 11 Sep 2024 17:24:31 +1000 Subject: [PATCH 6/8] coverage: Simplify creation of sum counters --- .../src/coverage/counters.rs | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs index fea61513800..7e3ecad1bce 100644 --- a/compiler/rustc_mir_transform/src/coverage/counters.rs +++ b/compiler/rustc_mir_transform/src/coverage/counters.rs @@ -155,12 +155,14 @@ impl CoverageCounters { BcbCounter::Expression { id } } - /// Variant of `make_expression` that makes `lhs` optional and assumes [`Op::Add`]. + /// Creates a counter that is the sum of the given counters. /// - /// This is useful when using [`Iterator::fold`] to build an arbitrary-length sum. - fn make_sum_expression(&mut self, lhs: Option, rhs: BcbCounter) -> BcbCounter { - let Some(lhs) = lhs else { return rhs }; - self.make_expression(lhs, Op::Add, rhs) + /// Returns `None` if the given list of counters was empty. + fn make_sum(&mut self, counters: &[BcbCounter]) -> Option { + counters + .iter() + .copied() + .reduce(|accum, counter| self.make_expression(accum, Op::Add, counter)) } pub(super) fn num_counters(&self) -> usize { @@ -322,12 +324,9 @@ impl<'a> MakeBcbCounters<'a> { .filter(|&to_bcb| to_bcb != expression_to_bcb) .map(|to_bcb| self.get_or_make_edge_counter(from_bcb, to_bcb)) .collect::>(); - let sum_of_all_other_out_edges: BcbCounter = other_out_edge_counters - .iter() - .copied() - .fold(None, |accum, edge_counter| { - Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) - }) + let sum_of_all_other_out_edges: BcbCounter = self + .coverage_counters + .make_sum(&other_out_edge_counters) .expect("there must be at least one other out-edge"); // Now create an expression for the chosen edge, by taking the counter @@ -380,12 +379,9 @@ impl<'a> MakeBcbCounters<'a> { .copied() .map(|from_bcb| self.get_or_make_edge_counter(from_bcb, bcb)) .collect::>(); - let sum_of_in_edges: BcbCounter = in_edge_counters - .iter() - .copied() - .fold(None, |accum, edge_counter| { - Some(self.coverage_counters.make_sum_expression(accum, edge_counter)) - }) + let sum_of_in_edges: BcbCounter = self + .coverage_counters + .make_sum(&in_edge_counters) .expect("there must be at least one in-edge"); debug!("{bcb:?} gets a new counter (sum of predecessor counters): {sum_of_in_edges:?}"); From 675c99f4d54693af8c7af162968838d6e75ffbee Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 12 Sep 2024 14:32:44 +0200 Subject: [PATCH 7/8] more eagerly discard constraints on overflow --- .../src/solve/eval_ctxt/canonical.rs | 15 +++++++++ .../src/solve/eval_ctxt/mod.rs | 33 ++++--------------- .../src/solve/fulfill.rs | 2 +- compiler/rustc_type_ir/src/solve/mod.rs | 10 ++---- .../issue-118950-root-region.stderr | 2 ++ 5 files changed, 27 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs index 1c00f5f8b41..5acfec3dee3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs @@ -122,6 +122,21 @@ where (certainty, NestedNormalizationGoals::empty()) }; + if let Certainty::Maybe(cause @ MaybeCause::Overflow { .. }) = certainty { + // If we have overflow, it's probable that we're substituting a type + // into itself infinitely and any partial substitutions in the query + // response are probably not useful anyways, so just return an empty + // query response. + // + // This may prevent us from potentially useful inference, e.g. + // 2 candidates, one ambiguous and one overflow, which both + // have the same inference constraints. + // + // Changing this to retain some constraints in the future + // won't be a breaking change, so this is good enough for now. + return Ok(self.make_ambiguous_response_no_constraints(cause)); + } + let external_constraints = self.compute_external_query_constraints(certainty, normalization_nested_goals); let (var_values, mut external_constraints) = (self.var_values, external_constraints) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 3f2f34d3255..15b123ebdf9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -17,7 +17,7 @@ use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ - CanonicalInput, CanonicalResponse, Certainty, Goal, GoalEvaluationKind, GoalSource, MaybeCause, + CanonicalInput, CanonicalResponse, Certainty, Goal, GoalEvaluationKind, GoalSource, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, SolverMode, FIXPOINT_STEP_LIMIT, }; @@ -370,7 +370,7 @@ where canonical_goal, &mut goal_evaluation, ); - let canonical_response = match canonical_response { + let response = match canonical_response { Err(e) => { self.inspect.goal_evaluation(goal_evaluation); return Err(e); @@ -378,12 +378,11 @@ where Ok(response) => response, }; - let (normalization_nested_goals, certainty, has_changed) = self - .instantiate_response_discarding_overflow( - goal.param_env, - orig_values, - canonical_response, - ); + let has_changed = !response.value.var_values.is_identity_modulo_regions() + || !response.value.external_constraints.opaque_types.is_empty(); + + let (normalization_nested_goals, certainty) = + self.instantiate_and_apply_query_response(goal.param_env, orig_values, response); self.inspect.goal_evaluation(goal_evaluation); // FIXME: We previously had an assert here that checked that recomputing // a goal after applying its constraints did not change its response. @@ -398,24 +397,6 @@ where Ok((normalization_nested_goals, has_changed, certainty)) } - fn instantiate_response_discarding_overflow( - &mut self, - param_env: I::ParamEnv, - original_values: Vec, - response: CanonicalResponse, - ) -> (NestedNormalizationGoals, Certainty, bool) { - if let Certainty::Maybe(MaybeCause::Overflow { .. }) = response.value.certainty { - return (NestedNormalizationGoals::empty(), response.value.certainty, false); - } - - let has_changed = !response.value.var_values.is_identity_modulo_regions() - || !response.value.external_constraints.opaque_types.is_empty(); - - let (normalization_nested_goals, certainty) = - self.instantiate_and_apply_query_response(param_env, original_values, response); - (normalization_nested_goals, certainty, has_changed) - } - fn compute_goal(&mut self, goal: Goal) -> QueryResult { let Goal { param_env, predicate } = goal; let kind = predicate.kind(); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index f5f36f40f7e..cfc73e2e47e 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -302,7 +302,7 @@ fn fulfillment_error_for_stalled<'tcx>( Ok((_, Certainty::Maybe(MaybeCause::Overflow { suggest_increasing_limit }))) => ( FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, // Don't look into overflows because we treat overflows weirdly anyways. - // In `instantiate_response_discarding_overflow` we set `has_changed = false`, + // We discard the inference constraints from overflowing goals, so // recomputing the goal again during `find_best_leaf_obligation` may apply // inference guidance that makes other goals go from ambig -> pass, for example. // diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 96998d2ec9f..a0f7658212f 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -117,7 +117,8 @@ impl Goal { /// Why a specific goal has to be proven. /// /// This is necessary as we treat nested goals different depending on -/// their source. +/// their source. This is currently mostly used by proof tree visitors +/// but will be used by cycle handling in the future. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] pub enum GoalSource { @@ -126,13 +127,6 @@ pub enum GoalSource { /// /// FIXME(-Znext-solver=coinductive): Explain how and why this /// changes whether cycles are coinductive. - /// - /// This also impacts whether we erase constraints on overflow. - /// Erasing constraints is generally very useful for perf and also - /// results in better error messages by avoiding spurious errors. - /// We do not erase overflow constraints in `normalizes-to` goals unless - /// they are from an impl where-clause. This is necessary due to - /// backwards compatibility, cc trait-system-refactor-initiatitive#70. ImplWhereBound, /// Instantiating a higher-ranked goal and re-proving it. InstantiateHigherRanked, diff --git a/tests/ui/traits/next-solver/issue-118950-root-region.stderr b/tests/ui/traits/next-solver/issue-118950-root-region.stderr index d14b9d217da..7c3e22fb401 100644 --- a/tests/ui/traits/next-solver/issue-118950-root-region.stderr +++ b/tests/ui/traits/next-solver/issue-118950-root-region.stderr @@ -37,6 +37,8 @@ LL | impl Overlap for T {} LL | LL | impl Overlap fn(Assoc<'a, T>)> for T where Missing: Overlap {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `fn(_)` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details error: aborting due to 3 previous errors; 1 warning emitted From d3ebd232a5f6765373b8b7ef23ed5b87477fbd1e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 12 Sep 2024 09:55:25 -0400 Subject: [PATCH 8/8] Add test for nalgebra hang in coherence --- tests/ui/traits/coherence-alias-hang.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/ui/traits/coherence-alias-hang.rs diff --git a/tests/ui/traits/coherence-alias-hang.rs b/tests/ui/traits/coherence-alias-hang.rs new file mode 100644 index 00000000000..37b80739589 --- /dev/null +++ b/tests/ui/traits/coherence-alias-hang.rs @@ -0,0 +1,23 @@ +//@ check-pass + +// Regression test for nalgebra hang . + +#![feature(lazy_type_alias)] +#![allow(incomplete_features)] + +type Id = T; +trait NotImplemented {} + +struct W(*const T, *const U); +trait Trait { + type Assoc: ?Sized; +} +impl Trait for W { + type Assoc = W>; +} + +trait Overlap {} +impl Overlap for W {} +impl Overlap for T {} + +fn main() {}