| author | bors <bors@rust-lang.org> 2025-11-06 14:52:37 UTC |
| committer | bors <bors@rust-lang.org> 2025-11-06 14:52:37 UTC |
| log | c90bcb9571b7aab0d8beaa2ce8a998ffaf079d38 |
| tree | 4b90398129b903354bada8c8150fbc41c7442281 |
| parent | c5e283b0d209ee6f7cd1a8cbc1974927c547f3e6 |
| parent | 1a6770c5c4183ce730200fab910000c193fb8f15 |
Rollup of 7 pull requests
Successful merges:
- rust-lang/rust#146861 (add extend_front to VecDeque with specialization like extend)
- rust-lang/rust#148213 (Fix invalid tag closing when leaving expansion "original code")
- rust-lang/rust#148292 (Un-shadow object bound candidate in `NormalizesTo` goal if self_ty is trait object)
- rust-lang/rust#148528 (run-make tests: use edition 2024)
- rust-lang/rust#148554 (Add regression test for issue 148542)
- rust-lang/rust#148561 (Fix ICE from async closure variance)
- rust-lang/rust#148563 (rustdoc-search: remove broken index special case)
r? `@ghost`
`@rustbot` modify labels: rollup26 files changed, 557 insertions(+), 34 deletions(-)
compiler/rustc_middle/src/ty/diagnostics.rs+1| ... | @@ -698,6 +698,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { | ... | @@ -698,6 +698,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { |
| 698 | } | 698 | } |
| 699 | 699 | ||
| 700 | Closure(..) | 700 | Closure(..) |
| 701 | | CoroutineClosure(..) | ||
| 701 | | FnDef(..) | 702 | | FnDef(..) |
| 702 | | Infer(..) | 703 | | Infer(..) |
| 703 | | Coroutine(..) | 704 | | Coroutine(..) |
compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs+10-1| ... | @@ -454,7 +454,16 @@ where | ... | @@ -454,7 +454,16 @@ where |
| 454 | self.assemble_object_bound_candidates(goal, &mut candidates); | 454 | self.assemble_object_bound_candidates(goal, &mut candidates); |
| 455 | } | 455 | } |
| 456 | } | 456 | } |
| 457 | AssembleCandidatesFrom::EnvAndBounds => {} | 457 | AssembleCandidatesFrom::EnvAndBounds => { |
| 458 | // This is somewhat inconsistent and may make #57893 slightly easier to exploit. | ||
| 459 | // However, it matches the behavior of the old solver. See | ||
| 460 | // `tests/ui/traits/next-solver/normalization-shadowing/use_object_if_empty_env.rs`. | ||
| 461 | if matches!(normalized_self_ty.kind(), ty::Dynamic(..)) | ||
| 462 | && !candidates.iter().any(|c| matches!(c.source, CandidateSource::ParamEnv(_))) | ||
| 463 | { | ||
| 464 | self.assemble_object_bound_candidates(goal, &mut candidates); | ||
| 465 | } | ||
| 466 | } | ||
| 458 | } | 467 | } |
| 459 | 468 | ||
| 460 | (candidates, failed_candidate_info) | 469 | (candidates, failed_candidate_info) |
library/alloc/src/collections/vec_deque/mod.rs+112-1| ... | @@ -52,7 +52,7 @@ pub use self::iter::Iter; | ... | @@ -52,7 +52,7 @@ pub use self::iter::Iter; |
| 52 | 52 | ||
| 53 | mod iter; | 53 | mod iter; |
| 54 | 54 | ||
| 55 | use self::spec_extend::SpecExtend; | 55 | use self::spec_extend::{SpecExtend, SpecExtendFront}; |
| 56 | 56 | ||
| 57 | mod spec_extend; | 57 | mod spec_extend; |
| 58 | 58 | ||
| ... | @@ -179,6 +179,21 @@ impl<T, A: Allocator> VecDeque<T, A> { | ... | @@ -179,6 +179,21 @@ impl<T, A: Allocator> VecDeque<T, A> { |
| 179 | self.len += 1; | 179 | self.len += 1; |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | /// Prepends an element to the buffer. | ||
| 183 | /// | ||
| 184 | /// # Safety | ||
| 185 | /// | ||
| 186 | /// May only be called if `deque.len() < deque.capacity()` | ||
| 187 | #[inline] | ||
| 188 | unsafe fn push_front_unchecked(&mut self, element: T) { | ||
| 189 | self.head = self.wrap_sub(self.head, 1); | ||
| 190 | // SAFETY: Because of the precondition, it's guaranteed that there is space | ||
| 191 | // in the logical array before the first element (where self.head is now). | ||
| 192 | unsafe { self.buffer_write(self.head, element) }; | ||
| 193 | // This can't overflow because `deque.len() < deque.capacity() <= usize::MAX`. | ||
| 194 | self.len += 1; | ||
| 195 | } | ||
| 196 | |||
| 182 | /// Moves an element out of the buffer | 197 | /// Moves an element out of the buffer |
| 183 | #[inline] | 198 | #[inline] |
| 184 | unsafe fn buffer_read(&mut self, off: usize) -> T { | 199 | unsafe fn buffer_read(&mut self, off: usize) -> T { |
| ... | @@ -505,6 +520,35 @@ impl<T, A: Allocator> VecDeque<T, A> { | ... | @@ -505,6 +520,35 @@ impl<T, A: Allocator> VecDeque<T, A> { |
| 505 | } | 520 | } |
| 506 | } | 521 | } |
| 507 | 522 | ||
| 523 | /// Copies all values from `src` to `dst` in reversed order, wrapping around if needed. | ||
| 524 | /// Assumes capacity is sufficient. | ||
| 525 | /// Equivalent to calling [`VecDeque::copy_slice`] with a [reversed](https://doc.rust-lang.org/std/primitive.slice.html#method.reverse) slice. | ||
| 526 | #[inline] | ||
| 527 | unsafe fn copy_slice_reversed(&mut self, dst: usize, src: &[T]) { | ||
| 528 | /// # Safety | ||
| 529 | /// | ||
| 530 | /// See [`ptr::copy_nonoverlapping`]. | ||
| 531 | unsafe fn copy_nonoverlapping_reversed<T>(src: *const T, dst: *mut T, count: usize) { | ||
| 532 | for i in 0..count { | ||
| 533 | unsafe { ptr::copy_nonoverlapping(src.add(count - 1 - i), dst.add(i), 1) }; | ||
| 534 | } | ||
| 535 | } | ||
| 536 | |||
| 537 | debug_assert!(src.len() <= self.capacity()); | ||
| 538 | let head_room = self.capacity() - dst; | ||
| 539 | if src.len() <= head_room { | ||
| 540 | unsafe { | ||
| 541 | copy_nonoverlapping_reversed(src.as_ptr(), self.ptr().add(dst), src.len()); | ||
| 542 | } | ||
| 543 | } else { | ||
| 544 | let (left, right) = src.split_at(src.len() - head_room); | ||
| 545 | unsafe { | ||
| 546 | copy_nonoverlapping_reversed(right.as_ptr(), self.ptr().add(dst), right.len()); | ||
| 547 | copy_nonoverlapping_reversed(left.as_ptr(), self.ptr(), left.len()); | ||
| 548 | } | ||
| 549 | } | ||
| 550 | } | ||
| 551 | |||
| 508 | /// Writes all values from `iter` to `dst`. | 552 | /// Writes all values from `iter` to `dst`. |
| 509 | /// | 553 | /// |
| 510 | /// # Safety | 554 | /// # Safety |
| ... | @@ -2122,6 +2166,73 @@ impl<T, A: Allocator> VecDeque<T, A> { | ... | @@ -2122,6 +2166,73 @@ impl<T, A: Allocator> VecDeque<T, A> { |
| 2122 | unsafe { self.buffer_write(self.to_physical_idx(len), value) } | 2166 | unsafe { self.buffer_write(self.to_physical_idx(len), value) } |
| 2123 | } | 2167 | } |
| 2124 | 2168 | ||
| 2169 | /// Prepends all contents of the iterator to the front of the deque. | ||
| 2170 | /// The order of the contents is preserved. | ||
| 2171 | /// | ||
| 2172 | /// To get behavior like [`append`][VecDeque::append] where elements are moved | ||
| 2173 | /// from the other collection to this one, use `self.prepend(other.drain(..))`. | ||
| 2174 | /// | ||
| 2175 | /// # Examples | ||
| 2176 | /// | ||
| 2177 | /// ``` | ||
| 2178 | /// #![feature(deque_extend_front)] | ||
| 2179 | /// use std::collections::VecDeque; | ||
| 2180 | /// | ||
| 2181 | /// let mut deque = VecDeque::from([4, 5, 6]); | ||
| 2182 | /// deque.prepend([1, 2, 3]); | ||
| 2183 | /// assert_eq!(deque, [1, 2, 3, 4, 5, 6]); | ||
| 2184 | /// ``` | ||
| 2185 | /// | ||
| 2186 | /// Move values between collections like [`append`][VecDeque::append] does but prepend to the front: | ||
| 2187 | /// | ||
| 2188 | /// ``` | ||
| 2189 | /// #![feature(deque_extend_front)] | ||
| 2190 | /// use std::collections::VecDeque; | ||
| 2191 | /// | ||
| 2192 | /// let mut deque1 = VecDeque::from([4, 5, 6]); | ||
| 2193 | /// let mut deque2 = VecDeque::from([1, 2, 3]); | ||
| 2194 | /// deque1.prepend(deque2.drain(..)); | ||
| 2195 | /// assert_eq!(deque1, [1, 2, 3, 4, 5, 6]); | ||
| 2196 | /// assert!(deque2.is_empty()); | ||
| 2197 | /// ``` | ||
| 2198 | #[unstable(feature = "deque_extend_front", issue = "146975")] | ||
| 2199 | #[track_caller] | ||
| 2200 | pub fn prepend<I: IntoIterator<Item = T, IntoIter: DoubleEndedIterator>>(&mut self, other: I) { | ||
| 2201 | self.extend_front(other.into_iter().rev()) | ||
| 2202 | } | ||
| 2203 | |||
| 2204 | /// Prepends all contents of the iterator to the front of the deque, | ||
| 2205 | /// as if [`push_front`][VecDeque::push_front] was called repeatedly with | ||
| 2206 | /// the values yielded by the iterator. | ||
| 2207 | /// | ||
| 2208 | /// # Examples | ||
| 2209 | /// | ||
| 2210 | /// ``` | ||
| 2211 | /// #![feature(deque_extend_front)] | ||
| 2212 | /// use std::collections::VecDeque; | ||
| 2213 | /// | ||
| 2214 | /// let mut deque = VecDeque::from([4, 5, 6]); | ||
| 2215 | /// deque.extend_front([3, 2, 1]); | ||
| 2216 | /// assert_eq!(deque, [1, 2, 3, 4, 5, 6]); | ||
| 2217 | /// ``` | ||
| 2218 | /// | ||
| 2219 | /// This behaves like [`push_front`][VecDeque::push_front] was called repeatedly: | ||
| 2220 | /// | ||
| 2221 | /// ``` | ||
| 2222 | /// use std::collections::VecDeque; | ||
| 2223 | /// | ||
| 2224 | /// let mut deque = VecDeque::from([4, 5, 6]); | ||
| 2225 | /// for v in [3, 2, 1] { | ||
| 2226 | /// deque.push_front(v); | ||
| 2227 | /// } | ||
| 2228 | /// assert_eq!(deque, [1, 2, 3, 4, 5, 6]); | ||
| 2229 | /// ``` | ||
| 2230 | #[unstable(feature = "deque_extend_front", issue = "146975")] | ||
| 2231 | #[track_caller] | ||
| 2232 | pub fn extend_front<I: IntoIterator<Item = T>>(&mut self, iter: I) { | ||
| 2233 | <Self as SpecExtendFront<T, I::IntoIter>>::spec_extend_front(self, iter.into_iter()); | ||
| 2234 | } | ||
| 2235 | |||
| 2125 | #[inline] | 2236 | #[inline] |
| 2126 | fn is_contiguous(&self) -> bool { | 2237 | fn is_contiguous(&self) -> bool { |
| 2127 | // Do the calculation like this to avoid overflowing if len + head > usize::MAX | 2238 | // Do the calculation like this to avoid overflowing if len + head > usize::MAX |
library/alloc/src/collections/vec_deque/spec_extend.rs+111-1| ... | @@ -1,4 +1,4 @@ | ... | @@ -1,4 +1,4 @@ |
| 1 | use core::iter::TrustedLen; | 1 | use core::iter::{Copied, Rev, TrustedLen}; |
| 2 | use core::slice; | 2 | use core::slice; |
| 3 | 3 | ||
| 4 | use super::VecDeque; | 4 | use super::VecDeque; |
| ... | @@ -114,3 +114,113 @@ where | ... | @@ -114,3 +114,113 @@ where |
| 114 | } | 114 | } |
| 115 | } | 115 | } |
| 116 | } | 116 | } |
| 117 | |||
| 118 | // Specialization trait used for VecDeque::extend_front | ||
| 119 | pub(super) trait SpecExtendFront<T, I> { | ||
| 120 | #[track_caller] | ||
| 121 | fn spec_extend_front(&mut self, iter: I); | ||
| 122 | } | ||
| 123 | |||
| 124 | impl<T, I, A: Allocator> SpecExtendFront<T, I> for VecDeque<T, A> | ||
| 125 | where | ||
| 126 | I: Iterator<Item = T>, | ||
| 127 | { | ||
| 128 | #[track_caller] | ||
| 129 | default fn spec_extend_front(&mut self, mut iter: I) { | ||
| 130 | // This function should be the moral equivalent of: | ||
| 131 | // | ||
| 132 | // for item in iter { | ||
| 133 | // self.push_front(item); | ||
| 134 | // } | ||
| 135 | |||
| 136 | while let Some(element) = iter.next() { | ||
| 137 | let (lower, _) = iter.size_hint(); | ||
| 138 | self.reserve(lower.saturating_add(1)); | ||
| 139 | |||
| 140 | // SAFETY: We just reserved space for at least one element. | ||
| 141 | unsafe { self.push_front_unchecked(element) }; | ||
| 142 | |||
| 143 | // Inner loop to avoid repeatedly calling `reserve`. | ||
| 144 | while self.len < self.capacity() { | ||
| 145 | let Some(element) = iter.next() else { | ||
| 146 | return; | ||
| 147 | }; | ||
| 148 | // SAFETY: The loop condition guarantees that `self.len() < self.capacity()`. | ||
| 149 | unsafe { self.push_front_unchecked(element) }; | ||
| 150 | } | ||
| 151 | } | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | #[cfg(not(test))] | ||
| 156 | impl<T, A: Allocator> SpecExtendFront<T, vec::IntoIter<T>> for VecDeque<T, A> { | ||
| 157 | #[track_caller] | ||
| 158 | fn spec_extend_front(&mut self, mut iterator: vec::IntoIter<T>) { | ||
| 159 | let slice = iterator.as_slice(); | ||
| 160 | // SAFETY: elements in the slice are forgotten after this call | ||
| 161 | unsafe { prepend_reversed(self, slice) }; | ||
| 162 | iterator.forget_remaining_elements(); | ||
| 163 | } | ||
| 164 | } | ||
| 165 | |||
| 166 | #[cfg(not(test))] | ||
| 167 | impl<T, A: Allocator> SpecExtendFront<T, Rev<vec::IntoIter<T>>> for VecDeque<T, A> { | ||
| 168 | #[track_caller] | ||
| 169 | fn spec_extend_front(&mut self, iterator: Rev<vec::IntoIter<T>>) { | ||
| 170 | let mut iterator = iterator.into_inner(); | ||
| 171 | let slice = iterator.as_slice(); | ||
| 172 | // SAFETY: elements in the slice are forgotten after this call | ||
| 173 | unsafe { prepend(self, slice) }; | ||
| 174 | iterator.forget_remaining_elements(); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | impl<'a, T, A: Allocator> SpecExtendFront<T, Copied<slice::Iter<'a, T>>> for VecDeque<T, A> | ||
| 179 | where | ||
| 180 | Copied<slice::Iter<'a, T>>: Iterator<Item = T>, | ||
| 181 | { | ||
| 182 | #[track_caller] | ||
| 183 | fn spec_extend_front(&mut self, iter: Copied<slice::Iter<'a, T>>) { | ||
| 184 | let slice = iter.into_inner().as_slice(); | ||
| 185 | // SAFETY: T is Copy because Copied<slice::Iter<'a, T>> is Iterator | ||
| 186 | unsafe { prepend_reversed(self, slice) }; | ||
| 187 | } | ||
| 188 | } | ||
| 189 | |||
| 190 | impl<'a, T, A: Allocator> SpecExtendFront<T, Rev<Copied<slice::Iter<'a, T>>>> for VecDeque<T, A> | ||
| 191 | where | ||
| 192 | Rev<Copied<slice::Iter<'a, T>>>: Iterator<Item = T>, | ||
| 193 | { | ||
| 194 | #[track_caller] | ||
| 195 | fn spec_extend_front(&mut self, iter: Rev<Copied<slice::Iter<'a, T>>>) { | ||
| 196 | let slice = iter.into_inner().into_inner().as_slice(); | ||
| 197 | // SAFETY: T is Copy because Rev<Copied<slice::Iter<'a, T>>> is Iterator | ||
| 198 | unsafe { prepend(self, slice) }; | ||
| 199 | } | ||
| 200 | } | ||
| 201 | |||
| 202 | /// # Safety | ||
| 203 | /// | ||
| 204 | /// Elements of `slice` will be copied into the deque, make sure to forget the items if `T` is not `Copy`. | ||
| 205 | unsafe fn prepend<T, A: Allocator>(deque: &mut VecDeque<T, A>, slice: &[T]) { | ||
| 206 | deque.reserve(slice.len()); | ||
| 207 | |||
| 208 | unsafe { | ||
| 209 | deque.head = deque.wrap_sub(deque.head, slice.len()); | ||
| 210 | deque.copy_slice(deque.head, slice); | ||
| 211 | deque.len += slice.len(); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | /// # Safety | ||
| 216 | /// | ||
| 217 | /// Elements of `slice` will be copied into the deque, make sure to forget the items if `T` is not `Copy`. | ||
| 218 | unsafe fn prepend_reversed<T, A: Allocator>(deque: &mut VecDeque<T, A>, slice: &[T]) { | ||
| 219 | deque.reserve(slice.len()); | ||
| 220 | |||
| 221 | unsafe { | ||
| 222 | deque.head = deque.wrap_sub(deque.head, slice.len()); | ||
| 223 | deque.copy_slice_reversed(deque.head, slice); | ||
| 224 | deque.len += slice.len(); | ||
| 225 | } | ||
| 226 | } |
library/alloc/src/lib.rs+2| ... | @@ -106,6 +106,7 @@ | ... | @@ -106,6 +106,7 @@ |
| 106 | #![feature(const_default)] | 106 | #![feature(const_default)] |
| 107 | #![feature(const_eval_select)] | 107 | #![feature(const_eval_select)] |
| 108 | #![feature(const_heap)] | 108 | #![feature(const_heap)] |
| 109 | #![feature(copied_into_inner)] | ||
| 109 | #![feature(core_intrinsics)] | 110 | #![feature(core_intrinsics)] |
| 110 | #![feature(deprecated_suggestion)] | 111 | #![feature(deprecated_suggestion)] |
| 111 | #![feature(deref_pure_trait)] | 112 | #![feature(deref_pure_trait)] |
| ... | @@ -134,6 +135,7 @@ | ... | @@ -134,6 +135,7 @@ |
| 134 | #![feature(ptr_alignment_type)] | 135 | #![feature(ptr_alignment_type)] |
| 135 | #![feature(ptr_internals)] | 136 | #![feature(ptr_internals)] |
| 136 | #![feature(ptr_metadata)] | 137 | #![feature(ptr_metadata)] |
| 138 | #![feature(rev_into_inner)] | ||
| 137 | #![feature(set_ptr_value)] | 139 | #![feature(set_ptr_value)] |
| 138 | #![feature(sized_type_properties)] | 140 | #![feature(sized_type_properties)] |
| 139 | #![feature(slice_from_ptr_range)] | 141 | #![feature(slice_from_ptr_range)] |
library/alloctests/lib.rs+2| ... | @@ -20,6 +20,7 @@ | ... | @@ -20,6 +20,7 @@ |
| 20 | #![feature(assert_matches)] | 20 | #![feature(assert_matches)] |
| 21 | #![feature(char_internals)] | 21 | #![feature(char_internals)] |
| 22 | #![feature(char_max_len)] | 22 | #![feature(char_max_len)] |
| 23 | #![feature(copied_into_inner)] | ||
| 23 | #![feature(core_intrinsics)] | 24 | #![feature(core_intrinsics)] |
| 24 | #![feature(exact_size_is_empty)] | 25 | #![feature(exact_size_is_empty)] |
| 25 | #![feature(extend_one)] | 26 | #![feature(extend_one)] |
| ... | @@ -32,6 +33,7 @@ | ... | @@ -32,6 +33,7 @@ |
| 32 | #![feature(maybe_uninit_uninit_array_transpose)] | 33 | #![feature(maybe_uninit_uninit_array_transpose)] |
| 33 | #![feature(ptr_alignment_type)] | 34 | #![feature(ptr_alignment_type)] |
| 34 | #![feature(ptr_internals)] | 35 | #![feature(ptr_internals)] |
| 36 | #![feature(rev_into_inner)] | ||
| 35 | #![feature(sized_type_properties)] | 37 | #![feature(sized_type_properties)] |
| 36 | #![feature(slice_iter_mut_as_mut_slice)] | 38 | #![feature(slice_iter_mut_as_mut_slice)] |
| 37 | #![feature(slice_ptr_get)] | 39 | #![feature(slice_ptr_get)] |
library/alloctests/tests/vec_deque.rs+74| ... | @@ -2081,3 +2081,77 @@ fn test_extend_and_prepend_from_within() { | ... | @@ -2081,3 +2081,77 @@ fn test_extend_and_prepend_from_within() { |
| 2081 | v.extend_from_within(..); | 2081 | v.extend_from_within(..); |
| 2082 | assert_eq!(v.iter().map(|s| &**s).collect::<String>(), "123123123123"); | 2082 | assert_eq!(v.iter().map(|s| &**s).collect::<String>(), "123123123123"); |
| 2083 | } | 2083 | } |
| 2084 | |||
| 2085 | #[test] | ||
| 2086 | fn test_extend_front() { | ||
| 2087 | let mut v = VecDeque::new(); | ||
| 2088 | v.extend_front(0..3); | ||
| 2089 | assert_eq!(v, [2, 1, 0]); | ||
| 2090 | v.extend_front(3..6); | ||
| 2091 | assert_eq!(v, [5, 4, 3, 2, 1, 0]); | ||
| 2092 | v.prepend([1; 4]); | ||
| 2093 | assert_eq!(v, [1, 1, 1, 1, 5, 4, 3, 2, 1, 0]); | ||
| 2094 | |||
| 2095 | let mut v = VecDeque::with_capacity(8); | ||
| 2096 | let cap = v.capacity(); | ||
| 2097 | v.extend(0..4); | ||
| 2098 | v.truncate_front(2); | ||
| 2099 | v.extend_front(4..8); | ||
| 2100 | assert_eq!(v.as_slices(), ([7, 6].as_slice(), [5, 4, 2, 3].as_slice())); | ||
| 2101 | assert_eq!(v.capacity(), cap); | ||
| 2102 | |||
| 2103 | let mut v = VecDeque::new(); | ||
| 2104 | v.extend_front([]); | ||
| 2105 | v.extend_front(None); | ||
| 2106 | v.extend_front(vec![]); | ||
| 2107 | v.prepend([]); | ||
| 2108 | v.prepend(None); | ||
| 2109 | v.prepend(vec![]); | ||
| 2110 | assert_eq!(v.capacity(), 0); | ||
| 2111 | v.extend_front(Some(123)); | ||
| 2112 | assert_eq!(v, [123]); | ||
| 2113 | } | ||
| 2114 | |||
| 2115 | #[test] | ||
| 2116 | fn test_extend_front_specialization_vec_into_iter() { | ||
| 2117 | // trigger 4 code paths: all combinations of prepend and extend_front, wrap and no wrap | ||
| 2118 | let mut v = VecDeque::with_capacity(4); | ||
| 2119 | v.prepend(vec![1, 2, 3]); | ||
| 2120 | assert_eq!(v, [1, 2, 3]); | ||
| 2121 | v.pop_back(); | ||
| 2122 | // this should wrap around the physical buffer | ||
| 2123 | v.prepend(vec![-1, 0]); | ||
| 2124 | // check it really wrapped | ||
| 2125 | assert_eq!(v.as_slices(), ([-1].as_slice(), [0, 1, 2].as_slice())); | ||
| 2126 | |||
| 2127 | let mut v = VecDeque::with_capacity(4); | ||
| 2128 | v.extend_front(vec![1, 2, 3]); | ||
| 2129 | assert_eq!(v, [3, 2, 1]); | ||
| 2130 | v.pop_back(); | ||
| 2131 | // this should wrap around the physical buffer | ||
| 2132 | v.extend_front(vec![4, 5]); | ||
| 2133 | // check it really wrapped | ||
| 2134 | assert_eq!(v.as_slices(), ([5].as_slice(), [4, 3, 2].as_slice())); | ||
| 2135 | } | ||
| 2136 | |||
| 2137 | #[test] | ||
| 2138 | fn test_extend_front_specialization_copy_slice() { | ||
| 2139 | // trigger 4 code paths: all combinations of prepend and extend_front, wrap and no wrap | ||
| 2140 | let mut v = VecDeque::with_capacity(4); | ||
| 2141 | v.prepend([1, 2, 3].as_slice().iter().copied()); | ||
| 2142 | assert_eq!(v, [1, 2, 3]); | ||
| 2143 | v.pop_back(); | ||
| 2144 | // this should wrap around the physical buffer | ||
| 2145 | v.prepend([-1, 0].as_slice().iter().copied()); | ||
| 2146 | // check it really wrapped | ||
| 2147 | assert_eq!(v.as_slices(), ([-1].as_slice(), [0, 1, 2].as_slice())); | ||
| 2148 | |||
| 2149 | let mut v = VecDeque::with_capacity(4); | ||
| 2150 | v.extend_front([1, 2, 3].as_slice().iter().copied()); | ||
| 2151 | assert_eq!(v, [3, 2, 1]); | ||
| 2152 | v.pop_back(); | ||
| 2153 | // this should wrap around the physical buffer | ||
| 2154 | v.extend_front([4, 5].as_slice().iter().copied()); | ||
| 2155 | // check it really wrapped | ||
| 2156 | assert_eq!(v.as_slices(), ([5].as_slice(), [4, 3, 2].as_slice())); | ||
| 2157 | } |
library/core/src/iter/adapters/copied.rs+6| ... | @@ -24,6 +24,12 @@ impl<I> Copied<I> { | ... | @@ -24,6 +24,12 @@ impl<I> Copied<I> { |
| 24 | pub(in crate::iter) fn new(it: I) -> Copied<I> { | 24 | pub(in crate::iter) fn new(it: I) -> Copied<I> { |
| 25 | Copied { it } | 25 | Copied { it } |
| 26 | } | 26 | } |
| 27 | |||
| 28 | #[doc(hidden)] | ||
| 29 | #[unstable(feature = "copied_into_inner", issue = "none")] | ||
| 30 | pub fn into_inner(self) -> I { | ||
| 31 | self.it | ||
| 32 | } | ||
| 27 | } | 33 | } |
| 28 | 34 | ||
| 29 | fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc { | 35 | fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc { |
src/librustdoc/html/highlight.rs+24-1| ... | @@ -427,6 +427,27 @@ impl<'a, F: Write> TokenHandler<'a, '_, F> { | ... | @@ -427,6 +427,27 @@ impl<'a, F: Write> TokenHandler<'a, '_, F> { |
| 427 | } | 427 | } |
| 428 | } | 428 | } |
| 429 | } | 429 | } |
| 430 | |||
| 431 | /// Used when we're done with the current expansion "original code" (ie code before expansion). | ||
| 432 | /// We close all tags inside `Class::Original` and only keep the ones that were not closed yet. | ||
| 433 | fn close_original_tag(&mut self) { | ||
| 434 | let mut classes_to_reopen = Vec::new(); | ||
| 435 | while let Some(mut class_info) = self.class_stack.open_classes.pop() { | ||
| 436 | if class_info.class == Class::Original { | ||
| 437 | while let Some(class_info) = classes_to_reopen.pop() { | ||
| 438 | self.class_stack.open_classes.push(class_info); | ||
| 439 | } | ||
| 440 | class_info.close_tag(self.out); | ||
| 441 | return; | ||
| 442 | } | ||
| 443 | class_info.close_tag(self.out); | ||
| 444 | if !class_info.pending_exit { | ||
| 445 | class_info.closing_tag = None; | ||
| 446 | classes_to_reopen.push(class_info); | ||
| 447 | } | ||
| 448 | } | ||
| 449 | panic!("Didn't find `Class::Original` to close"); | ||
| 450 | } | ||
| 430 | } | 451 | } |
| 431 | 452 | ||
| 432 | impl<F: Write> Drop for TokenHandler<'_, '_, F> { | 453 | impl<F: Write> Drop for TokenHandler<'_, '_, F> { |
| ... | @@ -484,7 +505,9 @@ fn end_expansion<'a, W: Write>( | ... | @@ -484,7 +505,9 @@ fn end_expansion<'a, W: Write>( |
| 484 | expanded_codes: &'a [ExpandedCode], | 505 | expanded_codes: &'a [ExpandedCode], |
| 485 | span: Span, | 506 | span: Span, |
| 486 | ) -> Option<&'a ExpandedCode> { | 507 | ) -> Option<&'a ExpandedCode> { |
| 487 | token_handler.class_stack.exit_elem(); | 508 | // We close `Class::Original` and everything open inside it. |
| 509 | token_handler.close_original_tag(); | ||
| 510 | // Then we check if we have another macro expansion on the same line. | ||
| 488 | let expansion = get_next_expansion(expanded_codes, token_handler.line, span); | 511 | let expansion = get_next_expansion(expanded_codes, token_handler.line, span); |
| 489 | if expansion.is_none() { | 512 | if expansion.is_none() { |
| 490 | token_handler.close_expansion(); | 513 | token_handler.close_expansion(); |
src/librustdoc/html/render/search_index.rs+14-21| ... | @@ -1051,28 +1051,21 @@ impl Serialize for TypeData { | ... | @@ -1051,28 +1051,21 @@ impl Serialize for TypeData { |
| 1051 | where | 1051 | where |
| 1052 | S: Serializer, | 1052 | S: Serializer, |
| 1053 | { | 1053 | { |
| 1054 | if self.search_unbox | 1054 | let mut seq = serializer.serialize_seq(None)?; |
| 1055 | || !self.inverted_function_inputs_index.is_empty() | 1055 | let mut buf = Vec::new(); |
| 1056 | || !self.inverted_function_output_index.is_empty() | 1056 | encode::write_postings_to_string(&self.inverted_function_inputs_index, &mut buf); |
| 1057 | { | 1057 | let mut serialized_result = Vec::new(); |
| 1058 | let mut seq = serializer.serialize_seq(None)?; | 1058 | stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result); |
| 1059 | let mut buf = Vec::new(); | 1059 | seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?; |
| 1060 | encode::write_postings_to_string(&self.inverted_function_inputs_index, &mut buf); | 1060 | buf.clear(); |
| 1061 | let mut serialized_result = Vec::new(); | 1061 | serialized_result.clear(); |
| 1062 | stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result); | 1062 | encode::write_postings_to_string(&self.inverted_function_output_index, &mut buf); |
| 1063 | seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?; | 1063 | stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result); |
| 1064 | buf.clear(); | 1064 | seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?; |
| 1065 | serialized_result.clear(); | 1065 | if self.search_unbox { |
| 1066 | encode::write_postings_to_string(&self.inverted_function_output_index, &mut buf); | 1066 | seq.serialize_element(&1)?; |
| 1067 | stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result); | ||
| 1068 | seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?; | ||
| 1069 | if self.search_unbox { | ||
| 1070 | seq.serialize_element(&1)?; | ||
| 1071 | } | ||
| 1072 | seq.end() | ||
| 1073 | } else { | ||
| 1074 | None::<()>.serialize(serializer) | ||
| 1075 | } | 1067 | } |
| 1068 | seq.end() | ||
| 1076 | } | 1069 | } |
| 1077 | } | 1070 | } |
| 1078 | 1071 |
tests/run-make/alloc-no-oom-handling/rmake.rs+1-1| ... | @@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root}; | ... | @@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root}; |
| 6 | 6 | ||
| 7 | fn main() { | 7 | fn main() { |
| 8 | rustc() | 8 | rustc() |
| 9 | .edition("2021") | 9 | .edition("2024") |
| 10 | .arg("-Dwarnings") | 10 | .arg("-Dwarnings") |
| 11 | .crate_type("rlib") | 11 | .crate_type("rlib") |
| 12 | .input(source_root().join("library/alloc/src/lib.rs")) | 12 | .input(source_root().join("library/alloc/src/lib.rs")) |
tests/run-make/alloc-no-rc/rmake.rs+1-1| ... | @@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root}; | ... | @@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root}; |
| 6 | 6 | ||
| 7 | fn main() { | 7 | fn main() { |
| 8 | rustc() | 8 | rustc() |
| 9 | .edition("2021") | 9 | .edition("2024") |
| 10 | .arg("-Dwarnings") | 10 | .arg("-Dwarnings") |
| 11 | .crate_type("rlib") | 11 | .crate_type("rlib") |
| 12 | .input(source_root().join("library/alloc/src/lib.rs")) | 12 | .input(source_root().join("library/alloc/src/lib.rs")) |
tests/run-make/alloc-no-sync/rmake.rs+1-1| ... | @@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root}; | ... | @@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root}; |
| 6 | 6 | ||
| 7 | fn main() { | 7 | fn main() { |
| 8 | rustc() | 8 | rustc() |
| 9 | .edition("2021") | 9 | .edition("2024") |
| 10 | .arg("-Dwarnings") | 10 | .arg("-Dwarnings") |
| 11 | .crate_type("rlib") | 11 | .crate_type("rlib") |
| 12 | .input(source_root().join("library/alloc/src/lib.rs")) | 12 | .input(source_root().join("library/alloc/src/lib.rs")) |
tests/run-make/llvm-location-discriminator-limit-dummy-span/rmake.rs+3-3| ... | @@ -49,21 +49,21 @@ fn main() { | ... | @@ -49,21 +49,21 @@ fn main() { |
| 49 | rustc() | 49 | rustc() |
| 50 | .input("proc.rs") | 50 | .input("proc.rs") |
| 51 | .crate_type("proc-macro") | 51 | .crate_type("proc-macro") |
| 52 | .edition("2021") | 52 | .edition("2024") |
| 53 | .arg("-Cdebuginfo=line-tables-only") | 53 | .arg("-Cdebuginfo=line-tables-only") |
| 54 | .run(); | 54 | .run(); |
| 55 | rustc() | 55 | rustc() |
| 56 | .extern_("proc", dynamic_lib_name("proc")) | 56 | .extern_("proc", dynamic_lib_name("proc")) |
| 57 | .input("other.rs") | 57 | .input("other.rs") |
| 58 | .crate_type("rlib") | 58 | .crate_type("rlib") |
| 59 | .edition("2021") | 59 | .edition("2024") |
| 60 | .opt_level("3") | 60 | .opt_level("3") |
| 61 | .arg("-Cdebuginfo=line-tables-only") | 61 | .arg("-Cdebuginfo=line-tables-only") |
| 62 | .run(); | 62 | .run(); |
| 63 | rustc() | 63 | rustc() |
| 64 | .extern_("other", rust_lib_name("other")) | 64 | .extern_("other", rust_lib_name("other")) |
| 65 | .input("main.rs") | 65 | .input("main.rs") |
| 66 | .edition("2021") | 66 | .edition("2024") |
| 67 | .opt_level("3") | 67 | .opt_level("3") |
| 68 | .arg("-Cdebuginfo=line-tables-only") | 68 | .arg("-Cdebuginfo=line-tables-only") |
| 69 | .arg("-Clto=fat") | 69 | .arg("-Clto=fat") |
tests/run-make/panic-abort-eh_frame/rmake.rs+1-1| ... | @@ -19,7 +19,7 @@ fn main() { | ... | @@ -19,7 +19,7 @@ fn main() { |
| 19 | .crate_type("lib") | 19 | .crate_type("lib") |
| 20 | .emit("obj=foo.o") | 20 | .emit("obj=foo.o") |
| 21 | .panic("abort") | 21 | .panic("abort") |
| 22 | .edition("2021") | 22 | .edition("2024") |
| 23 | .arg("-Zvalidate-mir") | 23 | .arg("-Zvalidate-mir") |
| 24 | .arg("-Cforce-unwind-tables=no") | 24 | .arg("-Cforce-unwind-tables=no") |
| 25 | .run(); | 25 | .run(); |
tests/run-make/rustdoc-scrape-examples-macros/rmake.rs+2-2| ... | @@ -19,14 +19,14 @@ fn main() { | ... | @@ -19,14 +19,14 @@ fn main() { |
| 19 | rustc() | 19 | rustc() |
| 20 | .input("src/proc.rs") | 20 | .input("src/proc.rs") |
| 21 | .crate_name(proc_crate_name) | 21 | .crate_name(proc_crate_name) |
| 22 | .edition("2021") | 22 | .edition("2024") |
| 23 | .crate_type("proc-macro") | 23 | .crate_type("proc-macro") |
| 24 | .emit("dep-info,link") | 24 | .emit("dep-info,link") |
| 25 | .run(); | 25 | .run(); |
| 26 | rustc() | 26 | rustc() |
| 27 | .input("src/lib.rs") | 27 | .input("src/lib.rs") |
| 28 | .crate_name(crate_name) | 28 | .crate_name(crate_name) |
| 29 | .edition("2021") | 29 | .edition("2024") |
| 30 | .crate_type("lib") | 30 | .crate_type("lib") |
| 31 | .emit("dep-info,link") | 31 | .emit("dep-info,link") |
| 32 | .run(); | 32 | .run(); |
tests/rustdoc-js/auxiliary/emptytype.rs created+41| ... | @@ -0,0 +1,41 @@ | ||
| 1 | // https://github.com/rust-lang/rust/issues/148431 | ||
| 2 | |||
| 3 | // This test is designed to hit a case where, thanks to the | ||
| 4 | // recursion limit, the where clause gets generated, but not | ||
| 5 | // used, because we run out of fuel. | ||
| 6 | // | ||
| 7 | // This results in a reverse index with nothing in it, which | ||
| 8 | // used to crash when we parsed it. | ||
| 9 | pub fn foobar1<A: T1<B>, B: T2<C>, C: T3<D>, D: T4<A>>(a: A) {} | ||
| 10 | |||
| 11 | pub trait T1<T: ?Sized> {} | ||
| 12 | pub trait T2<T: ?Sized> {} | ||
| 13 | pub trait T3<T: ?Sized> {} | ||
| 14 | pub trait T4<T: ?Sized> {} | ||
| 15 | |||
| 16 | // foobar1 is the version that worked at the time this test was written | ||
| 17 | // the rest are here to try to make the test at least a little more | ||
| 18 | // robust, in the sense that it actually tests the code and isn't magically | ||
| 19 | // fixed by the recursion limit changing | ||
| 20 | pub fn foobar2<A: U1<B>, B: U2<C>, C: U3<D>, D: U4<E>, E: U5<A>>(a: A) {} | ||
| 21 | |||
| 22 | pub trait U1<T: ?Sized> {} | ||
| 23 | pub trait U2<T: ?Sized> {} | ||
| 24 | pub trait U3<T: ?Sized> {} | ||
| 25 | pub trait U4<T: ?Sized> {} | ||
| 26 | pub trait U5<T: ?Sized> {} | ||
| 27 | |||
| 28 | pub fn foobar3<A: V1<B>, B: V2<C>, C: V3<D>, D: V4<E>, E: V5<F>, F: V6<A>>(a: A) {} | ||
| 29 | |||
| 30 | pub trait V1<T: ?Sized> {} | ||
| 31 | pub trait V2<T: ?Sized> {} | ||
| 32 | pub trait V3<T: ?Sized> {} | ||
| 33 | pub trait V4<T: ?Sized> {} | ||
| 34 | pub trait V5<T: ?Sized> {} | ||
| 35 | pub trait V6<T: ?Sized> {} | ||
| 36 | |||
| 37 | pub fn foobar4<A: W1<B>, B: W2<C>, C: W3<A>>(a: A) {} | ||
| 38 | |||
| 39 | pub trait W1<T: ?Sized> {} | ||
| 40 | pub trait W2<T: ?Sized> {} | ||
| 41 | pub trait W3<T: ?Sized> {} | ||
tests/rustdoc-js/empty-type.js created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | const EXPECTED = [ | ||
| 2 | { | ||
| 3 | query: 'baz', | ||
| 4 | others: [ | ||
| 5 | { name: 'baz' } | ||
| 6 | ], | ||
| 7 | }, | ||
| 8 | ]; | ||
tests/rustdoc-js/empty-type.rs created+8| ... | @@ -0,0 +1,8 @@ | ||
| 1 | //@ aux-crate:emptytype=emptytype.rs | ||
| 2 | //@ compile-flags: --extern emptytype | ||
| 3 | //@ aux-build:emptytype.rs | ||
| 4 | //@ build-aux-docs | ||
| 5 | |||
| 6 | extern crate emptytype; | ||
| 7 | |||
| 8 | pub fn baz() {} | ||
tests/rustdoc/macro/auxiliary/one-line-expand.rs created+15| ... | @@ -0,0 +1,15 @@ | ||
| 1 | //@ force-host | ||
| 2 | //@ no-prefer-dynamic | ||
| 3 | //@ compile-flags: --crate-type proc-macro | ||
| 4 | |||
| 5 | #![crate_type = "proc-macro"] | ||
| 6 | #![crate_name = "just_some_proc"] | ||
| 7 | |||
| 8 | extern crate proc_macro; | ||
| 9 | |||
| 10 | use proc_macro::TokenStream; | ||
| 11 | |||
| 12 | #[proc_macro_attribute] | ||
| 13 | pub fn repro(_args: TokenStream, _input: TokenStream) -> TokenStream { | ||
| 14 | "struct Repro;".parse().unwrap() | ||
| 15 | } | ||
tests/rustdoc/macro/one-line-expand.rs created+19| ... | @@ -0,0 +1,19 @@ | ||
| 1 | // Regression test for <https://github.com/rust-lang/rust/issues/148184>. | ||
| 2 | // It ensures that the macro expansion correctly handles its "class stack". | ||
| 3 | |||
| 4 | //@ compile-flags: -Zunstable-options --generate-macro-expansion | ||
| 5 | //@ aux-build:one-line-expand.rs | ||
| 6 | |||
| 7 | #![crate_name = "foo"] | ||
| 8 | |||
| 9 | extern crate just_some_proc; | ||
| 10 | |||
| 11 | //@ has 'src/foo/one-line-expand.rs.html' | ||
| 12 | //@ has - '//*[@class="comment"]' '//' | ||
| 13 | //@ has - '//*[@class="original"]' '#[just_some_proc::repro]' | ||
| 14 | //@ has - '//*[@class="original"]/*[@class="attr"]' '#[just_some_proc::repro]' | ||
| 15 | //@ has - '//code/*[@class="kw"]' 'struct ' | ||
| 16 | |||
| 17 | // | ||
| 18 | #[just_some_proc::repro] | ||
| 19 | struct Repro; | ||
tests/ui/async-await/async-closures/ice-async-closure-variance-issue-148488.rs created+12| ... | @@ -0,0 +1,12 @@ | ||
| 1 | //@ edition: 2024 | ||
| 2 | |||
| 3 | struct T<'g>(); | ||
| 4 | //~^ ERROR lifetime parameter `'g` is never used | ||
| 5 | |||
| 6 | fn ord<a>() -> _ { | ||
| 7 | //~^ WARN type parameter `a` should have an upper camel case name | ||
| 8 | //~| ERROR the placeholder `_` is not allowed within types on item signatures for return types | ||
| 9 | async || {} | ||
| 10 | } | ||
| 11 | |||
| 12 | fn main() {} | ||
tests/ui/async-await/async-closures/ice-async-closure-variance-issue-148488.stderr created+26| ... | @@ -0,0 +1,26 @@ | ||
| 1 | warning: type parameter `a` should have an upper camel case name | ||
| 2 | --> $DIR/ice-async-closure-variance-issue-148488.rs:6:8 | ||
| 3 | | | ||
| 4 | LL | fn ord<a>() -> _ { | ||
| 5 | | ^ help: convert the identifier to upper camel case: `A` | ||
| 6 | | | ||
| 7 | = note: `#[warn(non_camel_case_types)]` (part of `#[warn(nonstandard_style)]`) on by default | ||
| 8 | |||
| 9 | error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types | ||
| 10 | --> $DIR/ice-async-closure-variance-issue-148488.rs:6:16 | ||
| 11 | | | ||
| 12 | LL | fn ord<a>() -> _ { | ||
| 13 | | ^ not allowed in type signatures | ||
| 14 | |||
| 15 | error[E0392]: lifetime parameter `'g` is never used | ||
| 16 | --> $DIR/ice-async-closure-variance-issue-148488.rs:3:10 | ||
| 17 | | | ||
| 18 | LL | struct T<'g>(); | ||
| 19 | | ^^ unused lifetime parameter | ||
| 20 | | | ||
| 21 | = help: consider removing `'g`, referring to it in a field, or using a marker such as `PhantomData` | ||
| 22 | |||
| 23 | error: aborting due to 2 previous errors; 1 warning emitted | ||
| 24 | |||
| 25 | Some errors have detailed explanations: E0121, E0392. | ||
| 26 | For more information about an error, try `rustc --explain E0121`. | ||
tests/ui/pattern/const-error-ice-issue-148542.rs created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | //@ edition: 2021 | ||
| 2 | |||
| 3 | // Regression test for #148542 | ||
| 4 | // Ensure we don't ICE with "Invalid `ConstKind` for `const_to_pat`: {const error}" | ||
| 5 | |||
| 6 | fn foo() where &str:, { | ||
| 7 | //~^ ERROR `&` without an explicit lifetime name cannot be used here | ||
| 8 | match 42_u8 { | ||
| 9 | -10.. => {} | ||
| 10 | } | ||
| 11 | } | ||
| 12 | |||
| 13 | fn main() {} | ||
tests/ui/pattern/const-error-ice-issue-148542.stderr created+14| ... | @@ -0,0 +1,14 @@ | ||
| 1 | error[E0637]: `&` without an explicit lifetime name cannot be used here | ||
| 2 | --> $DIR/const-error-ice-issue-148542.rs:6:16 | ||
| 3 | | | ||
| 4 | LL | fn foo() where &str:, { | ||
| 5 | | ^ explicit lifetime name needed here | ||
| 6 | | | ||
| 7 | help: consider introducing a higher-ranked lifetime here | ||
| 8 | | | ||
| 9 | LL | fn foo() where for<'a> &'a str:, { | ||
| 10 | | +++++++ ++ | ||
| 11 | |||
| 12 | error: aborting due to 1 previous error | ||
| 13 | |||
| 14 | For more information about this error, try `rustc --explain E0637`. | ||
tests/ui/traits/next-solver/normalization-shadowing/use_object_if_empty_env.rs created+36| ... | @@ -0,0 +1,36 @@ | ||
| 1 | //@ compile-flags: -Znext-solver | ||
| 2 | //@ check-pass | ||
| 3 | |||
| 4 | // Regression test for trait-system-refactor-initiative#244 | ||
| 5 | |||
| 6 | trait Trait { | ||
| 7 | type Assoc; | ||
| 8 | } | ||
| 9 | |||
| 10 | // We have param env candidate for the trait goal but not the projection. | ||
| 11 | // Under such circumstance, consider object candidate if the self_ty is trait object. | ||
| 12 | fn foo<T>(x: <dyn Trait<Assoc = T> as Trait>::Assoc) -> T | ||
| 13 | where | ||
| 14 | dyn Trait<Assoc = T>: Trait, | ||
| 15 | { | ||
| 16 | x | ||
| 17 | } | ||
| 18 | |||
| 19 | trait Id<'a> { | ||
| 20 | type This: ?Sized; | ||
| 21 | } | ||
| 22 | impl<T: ?Sized> Id<'_> for T { | ||
| 23 | type This = T; | ||
| 24 | } | ||
| 25 | |||
| 26 | // Ensure that we properly normalize alias self_ty before evaluating the goal. | ||
| 27 | fn alias_foo<T>(x: for<'a> fn( | ||
| 28 | <<dyn Trait<Assoc = T> as Id<'a>>::This as Trait>::Assoc | ||
| 29 | )) -> fn(T) | ||
| 30 | where | ||
| 31 | dyn Trait<Assoc = T>: Trait, | ||
| 32 | { | ||
| 33 | x | ||
| 34 | } | ||
| 35 | |||
| 36 | fn main() {} | ||