Auto merge of #125552 - matthiaskrgr:rollup-f1yybpn, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #121377 (Stabilize `LazyCell` and `LazyLock`) - #122986 (Fix c_char on AIX) - #123803 (Fix `VecDeque::shrink_to` UB when `handle_alloc_error` unwinds.) - #124080 (Some unstable changes to where opaque types get defined) - #124667 (Stabilize `div_duration`) - #125472 (tidy: validate LLVM component names in tests) - #125523 (Exit the process a short time after entering our ctrl-c handler) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
0a59f11362
76 changed files with 589 additions and 221 deletions
|
@ -309,7 +309,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
|
|||
}
|
||||
|
||||
if let ConstContext::Static(_) = ccx.const_kind() {
|
||||
err.note("consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell");
|
||||
err.note("consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`");
|
||||
}
|
||||
|
||||
err
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#![feature(extend_one)]
|
||||
#![feature(hash_raw_entry)]
|
||||
#![feature(hasher_prefixfree_extras)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(lint_reasons)]
|
||||
#![feature(macro_metavar_expr)]
|
||||
#![feature(map_try_insert)]
|
||||
|
|
|
@ -57,7 +57,7 @@ use std::process::{self, Command, Stdio};
|
|||
use std::str;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{Arc, OnceLock};
|
||||
use std::time::{Instant, SystemTime};
|
||||
use std::time::{Duration, Instant, SystemTime};
|
||||
use time::OffsetDateTime;
|
||||
use tracing::trace;
|
||||
|
||||
|
@ -1502,14 +1502,13 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) {
|
|||
pub fn install_ctrlc_handler() {
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
ctrlc::set_handler(move || {
|
||||
// Indicate that we have been signaled to stop. If we were already signaled, exit
|
||||
// immediately. In our interpreter loop we try to consult this value often, but if for
|
||||
// whatever reason we don't get to that check or the cleanup we do upon finding that
|
||||
// this bool has become true takes a long time, the exit here will promptly exit the
|
||||
// process on the second Ctrl-C.
|
||||
if CTRL_C_RECEIVED.swap(true, Ordering::Relaxed) {
|
||||
std::process::exit(1);
|
||||
}
|
||||
// Indicate that we have been signaled to stop, then give the rest of the compiler a bit of
|
||||
// time to check CTRL_C_RECEIVED and run its own shutdown logic, but after a short amount
|
||||
// of time exit the process. This sleep+exit ensures that even if nobody is checking
|
||||
// CTRL_C_RECEIVED, the compiler exits reasonably promptly.
|
||||
CTRL_C_RECEIVED.store(true, Ordering::Relaxed);
|
||||
std::thread::sleep(Duration::from_millis(100));
|
||||
std::process::exit(1);
|
||||
})
|
||||
.expect("Unable to install ctrlc handler");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#![doc(rust_logo)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
#![allow(internal_features)]
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#![allow(internal_features)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![doc(rust_logo)]
|
||||
#![feature(lazy_cell)]
|
||||
|
||||
mod accepted;
|
||||
mod builtin_attrs;
|
||||
|
|
|
@ -68,7 +68,6 @@ This API is completely unstable and subject to change.
|
|||
#![feature(iter_intersperse)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(slice_partition_dedup)]
|
||||
#![feature(try_blocks)]
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#![feature(decl_macro)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(thread_spawn_unchecked)]
|
||||
#![feature(try_blocks)]
|
||||
|
|
|
@ -1316,10 +1316,8 @@ declare_lint! {
|
|||
/// * If you are trying to perform a one-time initialization of a global:
|
||||
/// * If the value can be computed at compile-time, consider using
|
||||
/// const-compatible values (see [Constant Evaluation]).
|
||||
/// * For more complex single-initialization cases, consider using a
|
||||
/// third-party crate, such as [`lazy_static`] or [`once_cell`].
|
||||
/// * If you are using the [nightly channel], consider the new
|
||||
/// [`lazy`] module in the standard library.
|
||||
/// * For more complex single-initialization cases, consider using
|
||||
/// [`std::sync::LazyLock`].
|
||||
/// * If you truly need a mutable global, consider using a [`static`],
|
||||
/// which has a variety of options:
|
||||
/// * Simple data types can be directly defined and mutated with an
|
||||
|
@ -1334,9 +1332,7 @@ declare_lint! {
|
|||
/// [Constant Evaluation]: https://doc.rust-lang.org/reference/const_eval.html
|
||||
/// [`static`]: https://doc.rust-lang.org/reference/items/static-items.html
|
||||
/// [mutable `static`]: https://doc.rust-lang.org/reference/items/static-items.html#mutable-statics
|
||||
/// [`lazy`]: https://doc.rust-lang.org/nightly/std/lazy/index.html
|
||||
/// [`lazy_static`]: https://crates.io/crates/lazy_static
|
||||
/// [`once_cell`]: https://crates.io/crates/once_cell
|
||||
/// [`std::sync::LazyLock`]: https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html
|
||||
/// [`atomic`]: https://doc.rust-lang.org/std/sync/atomic/index.html
|
||||
/// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
|
||||
pub CONST_ITEM_MUTATION,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#![feature(let_chains)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(option_get_or_insert_default)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(map_many_mut)]
|
||||
|
|
|
@ -2539,7 +2539,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
let InferOk { obligations, .. } = self
|
||||
.infcx
|
||||
.at(&cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref)
|
||||
.eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref)
|
||||
.map_err(|e| {
|
||||
debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
|
||||
})?;
|
||||
|
@ -2594,7 +2594,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
self.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(
|
||||
DefineOpaqueTypes::No,
|
||||
DefineOpaqueTypes::Yes,
|
||||
upcast_principal.map_bound(|trait_ref| {
|
||||
ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
|
||||
}),
|
||||
|
@ -2631,7 +2631,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
|
|||
nested.extend(
|
||||
self.infcx
|
||||
.at(&obligation.cause, obligation.param_env)
|
||||
.eq(DefineOpaqueTypes::No, source_projection, target_projection)
|
||||
.eq(DefineOpaqueTypes::Yes, source_projection, target_projection)
|
||||
.map_err(|_| SelectionError::Unimplemented)?
|
||||
.into_obligations(),
|
||||
);
|
||||
|
|
|
@ -20,6 +20,10 @@ rand_xorshift = "0.3.0"
|
|||
name = "alloctests"
|
||||
path = "tests/lib.rs"
|
||||
|
||||
[[test]]
|
||||
name = "vec_deque_alloc_error"
|
||||
path = "tests/vec_deque_alloc_error.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "allocbenches"
|
||||
path = "benches/lib.rs"
|
||||
|
|
|
@ -982,6 +982,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
// `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can
|
||||
// overflow.
|
||||
let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
|
||||
// Used in the drop guard below.
|
||||
let old_head = self.head;
|
||||
|
||||
if self.len == 0 {
|
||||
self.head = 0;
|
||||
|
@ -1034,12 +1036,74 @@ impl<T, A: Allocator> VecDeque<T, A> {
|
|||
}
|
||||
self.head = new_head;
|
||||
}
|
||||
self.buf.shrink_to_fit(target_cap);
|
||||
|
||||
struct Guard<'a, T, A: Allocator> {
|
||||
deque: &'a mut VecDeque<T, A>,
|
||||
old_head: usize,
|
||||
target_cap: usize,
|
||||
}
|
||||
|
||||
impl<T, A: Allocator> Drop for Guard<'_, T, A> {
|
||||
#[cold]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// SAFETY: This is only called if `buf.shrink_to_fit` unwinds,
|
||||
// which is the only time it's safe to call `abort_shrink`.
|
||||
self.deque.abort_shrink(self.old_head, self.target_cap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let guard = Guard { deque: self, old_head, target_cap };
|
||||
|
||||
guard.deque.buf.shrink_to_fit(target_cap);
|
||||
|
||||
// Don't drop the guard if we didn't unwind.
|
||||
mem::forget(guard);
|
||||
|
||||
debug_assert!(self.head < self.capacity() || self.capacity() == 0);
|
||||
debug_assert!(self.len <= self.capacity());
|
||||
}
|
||||
|
||||
/// Reverts the deque back into a consistent state in case `shrink_to` failed.
|
||||
/// This is necessary to prevent UB if the backing allocator returns an error
|
||||
/// from `shrink` and `handle_alloc_error` subsequently unwinds (see #123369).
|
||||
///
|
||||
/// `old_head` refers to the head index before `shrink_to` was called. `target_cap`
|
||||
/// is the capacity that it was trying to shrink to.
|
||||
unsafe fn abort_shrink(&mut self, old_head: usize, target_cap: usize) {
|
||||
// Moral equivalent of self.head + self.len <= target_cap. Won't overflow
|
||||
// because `self.len <= target_cap`.
|
||||
if self.head <= target_cap - self.len {
|
||||
// The deque's buffer is contiguous, so no need to copy anything around.
|
||||
return;
|
||||
}
|
||||
|
||||
// `shrink_to` already copied the head to fit into the new capacity, so this won't overflow.
|
||||
let head_len = target_cap - self.head;
|
||||
// `self.head > target_cap - self.len` => `self.len > target_cap - self.head =: head_len` so this must be positive.
|
||||
let tail_len = self.len - head_len;
|
||||
|
||||
if tail_len <= cmp::min(head_len, self.capacity() - target_cap) {
|
||||
// There's enough spare capacity to copy the tail to the back (because `tail_len < self.capacity() - target_cap`),
|
||||
// and copying the tail should be cheaper than copying the head (because `tail_len <= head_len`).
|
||||
|
||||
unsafe {
|
||||
// The old tail and the new tail can't overlap because the head slice lies between them. The
|
||||
// head slice ends at `target_cap`, so that's where we copy to.
|
||||
self.copy_nonoverlapping(0, target_cap, tail_len);
|
||||
}
|
||||
} else {
|
||||
// Either there's not enough spare capacity to make the deque contiguous, or the head is shorter than the tail
|
||||
// (and therefore hopefully cheaper to copy).
|
||||
unsafe {
|
||||
// The old and the new head slice can overlap, so we can't use `copy_nonoverlapping` here.
|
||||
self.copy(self.head, old_head, head_len);
|
||||
self.head = old_head;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Shortens the deque, keeping the first `len` elements and dropping
|
||||
/// the rest.
|
||||
///
|
||||
|
|
49
library/alloc/tests/vec_deque_alloc_error.rs
Normal file
49
library/alloc/tests/vec_deque_alloc_error.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
#![feature(alloc_error_hook, allocator_api)]
|
||||
|
||||
use std::{
|
||||
alloc::{set_alloc_error_hook, AllocError, Allocator, Layout, System},
|
||||
collections::VecDeque,
|
||||
panic::{catch_unwind, AssertUnwindSafe},
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_shrink_to_unwind() {
|
||||
// This tests that `shrink_to` leaves the deque in a consistent state when
|
||||
// the call to `RawVec::shrink_to_fit` unwinds. The code is adapted from #123369
|
||||
// but changed to hopefully not have any UB even if the test fails.
|
||||
|
||||
struct BadAlloc;
|
||||
|
||||
unsafe impl Allocator for BadAlloc {
|
||||
fn allocate(&self, l: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||
// We allocate zeroed here so that the whole buffer of the deque
|
||||
// is always initialized. That way, even if the deque is left in
|
||||
// an inconsistent state, no uninitialized memory should be accessed.
|
||||
System.allocate_zeroed(l)
|
||||
}
|
||||
|
||||
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
|
||||
unsafe { System.deallocate(ptr, layout) }
|
||||
}
|
||||
|
||||
unsafe fn shrink(
|
||||
&self,
|
||||
_ptr: NonNull<u8>,
|
||||
_old_layout: Layout,
|
||||
_new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
Err(AllocError)
|
||||
}
|
||||
}
|
||||
|
||||
set_alloc_error_hook(|_| panic!("alloc error"));
|
||||
|
||||
let mut v = VecDeque::with_capacity_in(15, BadAlloc);
|
||||
v.push_back(1);
|
||||
v.push_front(2);
|
||||
// This should unwind because it calls `BadAlloc::shrink` and then `handle_alloc_error` which unwinds.
|
||||
assert!(catch_unwind(AssertUnwindSafe(|| v.shrink_to_fit())).is_err());
|
||||
// This should only pass if the deque is left in a consistent state.
|
||||
assert_eq!(v, [2, 1]);
|
||||
}
|
|
@ -245,7 +245,7 @@ use crate::ptr::{self, NonNull};
|
|||
mod lazy;
|
||||
mod once;
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub use lazy::LazyCell;
|
||||
#[stable(feature = "once_cell", since = "1.70.0")]
|
||||
pub use once::OnceCell;
|
||||
|
|
|
@ -18,8 +18,6 @@ enum State<T, F> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
///
|
||||
/// use std::cell::LazyCell;
|
||||
///
|
||||
/// let lazy: LazyCell<i32> = LazyCell::new(|| {
|
||||
|
@ -36,7 +34,7 @@ enum State<T, F> {
|
|||
/// // 92
|
||||
/// // 92
|
||||
/// ```
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub struct LazyCell<T, F = fn() -> T> {
|
||||
state: UnsafeCell<State<T, F>>,
|
||||
}
|
||||
|
@ -47,8 +45,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
///
|
||||
/// use std::cell::LazyCell;
|
||||
///
|
||||
/// let hello = "Hello, World!".to_string();
|
||||
|
@ -58,7 +54,8 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
|
|||
/// assert_eq!(&*lazy, "HELLO, WORLD!");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn new(f: F) -> LazyCell<T, F> {
|
||||
LazyCell { state: UnsafeCell::new(State::Uninit(f)) }
|
||||
}
|
||||
|
@ -70,7 +67,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
/// #![feature(lazy_cell_consume)]
|
||||
///
|
||||
/// use std::cell::LazyCell;
|
||||
|
@ -99,8 +95,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
///
|
||||
/// use std::cell::LazyCell;
|
||||
///
|
||||
/// let lazy = LazyCell::new(|| 92);
|
||||
|
@ -109,7 +103,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
|
|||
/// assert_eq!(&*lazy, &92);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub fn force(this: &LazyCell<T, F>) -> &T {
|
||||
// SAFETY:
|
||||
// This invalidates any mutable references to the data. The resulting
|
||||
|
@ -173,7 +167,7 @@ impl<T, F> LazyCell<T, F> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
|
||||
type Target = T;
|
||||
#[inline]
|
||||
|
@ -182,7 +176,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: Default> Default for LazyCell<T> {
|
||||
/// Creates a new lazy value using `Default` as the initializing function.
|
||||
#[inline]
|
||||
|
@ -191,7 +185,7 @@ impl<T: Default> Default for LazyCell<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut d = f.debug_tuple("LazyCell");
|
||||
|
|
|
@ -133,7 +133,8 @@ mod c_char_definition {
|
|||
any(target_arch = "aarch64", target_arch = "riscv64")
|
||||
),
|
||||
all(target_os = "nto", target_arch = "aarch64"),
|
||||
target_os = "horizon"
|
||||
target_os = "horizon",
|
||||
target_os = "aix",
|
||||
))] {
|
||||
pub type c_char = u8;
|
||||
} else {
|
||||
|
|
|
@ -1084,40 +1084,42 @@ impl Duration {
|
|||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// #![feature(div_duration)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let dur1 = Duration::new(2, 700_000_000);
|
||||
/// let dur2 = Duration::new(5, 400_000_000);
|
||||
/// assert_eq!(dur1.div_duration_f64(dur2), 0.5);
|
||||
/// ```
|
||||
#[unstable(feature = "div_duration", issue = "63139")]
|
||||
#[stable(feature = "div_duration", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
|
||||
pub const fn div_duration_f64(self, rhs: Duration) -> f64 {
|
||||
self.as_secs_f64() / rhs.as_secs_f64()
|
||||
let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64);
|
||||
let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64);
|
||||
self_nanos / rhs_nanos
|
||||
}
|
||||
|
||||
/// Divide `Duration` by `Duration` and return `f32`.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// #![feature(div_duration)]
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let dur1 = Duration::new(2, 700_000_000);
|
||||
/// let dur2 = Duration::new(5, 400_000_000);
|
||||
/// assert_eq!(dur1.div_duration_f32(dur2), 0.5);
|
||||
/// ```
|
||||
#[unstable(feature = "div_duration", issue = "63139")]
|
||||
#[stable(feature = "div_duration", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
|
||||
pub const fn div_duration_f32(self, rhs: Duration) -> f32 {
|
||||
self.as_secs_f32() / rhs.as_secs_f32()
|
||||
let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32);
|
||||
let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32);
|
||||
self_nanos / rhs_nanos
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#![feature(core_private_bignum)]
|
||||
#![feature(core_private_diy_float)]
|
||||
#![feature(dec2flt)]
|
||||
#![feature(div_duration)]
|
||||
#![feature(duration_abs_diff)]
|
||||
#![feature(duration_consts_float)]
|
||||
#![feature(duration_constants)]
|
||||
|
@ -96,7 +95,6 @@
|
|||
#![feature(pointer_is_aligned_to)]
|
||||
#![feature(portable_simd)]
|
||||
#![feature(ptr_metadata)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
#![feature(const_option)]
|
||||
#![feature(const_option_ext)]
|
||||
|
|
|
@ -395,7 +395,6 @@
|
|||
#![feature(edition_panic)]
|
||||
#![feature(format_args_nl)]
|
||||
#![feature(get_many_mut)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(log_syntax)]
|
||||
#![feature(test)]
|
||||
#![feature(trace_macros)]
|
||||
|
|
|
@ -31,8 +31,6 @@ union Data<T, F> {
|
|||
/// Initialize static variables with `LazyLock`.
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
///
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// use std::sync::LazyLock;
|
||||
|
@ -61,8 +59,6 @@ union Data<T, F> {
|
|||
/// ```
|
||||
/// Initialize fields with `LazyLock`.
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
///
|
||||
/// use std::sync::LazyLock;
|
||||
///
|
||||
/// #[derive(Debug)]
|
||||
|
@ -76,8 +72,7 @@ union Data<T, F> {
|
|||
/// println!("{}", *data.number);
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub struct LazyLock<T, F = fn() -> T> {
|
||||
once: Once,
|
||||
data: UnsafeCell<Data<T, F>>,
|
||||
|
@ -85,8 +80,21 @@ pub struct LazyLock<T, F = fn() -> T> {
|
|||
|
||||
impl<T, F: FnOnce() -> T> LazyLock<T, F> {
|
||||
/// Creates a new lazy value with the given initializing function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::sync::LazyLock;
|
||||
///
|
||||
/// let hello = "Hello, World!".to_string();
|
||||
///
|
||||
/// let lazy = LazyLock::new(|| hello.to_uppercase());
|
||||
///
|
||||
/// assert_eq!(&*lazy, "HELLO, WORLD!");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_const_stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub const fn new(f: F) -> LazyLock<T, F> {
|
||||
LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
|
||||
}
|
||||
|
@ -107,7 +115,6 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
/// #![feature(lazy_cell_consume)]
|
||||
///
|
||||
/// use std::sync::LazyLock;
|
||||
|
@ -145,8 +152,6 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(lazy_cell)]
|
||||
///
|
||||
/// use std::sync::LazyLock;
|
||||
///
|
||||
/// let lazy = LazyLock::new(|| 92);
|
||||
|
@ -155,7 +160,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
|
|||
/// assert_eq!(&*lazy, &92);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub fn force(this: &LazyLock<T, F>) -> &T {
|
||||
this.once.call_once(|| {
|
||||
// SAFETY: `call_once` only runs this closure once, ever.
|
||||
|
@ -191,7 +196,7 @@ impl<T, F> LazyLock<T, F> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T, F> Drop for LazyLock<T, F> {
|
||||
fn drop(&mut self) {
|
||||
match self.once.state() {
|
||||
|
@ -204,7 +209,7 @@ impl<T, F> Drop for LazyLock<T, F> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
|
||||
type Target = T;
|
||||
|
||||
|
@ -219,7 +224,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: Default> Default for LazyLock<T> {
|
||||
/// Creates a new lazy value using `Default` as the initializing function.
|
||||
#[inline]
|
||||
|
@ -228,7 +233,7 @@ impl<T: Default> Default for LazyLock<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut d = f.debug_tuple("LazyLock");
|
||||
|
@ -242,13 +247,13 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
|
|||
|
||||
// We never create a `&F` from a `&LazyLock<T, F>` so it is fine
|
||||
// to not impl `Sync` for `F`.
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
|
||||
// auto-derived `Send` impl is OK.
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
@ -179,7 +179,7 @@ pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
#[unstable(feature = "lazy_cell", issue = "109736")]
|
||||
#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
|
||||
pub use self::lazy_lock::LazyLock;
|
||||
#[stable(feature = "once_cell", since = "1.70.0")]
|
||||
pub use self::once_lock::OnceLock;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#![feature(if_let_guard)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
#![feature(round_char_boundary)]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#![feature(lazy_cell)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(rustc_private)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#![allow(rustc::untranslatable_diagnostic)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(lazy_cell)]
|
||||
#![feature(lint_reasons)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
// warn on lints, that are included in `rust-lang/rust`s bootstrap
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#![feature(lazy_cell)]
|
||||
#![feature(is_sorted)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//!
|
||||
//! See [Eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) for context
|
||||
|
||||
#![feature(lazy_cell)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#![feature(lazy_cell)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#![feature(lazy_cell)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use test_utils::{CARGO_CLIPPY_PATH, IS_RUSTC_TEST_SUITE};
|
||||
|
|
|
@ -10,6 +10,25 @@ use crate::walk::filter_not_rust;
|
|||
const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:";
|
||||
const COMPILE_FLAGS_HEADER: &str = "compile-flags:";
|
||||
|
||||
const KNOWN_LLVM_COMPONENTS: &[&str] = &[
|
||||
"aarch64",
|
||||
"arm",
|
||||
"avr",
|
||||
"bpf",
|
||||
"hexagon",
|
||||
"loongarch",
|
||||
"m68k",
|
||||
"mips",
|
||||
"msp430",
|
||||
"nvptx",
|
||||
"powerpc",
|
||||
"riscv",
|
||||
"sparc",
|
||||
"systemz",
|
||||
"webassembly",
|
||||
"x86",
|
||||
];
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
struct RevisionInfo<'a> {
|
||||
target_arch: Option<&'a str>,
|
||||
|
@ -68,6 +87,17 @@ pub fn check(path: &Path, bad: &mut bool) {
|
|||
// gathered.
|
||||
}
|
||||
}
|
||||
if let Some(llvm_components) = llvm_components {
|
||||
for component in llvm_components {
|
||||
if !KNOWN_LLVM_COMPONENTS.contains(component) {
|
||||
eprintln!(
|
||||
"{}: revision {} specifies unknown LLVM component `{}`",
|
||||
file, rev, component
|
||||
);
|
||||
*bad = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ LL | static settings_dir: String = format!("");
|
|||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
= note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0507]: cannot move out of static item `settings_dir`
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
|
||||
error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
|
||||
--> $DIR/issue-16538.rs:11:22
|
||||
|
|
|
@ -13,7 +13,7 @@ LL | invalid();
|
|||
| ^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
|
||||
error[E0015]: cannot call non-const fn `invalid` in statics
|
||||
--> $DIR/issue-32829-2.rs:54:9
|
||||
|
@ -22,7 +22,7 @@ LL | invalid();
|
|||
| ^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | static foo: Foo = bar();
|
|||
| ^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ fn sum_to(n: u32) -> impl Foo {
|
|||
0
|
||||
} else {
|
||||
n + sum_to(n - 1)
|
||||
//~^ ERROR cannot add `impl Foo` to `u32`
|
||||
//~^ ERROR cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,12 +32,15 @@ trait Leak: Sized {
|
|||
}
|
||||
impl<T> Leak for T {
|
||||
default type T = ();
|
||||
default fn leak(self) -> Self::T { panic!() }
|
||||
default fn leak(self) -> Self::T {
|
||||
panic!()
|
||||
}
|
||||
}
|
||||
impl Leak for i32 {
|
||||
type T = i32;
|
||||
fn leak(self) -> i32 { self }
|
||||
fn leak(self) -> i32 {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
}
|
||||
fn main() {}
|
||||
|
|
|
@ -22,20 +22,13 @@ help: change the type of the numeric literal from `u32` to `i32`
|
|||
LL | 0_i32
|
||||
| ~~~
|
||||
|
||||
error[E0277]: cannot add `impl Foo` to `u32`
|
||||
error[E0284]: type annotations needed: cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
|
||||
--> $DIR/equality.rs:24:11
|
||||
|
|
||||
LL | n + sum_to(n - 1)
|
||||
| ^ no implementation for `u32 + impl Foo`
|
||||
|
|
||||
= help: the trait `Add<impl Foo>` is not implemented for `u32`
|
||||
= help: the following other types implement trait `Add<Rhs>`:
|
||||
<&'a u32 as Add<u32>>
|
||||
<&u32 as Add<&u32>>
|
||||
<u32 as Add<&u32>>
|
||||
<u32 as Add>
|
||||
| ^ cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
|
||||
|
||||
error: aborting due to 2 previous errors; 1 warning emitted
|
||||
|
||||
Some errors have detailed explanations: E0277, E0308.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
||||
Some errors have detailed explanations: E0284, E0308.
|
||||
For more information about an error, try `rustc --explain E0284`.
|
||||
|
|
|
@ -46,19 +46,23 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
|
|||
--> $DIR/nested_impl_trait.rs:6:46
|
||||
|
|
||||
LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into<u32>`
|
||||
|
|
||||
= help: the trait `Into<U>` is implemented for `T`
|
||||
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | fn bad_in_ret_position(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
|
||||
| +++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
|
||||
--> $DIR/nested_impl_trait.rs:19:34
|
||||
|
|
||||
LL | fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
|
||||
| ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into<u32>`
|
||||
|
|
||||
= help: the trait `Into<U>` is implemented for `T`
|
||||
= note: required for `impl Into<u32>` to implement `Into<impl Debug>`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
LL | fn bad(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
|
||||
| +++++++++++++++++
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ impl PartialEq<(Bar, i32)> for Bar {
|
|||
}
|
||||
|
||||
fn foo() -> Foo {
|
||||
//~^ ERROR can't compare `Bar` with `(Foo, i32)`
|
||||
//~^ ERROR overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>`
|
||||
Bar
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
error[E0277]: can't compare `Bar` with `(Foo, i32)`
|
||||
error[E0275]: overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>`
|
||||
--> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13
|
||||
|
|
||||
LL | fn foo() -> Foo {
|
||||
| ^^^ no implementation for `Bar == (Foo, i32)`
|
||||
LL |
|
||||
LL | Bar
|
||||
| --- return type was inferred to be `Bar` here
|
||||
|
|
||||
= help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar`
|
||||
= help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar`
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
14
tests/ui/impl-trait/unsize_adt.rs
Normal file
14
tests/ui/impl-trait/unsize_adt.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
//! Test that we do not allow unsizing `Foo<[Opaque; N]>` to `Foo<[Concrete]>`.
|
||||
|
||||
struct Foo<T: ?Sized>(T);
|
||||
|
||||
fn hello() -> Foo<[impl Sized; 2]> {
|
||||
if false {
|
||||
let x = hello();
|
||||
let _: &Foo<[i32]> = &x;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {}
|
17
tests/ui/impl-trait/unsize_adt.stderr
Normal file
17
tests/ui/impl-trait/unsize_adt.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/unsize_adt.rs:8:30
|
||||
|
|
||||
LL | fn hello() -> Foo<[impl Sized; 2]> {
|
||||
| ---------- the found opaque type
|
||||
...
|
||||
LL | let _: &Foo<[i32]> = &x;
|
||||
| ----------- ^^ expected `&Foo<[i32]>`, found `&Foo<[impl Sized; 2]>`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&Foo<[i32]>`
|
||||
found reference `&Foo<[impl Sized; 2]>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
12
tests/ui/impl-trait/unsize_slice.rs
Normal file
12
tests/ui/impl-trait/unsize_slice.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
//! Test that we do not allow unsizing `[Opaque; N]` to `[Concrete]`.
|
||||
|
||||
fn hello() -> [impl Sized; 2] {
|
||||
if false {
|
||||
let x = hello();
|
||||
let _: &[i32] = &x;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {}
|
17
tests/ui/impl-trait/unsize_slice.stderr
Normal file
17
tests/ui/impl-trait/unsize_slice.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/unsize_slice.rs:6:25
|
||||
|
|
||||
LL | fn hello() -> [impl Sized; 2] {
|
||||
| ---------- the found opaque type
|
||||
...
|
||||
LL | let _: &[i32] = &x;
|
||||
| ------ ^^ expected `&[i32]`, found `&[impl Sized; 2]`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&[i32]`
|
||||
found reference `&[impl Sized; 2]`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
14
tests/ui/impl-trait/unsize_tuple.rs
Normal file
14
tests/ui/impl-trait/unsize_tuple.rs
Normal file
|
@ -0,0 +1,14 @@
|
|||
//! Test that we do not allow unsizing `([Opaque; N],)` to `([Concrete],)`.
|
||||
|
||||
#![feature(unsized_tuple_coercion)]
|
||||
|
||||
fn hello() -> ([impl Sized; 2],) {
|
||||
if false {
|
||||
let x = hello();
|
||||
let _: &([i32],) = &x;
|
||||
//~^ ERROR: mismatched types
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {}
|
17
tests/ui/impl-trait/unsize_tuple.stderr
Normal file
17
tests/ui/impl-trait/unsize_tuple.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/unsize_tuple.rs:8:28
|
||||
|
|
||||
LL | fn hello() -> ([impl Sized; 2],) {
|
||||
| ---------- the found opaque type
|
||||
...
|
||||
LL | let _: &([i32],) = &x;
|
||||
| --------- ^^ expected `&([i32],)`, found `&([impl Sized; 2],)`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: expected reference `&([i32],)`
|
||||
found reference `&([impl Sized; 2],)`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -16,7 +16,7 @@ note: impl defined here, but it is not `const`
|
|||
LL | impl Deref for A {
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
|
||||
LL + #![feature(const_trait_impl)]
|
||||
|
|
|
@ -18,7 +18,7 @@ LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0));
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#![feature(lazy_cell)]
|
||||
#![deny(suspicious_double_ref_op, noop_method_call)]
|
||||
|
||||
use std::borrow::Borrow;
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
error: using `.clone()` on a double reference, which returns `&Vec<i32>` instead of cloning the inner type
|
||||
--> $DIR/suspicious-double-ref-op.rs:15:23
|
||||
--> $DIR/suspicious-double-ref-op.rs:14:23
|
||||
|
|
||||
LL | let z: &Vec<_> = y.clone();
|
||||
| ^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/suspicious-double-ref-op.rs:2:9
|
||||
--> $DIR/suspicious-double-ref-op.rs:1:9
|
||||
|
|
||||
LL | #![deny(suspicious_double_ref_op, noop_method_call)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: using `.clone()` on a double reference, which returns `&CloneType<u32>` instead of cloning the inner type
|
||||
--> $DIR/suspicious-double-ref-op.rs:33:63
|
||||
--> $DIR/suspicious-double-ref-op.rs:32:63
|
||||
|
|
||||
LL | let clone_type_ref_clone: &CloneType<u32> = clone_type_ref.clone();
|
||||
| ^^^^^^^^
|
||||
|
||||
error: using `.deref()` on a double reference, which returns `&PlainType<u32>` instead of dereferencing the inner type
|
||||
--> $DIR/suspicious-double-ref-op.rs:37:63
|
||||
--> $DIR/suspicious-double-ref-op.rs:36:63
|
||||
|
|
||||
LL | let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref();
|
||||
| ^^^^^^^^
|
||||
|
||||
error: using `.clone()` on a double reference, which returns `&str` instead of cloning the inner type
|
||||
--> $DIR/suspicious-double-ref-op.rs:41:44
|
||||
--> $DIR/suspicious-double-ref-op.rs:40:44
|
||||
|
|
||||
LL | let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead
|
||||
| ^^^^^^^^
|
||||
|
|
|
@ -352,7 +352,7 @@ LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]);
|
|||
| ^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
|
||||
LL + #![feature(const_trait_impl)]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//@ check-pass
|
||||
|
||||
#![feature(const_trait_impl, lazy_cell)]
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | static mut a: Box<isize> = Box::new(3);
|
|||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ LL | static a: [isize; 2] = [foo(); 2];
|
|||
| ^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
|
|||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0015]: cannot call non-const fn `<str as ToString>::to_string` in statics
|
||||
|
@ -36,7 +36,7 @@ LL | field2: SafeEnum::Variant4("str".to_string()),
|
|||
| ^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
|
||||
|
|
||||
LL + #![feature(const_trait_impl)]
|
||||
|
@ -57,7 +57,7 @@ LL | vec![MyOwned],
|
|||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0010]: allocations are not allowed in statics
|
||||
|
@ -75,7 +75,7 @@ LL | vec![MyOwned],
|
|||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0010]: allocations are not allowed in statics
|
||||
|
@ -93,7 +93,7 @@ LL | &vec![MyOwned],
|
|||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0010]: allocations are not allowed in statics
|
||||
|
@ -111,7 +111,7 @@ LL | &vec![MyOwned],
|
|||
| ^^^^^^^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0010]: allocations are not allowed in statics
|
||||
|
@ -129,7 +129,7 @@ LL | static STATIC19: Vec<isize> = vec![3];
|
|||
| ^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0010]: allocations are not allowed in statics
|
||||
|
@ -147,7 +147,7 @@ LL | static x: Vec<isize> = vec![3];
|
|||
| ^^^^^^^
|
||||
|
|
||||
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
|
||||
= note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
|
||||
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
|
||||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error[E0507]: cannot move out of static item `x`
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[next] failure-status: 101
|
||||
//@[next] known-bug: unknown
|
||||
//@[next] normalize-stderr-test "note: .*\n\n" -> ""
|
||||
//@[next] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
|
||||
//@[next] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
|
||||
//@[next] normalize-stderr-test "delayed at .*" -> ""
|
||||
//@[next] rustc-env:RUST_BACKTRACE=0
|
||||
//@ check-pass
|
||||
|
||||
#![feature(trait_upcasting)]
|
||||
|
||||
trait Super {
|
||||
type Assoc;
|
||||
}
|
||||
|
||||
trait Sub: Super {}
|
||||
|
||||
impl<T: ?Sized> Super for T {
|
||||
type Assoc = i32;
|
||||
}
|
||||
|
||||
fn illegal(x: &dyn Sub<Assoc = i32>) -> &dyn Super<Assoc = impl Sized> {
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -11,6 +11,10 @@ fn test_correct(x: &dyn Foo<'static>) {
|
|||
let _ = x as &dyn Bar<'static, 'static>;
|
||||
}
|
||||
|
||||
fn test_correct2<'a>(x: &dyn Foo<'a>) {
|
||||
let _ = x as &dyn Bar<'_, '_>;
|
||||
}
|
||||
|
||||
fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
|
||||
let _ = x as &dyn Bar<'static, 'a>; // Error
|
||||
//~^ ERROR lifetime may not live long enough
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
error: lifetime may not live long enough
|
||||
--> $DIR/type-checking-test-4.rs:15:13
|
||||
--> $DIR/type-checking-test-4.rs:19:13
|
||||
|
|
||||
LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
|
||||
| -- lifetime `'a` defined here
|
||||
|
@ -7,7 +7,7 @@ LL | let _ = x as &dyn Bar<'static, 'a>; // Error
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-checking-test-4.rs:20:13
|
||||
--> $DIR/type-checking-test-4.rs:24:13
|
||||
|
|
||||
LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
|
||||
| -- lifetime `'a` defined here
|
||||
|
@ -15,7 +15,7 @@ LL | let _ = x as &dyn Bar<'a, 'static>; // Error
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-checking-test-4.rs:26:5
|
||||
--> $DIR/type-checking-test-4.rs:30:5
|
||||
|
|
||||
LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| -- lifetime `'a` defined here
|
||||
|
@ -24,7 +24,7 @@ LL | y.get_b() // ERROR
|
|||
| ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-checking-test-4.rs:31:5
|
||||
--> $DIR/type-checking-test-4.rs:35:5
|
||||
|
|
||||
LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| -- lifetime `'a` defined here
|
||||
|
@ -32,7 +32,7 @@ LL | <_ as Bar>::get_b(x) // ERROR
|
|||
| ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-checking-test-4.rs:36:5
|
||||
--> $DIR/type-checking-test-4.rs:40:5
|
||||
|
|
||||
LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| -- lifetime `'a` defined here
|
||||
|
@ -40,7 +40,7 @@ LL | <_ as Bar<'_, '_>>::get_b(x) // ERROR
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
|
||||
|
||||
error: lifetime may not live long enough
|
||||
--> $DIR/type-checking-test-4.rs:44:5
|
||||
--> $DIR/type-checking-test-4.rs:48:5
|
||||
|
|
||||
LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
|
||||
| -- lifetime `'a` defined here
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
#![feature(trait_upcasting, type_alias_impl_trait)]
|
||||
|
||||
//@ check-pass
|
||||
|
||||
type Tait = impl Sized;
|
||||
|
||||
trait Foo<'a>: Bar<'a, 'a, Tait> {}
|
||||
trait Bar<'a, 'b, T> {}
|
||||
|
||||
fn test_correct(x: &dyn Foo<'static>) {
|
||||
let _ = x as &dyn Bar<'static, 'static, Tait>;
|
||||
}
|
||||
|
||||
fn test_correct2<'a>(x: &dyn Foo<'a>) {
|
||||
let _ = x as &dyn Bar<'_, '_, Tait>;
|
||||
}
|
||||
|
||||
fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) {
|
||||
let _ = x as &dyn Bar<'_, '_, ()>;
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -1,17 +0,0 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/upcast-defining-opaque.rs:21:5
|
||||
|
|
||||
LL | type Foo = impl Sized;
|
||||
| ---------- the found opaque type
|
||||
LL |
|
||||
LL | fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
|
||||
| ----------------------- expected `&dyn Super<Assoc = i32>` because of return type
|
||||
LL | x
|
||||
| ^ expected trait `Super`, found trait `Sub`
|
||||
|
|
||||
= note: expected reference `&dyn Super<Assoc = i32>`
|
||||
found reference `&dyn Sub<Assoc = Foo>`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
|
@ -1,7 +1,7 @@
|
|||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] check-pass
|
||||
//@check-pass
|
||||
|
||||
#![feature(trait_upcasting, type_alias_impl_trait)]
|
||||
|
||||
|
@ -18,7 +18,7 @@ impl<T: ?Sized> Super for T {
|
|||
type Foo = impl Sized;
|
||||
|
||||
fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
|
||||
x //[current]~ mismatched types
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
27
tests/ui/type-alias-impl-trait/constrain_in_projection.rs
Normal file
27
tests/ui/type-alias-impl-trait/constrain_in_projection.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
//! Check that projections will constrain opaque types while looking for
|
||||
//! matching impls.
|
||||
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@check-pass
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
struct Foo;
|
||||
|
||||
type Bar = impl Sized;
|
||||
|
||||
trait Trait<T> {
|
||||
type Assoc: Default;
|
||||
}
|
||||
|
||||
impl Trait<()> for Foo {
|
||||
type Assoc = u32;
|
||||
}
|
||||
|
||||
fn bop(_: Bar) {
|
||||
let x = <Foo as Trait<Bar>>::Assoc::default();
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,19 @@
|
|||
error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
|
||||
--> $DIR/constrain_in_projection2.rs:27:14
|
||||
|
|
||||
LL | let x = <Foo as Trait<Bar>>::Assoc::default();
|
||||
| ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
|
||||
|
|
||||
note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
|
||||
--> $DIR/constrain_in_projection2.rs:18:1
|
||||
|
|
||||
LL | impl Trait<()> for Foo {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | impl Trait<u32> for Foo {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
|
@ -0,0 +1,19 @@
|
|||
error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
|
||||
--> $DIR/constrain_in_projection2.rs:27:14
|
||||
|
|
||||
LL | let x = <Foo as Trait<Bar>>::Assoc::default();
|
||||
| ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
|
||||
|
|
||||
note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
|
||||
--> $DIR/constrain_in_projection2.rs:18:1
|
||||
|
|
||||
LL | impl Trait<()> for Foo {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | impl Trait<u32> for Foo {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
31
tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
Normal file
31
tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
Normal file
|
@ -0,0 +1,31 @@
|
|||
//! Check that projections will constrain opaque types while looking for
|
||||
//! matching impls and error if ambiguous.
|
||||
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
struct Foo;
|
||||
|
||||
type Bar = impl Sized;
|
||||
|
||||
trait Trait<T> {
|
||||
type Assoc: Default;
|
||||
}
|
||||
|
||||
impl Trait<()> for Foo {
|
||||
type Assoc = u32;
|
||||
}
|
||||
|
||||
impl Trait<u32> for Foo {
|
||||
type Assoc = u32;
|
||||
}
|
||||
|
||||
fn bop(_: Bar) {
|
||||
let x = <Foo as Trait<Bar>>::Assoc::default();
|
||||
//~^ ERROR: cannot satisfy `Foo: Trait<Bar>`
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -1,5 +1,5 @@
|
|||
error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
|
||||
--> $DIR/issue-84660-unsoundness.rs:23:1
|
||||
--> $DIR/issue-84660-unsoundness.rs:28:1
|
||||
|
|
||||
LL | impl<In, Out> Trait<Bar, In> for Out {
|
||||
| ------------------------------------ first implementation here
|
|
@ -0,0 +1,23 @@
|
|||
error[E0284]: type annotations needed: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
|
||||
--> $DIR/issue-84660-unsoundness.rs:22:37
|
||||
|
|
||||
LL | fn convert(_i: In) -> Self::Out {
|
||||
| _____________________________________^
|
||||
LL | |
|
||||
LL | | unreachable!();
|
||||
LL | | }
|
||||
| |_____^ cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
|
||||
|
||||
error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
|
||||
--> $DIR/issue-84660-unsoundness.rs:28:1
|
||||
|
|
||||
LL | impl<In, Out> Trait<Bar, In> for Out {
|
||||
| ------------------------------------ first implementation here
|
||||
...
|
||||
LL | impl<In, Out> Trait<(), In> for Out {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0119, E0284.
|
||||
For more information about an error, try `rustc --explain E0119`.
|
|
@ -1,6 +1,10 @@
|
|||
// Another example from issue #84660, this time weaponized as a safe transmute: an opaque type in an
|
||||
// impl header being accepted was used to create unsoundness.
|
||||
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
trait Foo {}
|
||||
|
@ -16,11 +20,13 @@ trait Trait<T, In> {
|
|||
impl<In, Out> Trait<Bar, In> for Out {
|
||||
type Out = Out;
|
||||
fn convert(_i: In) -> Self::Out {
|
||||
//[next]~^ ERROR: type annotations needed
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
impl<In, Out> Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait<Bar, _>`
|
||||
impl<In, Out> Trait<(), In> for Out {
|
||||
//~^ ERROR conflicting implementations of trait `Trait<Bar, _>`
|
||||
type Out = In;
|
||||
fn convert(i: In) -> Self::Out {
|
||||
i
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@check-pass
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
type FooX = impl Debug;
|
||||
|
||||
trait Foo<A> { }
|
||||
trait Foo<A> {}
|
||||
|
||||
impl Foo<()> for () { }
|
||||
impl Foo<()> for () {}
|
||||
|
||||
fn foo() -> impl Foo<FooX> {
|
||||
//~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
|
||||
// FIXME(type-alias-impl-trait): We could probably make this work.
|
||||
()
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
fn main() {}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
error[E0283]: type annotations needed: cannot satisfy `(): Foo<FooX>`
|
||||
--> $DIR/nested-tait-inference2.rs:17:13
|
||||
|
|
||||
LL | fn foo() -> impl Foo<FooX> {
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: multiple `impl`s satisfying `(): Foo<FooX>` found
|
||||
--> $DIR/nested-tait-inference2.rs:14:1
|
||||
|
|
||||
LL | impl Foo<()> for () {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
LL | impl Foo<u32> for () {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0283`.
|
|
@ -0,0 +1,9 @@
|
|||
error[E0284]: type annotations needed: cannot satisfy `impl Foo<FooX> == ()`
|
||||
--> $DIR/nested-tait-inference2.rs:19:5
|
||||
|
|
||||
LL | ()
|
||||
| ^^ cannot satisfy `impl Foo<FooX> == ()`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0284`.
|
|
@ -1,6 +1,10 @@
|
|||
#![feature(type_alias_impl_trait)]
|
||||
#![allow(dead_code)]
|
||||
|
||||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
type FooX = impl Debug;
|
||||
|
@ -11,8 +15,9 @@ impl Foo<()> for () {}
|
|||
impl Foo<u32> for () {}
|
||||
|
||||
fn foo() -> impl Foo<FooX> {
|
||||
//~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
|
||||
//[current]~^ ERROR: cannot satisfy `(): Foo<FooX>`
|
||||
()
|
||||
//[next]~^ ERROR: cannot satisfy `impl Foo<FooX> == ()`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
|
||||
--> $DIR/nested-tait-inference2.rs:13:13
|
||||
|
|
||||
LL | fn foo() -> impl Foo<FooX> {
|
||||
| ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
|
||||
LL |
|
||||
LL | ()
|
||||
| -- return type was inferred to be `()` here
|
||||
|
|
||||
= help: the following other types implement trait `Foo<A>`:
|
||||
<() as Foo<()>>
|
||||
<() as Foo<u32>>
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -22,21 +22,17 @@ note: previous use here
|
|||
LL | fn define_1() -> Opaque { dyn_hoops::<_>(0) }
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0308]: mismatched types
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/normalize-hidden-types.rs:43:25
|
||||
|
|
||||
LL | type Opaque = impl Sized;
|
||||
| ---------- the expected opaque type
|
||||
...
|
||||
LL | let _: Opaque = dyn_hoops::<u8>(0);
|
||||
| ------ ^^^^^^^^^^^^^^^^^^ expected opaque type, found `*const dyn FnOnce(())`
|
||||
| |
|
||||
| expected due to this
|
||||
| ^^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
|
||||
|
|
||||
= note: expected opaque type `typeck::Opaque`
|
||||
found raw pointer `*const (dyn FnOnce(()) + 'static)`
|
||||
= help: consider constraining the associated type `<u8 as Trait>::Gat<'_>` to `()` or calling a method that returns `<u8 as Trait>::Gat<'_>`
|
||||
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
|
||||
note: previous use here
|
||||
--> $DIR/normalize-hidden-types.rs:44:9
|
||||
|
|
||||
LL | None
|
||||
| ^^^^
|
||||
|
||||
error: concrete type differs from previous defining opaque type use
|
||||
--> $DIR/normalize-hidden-types.rs:52:25
|
||||
|
@ -52,4 +48,3 @@ LL | None
|
|||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
error[E0277]: can't compare `i32` with `Foo`
|
||||
--> $DIR/self-referential-2.rs:10:13
|
||||
|
|
||||
LL | fn bar() -> Bar {
|
||||
| ^^^ no implementation for `i32 == Foo`
|
||||
LL | 42_i32
|
||||
| ------ return type was inferred to be `i32` here
|
||||
|
|
||||
= help: the trait `PartialEq<Foo>` is not implemented for `i32`
|
||||
= help: the trait `PartialEq` is implemented for `i32`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,14 +1,14 @@
|
|||
//@ revisions: current next
|
||||
//@ ignore-compare-mode-next-solver (explicit revisions)
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
//@[next] check-pass
|
||||
//@ check-pass
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
type Foo = impl std::fmt::Debug;
|
||||
type Bar = impl PartialEq<Foo>;
|
||||
|
||||
fn bar() -> Bar {
|
||||
42_i32 //[current]~^ ERROR can't compare `i32` with `Foo`
|
||||
42_i32
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug;
|
||||
|
||||
fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
|
||||
//~^ ERROR can't compare `&i32` with `Bar<'a, 'b>`
|
||||
//~^ ERROR overflow normalizing the type alias `Bar<'a, 'b>`
|
||||
i
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
error[E0277]: can't compare `&i32` with `Bar<'a, 'b>`
|
||||
error[E0275]: overflow normalizing the type alias `Bar<'a, 'b>`
|
||||
--> $DIR/self-referential-3.rs:7:31
|
||||
|
|
||||
LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
|
||||
| ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>`
|
||||
LL |
|
||||
LL | i
|
||||
| - return type was inferred to be `&i32` here
|
||||
| ^^^^^^^^^^^
|
||||
|
|
||||
= help: the trait `PartialEq<Bar<'a, 'b>>` is not implemented for `&i32`
|
||||
= help: the trait `PartialEq` is implemented for `i32`
|
||||
= note: in case this is a recursive type alias, consider using a struct, enum, or union instead
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
For more information about this error, try `rustc --explain E0275`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue