Auto merge of #148573 - matthiaskrgr:rollup-cn5viia, r=matthiaskrgr

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: rollup
This commit is contained in:
bors
2025-11-06 14:52:37 +00:00
26 changed files with 557 additions and 34 deletions
@@ -698,6 +698,7 @@ fn try_fold_ty(&mut self, t: Ty<'tcx>) -> Result<Ty<'tcx>, Self::Error> {
}
Closure(..)
| CoroutineClosure(..)
| FnDef(..)
| Infer(..)
| Coroutine(..)
@@ -454,7 +454,16 @@ pub(super) fn assemble_and_evaluate_candidates<G: GoalKind<D>>(
self.assemble_object_bound_candidates(goal, &mut candidates);
}
}
AssembleCandidatesFrom::EnvAndBounds => {}
AssembleCandidatesFrom::EnvAndBounds => {
// This is somewhat inconsistent and may make #57893 slightly easier to exploit.
// However, it matches the behavior of the old solver. See
// `tests/ui/traits/next-solver/normalization-shadowing/use_object_if_empty_env.rs`.
if matches!(normalized_self_ty.kind(), ty::Dynamic(..))
&& !candidates.iter().any(|c| matches!(c.source, CandidateSource::ParamEnv(_)))
{
self.assemble_object_bound_candidates(goal, &mut candidates);
}
}
}
(candidates, failed_candidate_info)
+112 -1
View File
@@ -52,7 +52,7 @@
mod iter;
use self::spec_extend::SpecExtend;
use self::spec_extend::{SpecExtend, SpecExtendFront};
mod spec_extend;
@@ -179,6 +179,21 @@ unsafe fn push_unchecked(&mut self, element: T) {
self.len += 1;
}
/// Prepends an element to the buffer.
///
/// # Safety
///
/// May only be called if `deque.len() < deque.capacity()`
#[inline]
unsafe fn push_front_unchecked(&mut self, element: T) {
self.head = self.wrap_sub(self.head, 1);
// SAFETY: Because of the precondition, it's guaranteed that there is space
// in the logical array before the first element (where self.head is now).
unsafe { self.buffer_write(self.head, element) };
// This can't overflow because `deque.len() < deque.capacity() <= usize::MAX`.
self.len += 1;
}
/// Moves an element out of the buffer
#[inline]
unsafe fn buffer_read(&mut self, off: usize) -> T {
@@ -505,6 +520,35 @@ unsafe fn copy_slice(&mut self, dst: usize, src: &[T]) {
}
}
/// Copies all values from `src` to `dst` in reversed order, wrapping around if needed.
/// Assumes capacity is sufficient.
/// Equivalent to calling [`VecDeque::copy_slice`] with a [reversed](https://doc.rust-lang.org/std/primitive.slice.html#method.reverse) slice.
#[inline]
unsafe fn copy_slice_reversed(&mut self, dst: usize, src: &[T]) {
/// # Safety
///
/// See [`ptr::copy_nonoverlapping`].
unsafe fn copy_nonoverlapping_reversed<T>(src: *const T, dst: *mut T, count: usize) {
for i in 0..count {
unsafe { ptr::copy_nonoverlapping(src.add(count - 1 - i), dst.add(i), 1) };
}
}
debug_assert!(src.len() <= self.capacity());
let head_room = self.capacity() - dst;
if src.len() <= head_room {
unsafe {
copy_nonoverlapping_reversed(src.as_ptr(), self.ptr().add(dst), src.len());
}
} else {
let (left, right) = src.split_at(src.len() - head_room);
unsafe {
copy_nonoverlapping_reversed(right.as_ptr(), self.ptr().add(dst), right.len());
copy_nonoverlapping_reversed(left.as_ptr(), self.ptr(), left.len());
}
}
}
/// Writes all values from `iter` to `dst`.
///
/// # Safety
@@ -2122,6 +2166,73 @@ pub fn push_back_mut(&mut self, value: T) -> &mut T {
unsafe { self.buffer_write(self.to_physical_idx(len), value) }
}
/// Prepends all contents of the iterator to the front of the deque.
/// The order of the contents is preserved.
///
/// To get behavior like [`append`][VecDeque::append] where elements are moved
/// from the other collection to this one, use `self.prepend(other.drain(..))`.
///
/// # Examples
///
/// ```
/// #![feature(deque_extend_front)]
/// use std::collections::VecDeque;
///
/// let mut deque = VecDeque::from([4, 5, 6]);
/// deque.prepend([1, 2, 3]);
/// assert_eq!(deque, [1, 2, 3, 4, 5, 6]);
/// ```
///
/// Move values between collections like [`append`][VecDeque::append] does but prepend to the front:
///
/// ```
/// #![feature(deque_extend_front)]
/// use std::collections::VecDeque;
///
/// let mut deque1 = VecDeque::from([4, 5, 6]);
/// let mut deque2 = VecDeque::from([1, 2, 3]);
/// deque1.prepend(deque2.drain(..));
/// assert_eq!(deque1, [1, 2, 3, 4, 5, 6]);
/// assert!(deque2.is_empty());
/// ```
#[unstable(feature = "deque_extend_front", issue = "146975")]
#[track_caller]
pub fn prepend<I: IntoIterator<Item = T, IntoIter: DoubleEndedIterator>>(&mut self, other: I) {
self.extend_front(other.into_iter().rev())
}
/// Prepends all contents of the iterator to the front of the deque,
/// as if [`push_front`][VecDeque::push_front] was called repeatedly with
/// the values yielded by the iterator.
///
/// # Examples
///
/// ```
/// #![feature(deque_extend_front)]
/// use std::collections::VecDeque;
///
/// let mut deque = VecDeque::from([4, 5, 6]);
/// deque.extend_front([3, 2, 1]);
/// assert_eq!(deque, [1, 2, 3, 4, 5, 6]);
/// ```
///
/// This behaves like [`push_front`][VecDeque::push_front] was called repeatedly:
///
/// ```
/// use std::collections::VecDeque;
///
/// let mut deque = VecDeque::from([4, 5, 6]);
/// for v in [3, 2, 1] {
/// deque.push_front(v);
/// }
/// assert_eq!(deque, [1, 2, 3, 4, 5, 6]);
/// ```
#[unstable(feature = "deque_extend_front", issue = "146975")]
#[track_caller]
pub fn extend_front<I: IntoIterator<Item = T>>(&mut self, iter: I) {
<Self as SpecExtendFront<T, I::IntoIter>>::spec_extend_front(self, iter.into_iter());
}
#[inline]
fn is_contiguous(&self) -> bool {
// Do the calculation like this to avoid overflowing if len + head > usize::MAX
@@ -1,4 +1,4 @@
use core::iter::TrustedLen;
use core::iter::{Copied, Rev, TrustedLen};
use core::slice;
use super::VecDeque;
@@ -114,3 +114,113 @@ fn spec_extend(&mut self, iterator: slice::Iter<'a, T>) {
}
}
}
// Specialization trait used for VecDeque::extend_front
pub(super) trait SpecExtendFront<T, I> {
#[track_caller]
fn spec_extend_front(&mut self, iter: I);
}
impl<T, I, A: Allocator> SpecExtendFront<T, I> for VecDeque<T, A>
where
I: Iterator<Item = T>,
{
#[track_caller]
default fn spec_extend_front(&mut self, mut iter: I) {
// This function should be the moral equivalent of:
//
// for item in iter {
// self.push_front(item);
// }
while let Some(element) = iter.next() {
let (lower, _) = iter.size_hint();
self.reserve(lower.saturating_add(1));
// SAFETY: We just reserved space for at least one element.
unsafe { self.push_front_unchecked(element) };
// Inner loop to avoid repeatedly calling `reserve`.
while self.len < self.capacity() {
let Some(element) = iter.next() else {
return;
};
// SAFETY: The loop condition guarantees that `self.len() < self.capacity()`.
unsafe { self.push_front_unchecked(element) };
}
}
}
}
#[cfg(not(test))]
impl<T, A: Allocator> SpecExtendFront<T, vec::IntoIter<T>> for VecDeque<T, A> {
#[track_caller]
fn spec_extend_front(&mut self, mut iterator: vec::IntoIter<T>) {
let slice = iterator.as_slice();
// SAFETY: elements in the slice are forgotten after this call
unsafe { prepend_reversed(self, slice) };
iterator.forget_remaining_elements();
}
}
#[cfg(not(test))]
impl<T, A: Allocator> SpecExtendFront<T, Rev<vec::IntoIter<T>>> for VecDeque<T, A> {
#[track_caller]
fn spec_extend_front(&mut self, iterator: Rev<vec::IntoIter<T>>) {
let mut iterator = iterator.into_inner();
let slice = iterator.as_slice();
// SAFETY: elements in the slice are forgotten after this call
unsafe { prepend(self, slice) };
iterator.forget_remaining_elements();
}
}
impl<'a, T, A: Allocator> SpecExtendFront<T, Copied<slice::Iter<'a, T>>> for VecDeque<T, A>
where
Copied<slice::Iter<'a, T>>: Iterator<Item = T>,
{
#[track_caller]
fn spec_extend_front(&mut self, iter: Copied<slice::Iter<'a, T>>) {
let slice = iter.into_inner().as_slice();
// SAFETY: T is Copy because Copied<slice::Iter<'a, T>> is Iterator
unsafe { prepend_reversed(self, slice) };
}
}
impl<'a, T, A: Allocator> SpecExtendFront<T, Rev<Copied<slice::Iter<'a, T>>>> for VecDeque<T, A>
where
Rev<Copied<slice::Iter<'a, T>>>: Iterator<Item = T>,
{
#[track_caller]
fn spec_extend_front(&mut self, iter: Rev<Copied<slice::Iter<'a, T>>>) {
let slice = iter.into_inner().into_inner().as_slice();
// SAFETY: T is Copy because Rev<Copied<slice::Iter<'a, T>>> is Iterator
unsafe { prepend(self, slice) };
}
}
/// # Safety
///
/// Elements of `slice` will be copied into the deque, make sure to forget the items if `T` is not `Copy`.
unsafe fn prepend<T, A: Allocator>(deque: &mut VecDeque<T, A>, slice: &[T]) {
deque.reserve(slice.len());
unsafe {
deque.head = deque.wrap_sub(deque.head, slice.len());
deque.copy_slice(deque.head, slice);
deque.len += slice.len();
}
}
/// # Safety
///
/// Elements of `slice` will be copied into the deque, make sure to forget the items if `T` is not `Copy`.
unsafe fn prepend_reversed<T, A: Allocator>(deque: &mut VecDeque<T, A>, slice: &[T]) {
deque.reserve(slice.len());
unsafe {
deque.head = deque.wrap_sub(deque.head, slice.len());
deque.copy_slice_reversed(deque.head, slice);
deque.len += slice.len();
}
}
+2
View File
@@ -106,6 +106,7 @@
#![feature(const_default)]
#![feature(const_eval_select)]
#![feature(const_heap)]
#![feature(copied_into_inner)]
#![feature(core_intrinsics)]
#![feature(deprecated_suggestion)]
#![feature(deref_pure_trait)]
@@ -134,6 +135,7 @@
#![feature(ptr_alignment_type)]
#![feature(ptr_internals)]
#![feature(ptr_metadata)]
#![feature(rev_into_inner)]
#![feature(set_ptr_value)]
#![feature(sized_type_properties)]
#![feature(slice_from_ptr_range)]
+2
View File
@@ -20,6 +20,7 @@
#![feature(assert_matches)]
#![feature(char_internals)]
#![feature(char_max_len)]
#![feature(copied_into_inner)]
#![feature(core_intrinsics)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
@@ -32,6 +33,7 @@
#![feature(maybe_uninit_uninit_array_transpose)]
#![feature(ptr_alignment_type)]
#![feature(ptr_internals)]
#![feature(rev_into_inner)]
#![feature(sized_type_properties)]
#![feature(slice_iter_mut_as_mut_slice)]
#![feature(slice_ptr_get)]
+74
View File
@@ -2081,3 +2081,77 @@ fn test_extend_and_prepend_from_within() {
v.extend_from_within(..);
assert_eq!(v.iter().map(|s| &**s).collect::<String>(), "123123123123");
}
#[test]
fn test_extend_front() {
let mut v = VecDeque::new();
v.extend_front(0..3);
assert_eq!(v, [2, 1, 0]);
v.extend_front(3..6);
assert_eq!(v, [5, 4, 3, 2, 1, 0]);
v.prepend([1; 4]);
assert_eq!(v, [1, 1, 1, 1, 5, 4, 3, 2, 1, 0]);
let mut v = VecDeque::with_capacity(8);
let cap = v.capacity();
v.extend(0..4);
v.truncate_front(2);
v.extend_front(4..8);
assert_eq!(v.as_slices(), ([7, 6].as_slice(), [5, 4, 2, 3].as_slice()));
assert_eq!(v.capacity(), cap);
let mut v = VecDeque::new();
v.extend_front([]);
v.extend_front(None);
v.extend_front(vec![]);
v.prepend([]);
v.prepend(None);
v.prepend(vec![]);
assert_eq!(v.capacity(), 0);
v.extend_front(Some(123));
assert_eq!(v, [123]);
}
#[test]
fn test_extend_front_specialization_vec_into_iter() {
// trigger 4 code paths: all combinations of prepend and extend_front, wrap and no wrap
let mut v = VecDeque::with_capacity(4);
v.prepend(vec![1, 2, 3]);
assert_eq!(v, [1, 2, 3]);
v.pop_back();
// this should wrap around the physical buffer
v.prepend(vec![-1, 0]);
// check it really wrapped
assert_eq!(v.as_slices(), ([-1].as_slice(), [0, 1, 2].as_slice()));
let mut v = VecDeque::with_capacity(4);
v.extend_front(vec![1, 2, 3]);
assert_eq!(v, [3, 2, 1]);
v.pop_back();
// this should wrap around the physical buffer
v.extend_front(vec![4, 5]);
// check it really wrapped
assert_eq!(v.as_slices(), ([5].as_slice(), [4, 3, 2].as_slice()));
}
#[test]
fn test_extend_front_specialization_copy_slice() {
// trigger 4 code paths: all combinations of prepend and extend_front, wrap and no wrap
let mut v = VecDeque::with_capacity(4);
v.prepend([1, 2, 3].as_slice().iter().copied());
assert_eq!(v, [1, 2, 3]);
v.pop_back();
// this should wrap around the physical buffer
v.prepend([-1, 0].as_slice().iter().copied());
// check it really wrapped
assert_eq!(v.as_slices(), ([-1].as_slice(), [0, 1, 2].as_slice()));
let mut v = VecDeque::with_capacity(4);
v.extend_front([1, 2, 3].as_slice().iter().copied());
assert_eq!(v, [3, 2, 1]);
v.pop_back();
// this should wrap around the physical buffer
v.extend_front([4, 5].as_slice().iter().copied());
// check it really wrapped
assert_eq!(v.as_slices(), ([5].as_slice(), [4, 3, 2].as_slice()));
}
+6
View File
@@ -24,6 +24,12 @@ impl<I> Copied<I> {
pub(in crate::iter) fn new(it: I) -> Copied<I> {
Copied { it }
}
#[doc(hidden)]
#[unstable(feature = "copied_into_inner", issue = "none")]
pub fn into_inner(self) -> I {
self.it
}
}
fn copy_fold<T: Copy, Acc>(mut f: impl FnMut(Acc, T) -> Acc) -> impl FnMut(Acc, &T) -> Acc {
+24 -1
View File
@@ -427,6 +427,27 @@ fn close_expansion(&mut self) {
}
}
}
/// Used when we're done with the current expansion "original code" (ie code before expansion).
/// We close all tags inside `Class::Original` and only keep the ones that were not closed yet.
fn close_original_tag(&mut self) {
let mut classes_to_reopen = Vec::new();
while let Some(mut class_info) = self.class_stack.open_classes.pop() {
if class_info.class == Class::Original {
while let Some(class_info) = classes_to_reopen.pop() {
self.class_stack.open_classes.push(class_info);
}
class_info.close_tag(self.out);
return;
}
class_info.close_tag(self.out);
if !class_info.pending_exit {
class_info.closing_tag = None;
classes_to_reopen.push(class_info);
}
}
panic!("Didn't find `Class::Original` to close");
}
}
impl<F: Write> Drop for TokenHandler<'_, '_, F> {
@@ -484,7 +505,9 @@ fn end_expansion<'a, W: Write>(
expanded_codes: &'a [ExpandedCode],
span: Span,
) -> Option<&'a ExpandedCode> {
token_handler.class_stack.exit_elem();
// We close `Class::Original` and everything open inside it.
token_handler.close_original_tag();
// Then we check if we have another macro expansion on the same line.
let expansion = get_next_expansion(expanded_codes, token_handler.line, span);
if expansion.is_none() {
token_handler.close_expansion();
+14 -21
View File
@@ -1051,28 +1051,21 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if self.search_unbox
|| !self.inverted_function_inputs_index.is_empty()
|| !self.inverted_function_output_index.is_empty()
{
let mut seq = serializer.serialize_seq(None)?;
let mut buf = Vec::new();
encode::write_postings_to_string(&self.inverted_function_inputs_index, &mut buf);
let mut serialized_result = Vec::new();
stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result);
seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?;
buf.clear();
serialized_result.clear();
encode::write_postings_to_string(&self.inverted_function_output_index, &mut buf);
stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result);
seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?;
if self.search_unbox {
seq.serialize_element(&1)?;
}
seq.end()
} else {
None::<()>.serialize(serializer)
let mut seq = serializer.serialize_seq(None)?;
let mut buf = Vec::new();
encode::write_postings_to_string(&self.inverted_function_inputs_index, &mut buf);
let mut serialized_result = Vec::new();
stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result);
seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?;
buf.clear();
serialized_result.clear();
encode::write_postings_to_string(&self.inverted_function_output_index, &mut buf);
stringdex_internals::encode::write_base64_to_bytes(&buf, &mut serialized_result);
seq.serialize_element(&str::from_utf8(&serialized_result).unwrap())?;
if self.search_unbox {
seq.serialize_element(&1)?;
}
seq.end()
}
}
@@ -6,7 +6,7 @@
fn main() {
rustc()
.edition("2021")
.edition("2024")
.arg("-Dwarnings")
.crate_type("rlib")
.input(source_root().join("library/alloc/src/lib.rs"))
+1 -1
View File
@@ -6,7 +6,7 @@
fn main() {
rustc()
.edition("2021")
.edition("2024")
.arg("-Dwarnings")
.crate_type("rlib")
.input(source_root().join("library/alloc/src/lib.rs"))
+1 -1
View File
@@ -6,7 +6,7 @@
fn main() {
rustc()
.edition("2021")
.edition("2024")
.arg("-Dwarnings")
.crate_type("rlib")
.input(source_root().join("library/alloc/src/lib.rs"))
@@ -49,21 +49,21 @@ fn main() {
rustc()
.input("proc.rs")
.crate_type("proc-macro")
.edition("2021")
.edition("2024")
.arg("-Cdebuginfo=line-tables-only")
.run();
rustc()
.extern_("proc", dynamic_lib_name("proc"))
.input("other.rs")
.crate_type("rlib")
.edition("2021")
.edition("2024")
.opt_level("3")
.arg("-Cdebuginfo=line-tables-only")
.run();
rustc()
.extern_("other", rust_lib_name("other"))
.input("main.rs")
.edition("2021")
.edition("2024")
.opt_level("3")
.arg("-Cdebuginfo=line-tables-only")
.arg("-Clto=fat")
+1 -1
View File
@@ -19,7 +19,7 @@ fn main() {
.crate_type("lib")
.emit("obj=foo.o")
.panic("abort")
.edition("2021")
.edition("2024")
.arg("-Zvalidate-mir")
.arg("-Cforce-unwind-tables=no")
.run();
@@ -19,14 +19,14 @@ fn main() {
rustc()
.input("src/proc.rs")
.crate_name(proc_crate_name)
.edition("2021")
.edition("2024")
.crate_type("proc-macro")
.emit("dep-info,link")
.run();
rustc()
.input("src/lib.rs")
.crate_name(crate_name)
.edition("2021")
.edition("2024")
.crate_type("lib")
.emit("dep-info,link")
.run();
+41
View File
@@ -0,0 +1,41 @@
// https://github.com/rust-lang/rust/issues/148431
// This test is designed to hit a case where, thanks to the
// recursion limit, the where clause gets generated, but not
// used, because we run out of fuel.
//
// This results in a reverse index with nothing in it, which
// used to crash when we parsed it.
pub fn foobar1<A: T1<B>, B: T2<C>, C: T3<D>, D: T4<A>>(a: A) {}
pub trait T1<T: ?Sized> {}
pub trait T2<T: ?Sized> {}
pub trait T3<T: ?Sized> {}
pub trait T4<T: ?Sized> {}
// foobar1 is the version that worked at the time this test was written
// the rest are here to try to make the test at least a little more
// robust, in the sense that it actually tests the code and isn't magically
// fixed by the recursion limit changing
pub fn foobar2<A: U1<B>, B: U2<C>, C: U3<D>, D: U4<E>, E: U5<A>>(a: A) {}
pub trait U1<T: ?Sized> {}
pub trait U2<T: ?Sized> {}
pub trait U3<T: ?Sized> {}
pub trait U4<T: ?Sized> {}
pub trait U5<T: ?Sized> {}
pub fn foobar3<A: V1<B>, B: V2<C>, C: V3<D>, D: V4<E>, E: V5<F>, F: V6<A>>(a: A) {}
pub trait V1<T: ?Sized> {}
pub trait V2<T: ?Sized> {}
pub trait V3<T: ?Sized> {}
pub trait V4<T: ?Sized> {}
pub trait V5<T: ?Sized> {}
pub trait V6<T: ?Sized> {}
pub fn foobar4<A: W1<B>, B: W2<C>, C: W3<A>>(a: A) {}
pub trait W1<T: ?Sized> {}
pub trait W2<T: ?Sized> {}
pub trait W3<T: ?Sized> {}
+8
View File
@@ -0,0 +1,8 @@
const EXPECTED = [
{
query: 'baz',
others: [
{ name: 'baz' }
],
},
];
+8
View File
@@ -0,0 +1,8 @@
//@ aux-crate:emptytype=emptytype.rs
//@ compile-flags: --extern emptytype
//@ aux-build:emptytype.rs
//@ build-aux-docs
extern crate emptytype;
pub fn baz() {}
@@ -0,0 +1,15 @@
//@ force-host
//@ no-prefer-dynamic
//@ compile-flags: --crate-type proc-macro
#![crate_type = "proc-macro"]
#![crate_name = "just_some_proc"]
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_attribute]
pub fn repro(_args: TokenStream, _input: TokenStream) -> TokenStream {
"struct Repro;".parse().unwrap()
}
+19
View File
@@ -0,0 +1,19 @@
// Regression test for <https://github.com/rust-lang/rust/issues/148184>.
// It ensures that the macro expansion correctly handles its "class stack".
//@ compile-flags: -Zunstable-options --generate-macro-expansion
//@ aux-build:one-line-expand.rs
#![crate_name = "foo"]
extern crate just_some_proc;
//@ has 'src/foo/one-line-expand.rs.html'
//@ has - '//*[@class="comment"]' '//'
//@ has - '//*[@class="original"]' '#[just_some_proc::repro]'
//@ has - '//*[@class="original"]/*[@class="attr"]' '#[just_some_proc::repro]'
//@ has - '//code/*[@class="kw"]' 'struct '
//
#[just_some_proc::repro]
struct Repro;
@@ -0,0 +1,12 @@
//@ edition: 2024
struct T<'g>();
//~^ ERROR lifetime parameter `'g` is never used
fn ord<a>() -> _ {
//~^ WARN type parameter `a` should have an upper camel case name
//~| ERROR the placeholder `_` is not allowed within types on item signatures for return types
async || {}
}
fn main() {}
@@ -0,0 +1,26 @@
warning: type parameter `a` should have an upper camel case name
--> $DIR/ice-async-closure-variance-issue-148488.rs:6:8
|
LL | fn ord<a>() -> _ {
| ^ help: convert the identifier to upper camel case: `A`
|
= note: `#[warn(non_camel_case_types)]` (part of `#[warn(nonstandard_style)]`) on by default
error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
--> $DIR/ice-async-closure-variance-issue-148488.rs:6:16
|
LL | fn ord<a>() -> _ {
| ^ not allowed in type signatures
error[E0392]: lifetime parameter `'g` is never used
--> $DIR/ice-async-closure-variance-issue-148488.rs:3:10
|
LL | struct T<'g>();
| ^^ unused lifetime parameter
|
= help: consider removing `'g`, referring to it in a field, or using a marker such as `PhantomData`
error: aborting due to 2 previous errors; 1 warning emitted
Some errors have detailed explanations: E0121, E0392.
For more information about an error, try `rustc --explain E0121`.
@@ -0,0 +1,13 @@
//@ edition: 2021
// Regression test for #148542
// Ensure we don't ICE with "Invalid `ConstKind` for `const_to_pat`: {const error}"
fn foo() where &str:, {
//~^ ERROR `&` without an explicit lifetime name cannot be used here
match 42_u8 {
-10.. => {}
}
}
fn main() {}
@@ -0,0 +1,14 @@
error[E0637]: `&` without an explicit lifetime name cannot be used here
--> $DIR/const-error-ice-issue-148542.rs:6:16
|
LL | fn foo() where &str:, {
| ^ explicit lifetime name needed here
|
help: consider introducing a higher-ranked lifetime here
|
LL | fn foo() where for<'a> &'a str:, {
| +++++++ ++
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0637`.
@@ -0,0 +1,36 @@
//@ compile-flags: -Znext-solver
//@ check-pass
// Regression test for trait-system-refactor-initiative#244
trait Trait {
type Assoc;
}
// We have param env candidate for the trait goal but not the projection.
// Under such circumstance, consider object candidate if the self_ty is trait object.
fn foo<T>(x: <dyn Trait<Assoc = T> as Trait>::Assoc) -> T
where
dyn Trait<Assoc = T>: Trait,
{
x
}
trait Id<'a> {
type This: ?Sized;
}
impl<T: ?Sized> Id<'_> for T {
type This = T;
}
// Ensure that we properly normalize alias self_ty before evaluating the goal.
fn alias_foo<T>(x: for<'a> fn(
<<dyn Trait<Assoc = T> as Id<'a>>::This as Trait>::Assoc
)) -> fn(T)
where
dyn Trait<Assoc = T>: Trait,
{
x
}
fn main() {}