Auto merge of #133978 - matthiaskrgr:rollup-6gh1iho, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #130209 (Stabilize `std::io::ErrorKind::CrossesDevices`) - #130254 (Stabilize `std::io::ErrorKind::QuotaExceeded`) - #132187 (Add Extend impls for tuples of arity 1 through 12) - #133875 (handle `--json-output` properly) - #133934 (Do not implement unsafe auto traits for types with unsafe fields) - #133954 (Hide errors whose suggestions would contain error constants or types) - #133960 (rustdoc: remove eq for clean::Attributes) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
9c707a8b76
32 changed files with 295 additions and 236 deletions
|
@ -998,6 +998,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
self.lower_const_arg(ct, FeedConstTy::No).into()
|
||||
}
|
||||
};
|
||||
if term.references_error() {
|
||||
continue;
|
||||
}
|
||||
// FIXME(#97583): This isn't syntactically well-formed!
|
||||
where_bounds.push(format!(
|
||||
" T: {trait}::{assoc_name} = {term}",
|
||||
|
|
|
@ -585,6 +585,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
self.trait_def(trait_def_id).implement_via_object
|
||||
}
|
||||
|
||||
fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool {
|
||||
self.trait_def(trait_def_id).safety == hir::Safety::Unsafe
|
||||
}
|
||||
|
||||
fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
|
||||
self.is_impl_trait_in_trait(def_id)
|
||||
}
|
||||
|
|
|
@ -978,6 +978,14 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
|
|||
fn async_destructor_ty(self, interner: TyCtxt<'tcx>) -> Ty<'tcx> {
|
||||
self.async_destructor_ty(interner)
|
||||
}
|
||||
|
||||
fn has_unsafe_fields(self) -> bool {
|
||||
if let ty::Adt(adt_def, ..) = self.kind() {
|
||||
adt_def.all_fields().any(|x| x.safety == hir::Safety::Unsafe)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Type utilities
|
||||
|
|
|
@ -2,7 +2,7 @@ use rustc_ast as ast;
|
|||
use rustc_hir::LangItem;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
|
||||
use rustc_middle::ty::{self, ScalarInt, TyCtxt};
|
||||
use rustc_middle::ty::{self, ScalarInt, TyCtxt, TypeVisitableExt as _};
|
||||
use tracing::trace;
|
||||
|
||||
use crate::build::parse_float_into_scalar;
|
||||
|
@ -13,6 +13,10 @@ pub(crate) fn lit_to_const<'tcx>(
|
|||
) -> Result<ty::Const<'tcx>, LitToConstError> {
|
||||
let LitToConstInput { lit, ty, neg } = lit_input;
|
||||
|
||||
if let Err(guar) = ty.error_reported() {
|
||||
return Ok(ty::Const::new_error(tcx, guar));
|
||||
}
|
||||
|
||||
let trunc = |n| {
|
||||
let width = match tcx.layout_of(ty::TypingEnv::fully_monomorphized().as_query_input(ty)) {
|
||||
Ok(layout) => layout.size,
|
||||
|
|
|
@ -169,6 +169,14 @@ where
|
|||
return result;
|
||||
}
|
||||
|
||||
// Only consider auto impls of unsafe traits when there are no unsafe
|
||||
// fields.
|
||||
if ecx.cx().trait_is_unsafe(goal.predicate.def_id())
|
||||
&& goal.predicate.self_ty().has_unsafe_fields()
|
||||
{
|
||||
return Err(NoSolution);
|
||||
}
|
||||
|
||||
// We only look into opaque types during analysis for opaque types
|
||||
// outside of their defining scope. Doing so for opaques in the
|
||||
// defining scope may require calling `typeck` on the same item we're
|
||||
|
|
|
@ -18,6 +18,7 @@ use rustc_infer::traits::{
|
|||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt, TypingMode};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_type_ir::Interner;
|
||||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use super::SelectionCandidate::*;
|
||||
|
@ -794,6 +795,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
| ty::Never
|
||||
| ty::Tuple(_)
|
||||
| ty::CoroutineWitness(..) => {
|
||||
use rustc_type_ir::inherent::*;
|
||||
|
||||
// Only consider auto impls of unsafe traits when there are
|
||||
// no unsafe fields.
|
||||
if self.tcx().trait_is_unsafe(def_id) && self_ty.has_unsafe_fields() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only consider auto impls if there are no manual impls for the root of `self_ty`.
|
||||
//
|
||||
// For example, we only consider auto candidates for `&i32: Auto` if no explicit impl
|
||||
|
|
|
@ -136,6 +136,9 @@ pub trait Ty<I: Interner<Ty = Self>>:
|
|||
matches!(self.kind(), ty::FnPtr(..))
|
||||
}
|
||||
|
||||
/// Checks whether this type is an ADT that has unsafe fields.
|
||||
fn has_unsafe_fields(self) -> bool;
|
||||
|
||||
fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> {
|
||||
match self.kind() {
|
||||
ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr),
|
||||
|
|
|
@ -270,6 +270,9 @@ pub trait Interner:
|
|||
|
||||
fn trait_may_be_implemented_via_object(self, trait_def_id: Self::DefId) -> bool;
|
||||
|
||||
/// Returns `true` if this is an `unsafe trait`.
|
||||
fn trait_is_unsafe(self, trait_def_id: Self::DefId) -> bool;
|
||||
|
||||
fn is_impl_trait_in_trait(self, def_id: Self::DefId) -> bool;
|
||||
|
||||
fn delay_bug(self, msg: impl ToString) -> Self::ErrorGuaranteed;
|
||||
|
|
|
@ -492,11 +492,22 @@ impl Extend<()> for () {
|
|||
fn extend_one(&mut self, _item: ()) {}
|
||||
}
|
||||
|
||||
macro_rules! spec_tuple_impl {
|
||||
( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), ) => {
|
||||
spec_tuple_impl!($trait_name, $default_fn_name, #[doc(fake_variadic)] #[doc = "This trait is implemented for tuples up to twelve items long. The `impl`s for 1- and 3- through 12-ary tuples were stabilized after 2-tuples, in RUSTC_CURRENT_VERSION."] => ($ty_name, $var_name, $extend_ty_name, $cnt),);
|
||||
};
|
||||
( ($ty_name:ident, $var_name:ident, $extend_ty_name: ident, $trait_name:ident, $default_fn_name:ident, $cnt:tt), $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $trait_names:ident, $default_fn_names:ident, $cnts:tt),)*) => {
|
||||
|
||||
spec_tuple_impl!($(($ty_names, $var_names, $extend_ty_names, $trait_names, $default_fn_names, $cnts),)*);
|
||||
spec_tuple_impl!($trait_name, $default_fn_name, #[doc(hidden)] => ($ty_name, $var_name, $extend_ty_name, $cnt), $(($ty_names, $var_names, $extend_ty_names, $cnts),)*);
|
||||
};
|
||||
($trait_name:ident, $default_fn_name:ident, #[$meta:meta] $(#[$doctext:meta])? => $(($ty_names:ident, $var_names:ident, $extend_ty_names:ident, $cnts:tt),)*) => {
|
||||
#[$meta]
|
||||
$(#[$doctext])?
|
||||
#[stable(feature = "extend_for_tuple", since = "1.56.0")]
|
||||
impl<A, B, ExtendA, ExtendB> Extend<(A, B)> for (ExtendA, ExtendB)
|
||||
impl<$($ty_names,)* $($extend_ty_names,)*> Extend<($($ty_names,)*)> for ($($extend_ty_names,)*)
|
||||
where
|
||||
ExtendA: Extend<A>,
|
||||
ExtendB: Extend<B>,
|
||||
$($extend_ty_names: Extend<$ty_names>,)*
|
||||
{
|
||||
/// Allows to `extend` a tuple of collections that also implement `Extend`.
|
||||
///
|
||||
|
@ -504,6 +515,7 @@ where
|
|||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// // Example given for a 2-tuple, but 1- through 12-tuples are supported
|
||||
/// let mut tuple = (vec![0], vec![1]);
|
||||
/// tuple.extend([(2, 3), (4, 5), (6, 7)]);
|
||||
/// assert_eq!(tuple.0, [0, 2, 4, 6]);
|
||||
|
@ -518,89 +530,79 @@ where
|
|||
/// assert_eq!(b, [2, 5, 8]);
|
||||
/// assert_eq!(c, [3, 6, 9]);
|
||||
/// ```
|
||||
fn extend<T: IntoIterator<Item = (A, B)>>(&mut self, into_iter: T) {
|
||||
let (a, b) = self;
|
||||
fn extend<T: IntoIterator<Item = ($($ty_names,)*)>>(&mut self, into_iter: T) {
|
||||
let ($($var_names,)*) = self;
|
||||
let iter = into_iter.into_iter();
|
||||
SpecTupleExtend::extend(iter, a, b);
|
||||
$trait_name::extend(iter, $($var_names,)*);
|
||||
}
|
||||
|
||||
fn extend_one(&mut self, item: (A, B)) {
|
||||
self.0.extend_one(item.0);
|
||||
self.1.extend_one(item.1);
|
||||
fn extend_one(&mut self, item: ($($ty_names,)*)) {
|
||||
$(self.$cnts.extend_one(item.$cnts);)*
|
||||
}
|
||||
|
||||
fn extend_reserve(&mut self, additional: usize) {
|
||||
self.0.extend_reserve(additional);
|
||||
self.1.extend_reserve(additional);
|
||||
$(self.$cnts.extend_reserve(additional);)*
|
||||
}
|
||||
|
||||
unsafe fn extend_one_unchecked(&mut self, item: (A, B)) {
|
||||
unsafe fn extend_one_unchecked(&mut self, item: ($($ty_names,)*)) {
|
||||
// SAFETY: Those are our safety preconditions, and we correctly forward `extend_reserve`.
|
||||
unsafe {
|
||||
self.0.extend_one_unchecked(item.0);
|
||||
self.1.extend_one_unchecked(item.1);
|
||||
$(self.$cnts.extend_one_unchecked(item.$cnts);)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn default_extend_tuple<A, B, ExtendA, ExtendB>(
|
||||
iter: impl Iterator<Item = (A, B)>,
|
||||
a: &mut ExtendA,
|
||||
b: &mut ExtendB,
|
||||
trait $trait_name<$($ty_names),*> {
|
||||
fn extend(self, $($var_names: &mut $ty_names,)*);
|
||||
}
|
||||
|
||||
fn $default_fn_name<$($ty_names,)* $($extend_ty_names,)*>(
|
||||
iter: impl Iterator<Item = ($($ty_names,)*)>,
|
||||
$($var_names: &mut $extend_ty_names,)*
|
||||
) where
|
||||
ExtendA: Extend<A>,
|
||||
ExtendB: Extend<B>,
|
||||
$($extend_ty_names: Extend<$ty_names>,)*
|
||||
{
|
||||
fn extend<'a, A, B>(
|
||||
a: &'a mut impl Extend<A>,
|
||||
b: &'a mut impl Extend<B>,
|
||||
) -> impl FnMut((), (A, B)) + 'a {
|
||||
move |(), (t, u)| {
|
||||
a.extend_one(t);
|
||||
b.extend_one(u);
|
||||
fn extend<'a, $($ty_names,)*>(
|
||||
$($var_names: &'a mut impl Extend<$ty_names>,)*
|
||||
) -> impl FnMut((), ($($ty_names,)*)) + 'a {
|
||||
#[allow(non_snake_case)]
|
||||
move |(), ($($extend_ty_names,)*)| {
|
||||
$($var_names.extend_one($extend_ty_names);)*
|
||||
}
|
||||
}
|
||||
|
||||
let (lower_bound, _) = iter.size_hint();
|
||||
if lower_bound > 0 {
|
||||
a.extend_reserve(lower_bound);
|
||||
b.extend_reserve(lower_bound);
|
||||
$($var_names.extend_reserve(lower_bound);)*
|
||||
}
|
||||
|
||||
iter.fold((), extend(a, b));
|
||||
iter.fold((), extend($($var_names,)*));
|
||||
}
|
||||
|
||||
trait SpecTupleExtend<A, B> {
|
||||
fn extend(self, a: &mut A, b: &mut B);
|
||||
}
|
||||
|
||||
impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
|
||||
impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter
|
||||
where
|
||||
ExtendA: Extend<A>,
|
||||
ExtendB: Extend<B>,
|
||||
Iter: Iterator<Item = (A, B)>,
|
||||
$($extend_ty_names: Extend<$ty_names>,)*
|
||||
Iter: Iterator<Item = ($($ty_names,)*)>,
|
||||
{
|
||||
default fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
|
||||
default_extend_tuple(self, a, b);
|
||||
default fn extend(self, $($var_names: &mut $extend_ty_names),*) {
|
||||
$default_fn_name(self, $($var_names),*);
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, ExtendA, ExtendB, Iter> SpecTupleExtend<ExtendA, ExtendB> for Iter
|
||||
impl<$($ty_names,)* $($extend_ty_names,)* Iter> $trait_name<$($extend_ty_names),*> for Iter
|
||||
where
|
||||
ExtendA: Extend<A>,
|
||||
ExtendB: Extend<B>,
|
||||
Iter: TrustedLen<Item = (A, B)>,
|
||||
$($extend_ty_names: Extend<$ty_names>,)*
|
||||
Iter: TrustedLen<Item = ($($ty_names,)*)>,
|
||||
{
|
||||
fn extend(self, a: &mut ExtendA, b: &mut ExtendB) {
|
||||
fn extend<'a, A, B>(
|
||||
a: &'a mut impl Extend<A>,
|
||||
b: &'a mut impl Extend<B>,
|
||||
) -> impl FnMut((), (A, B)) + 'a {
|
||||
fn extend(self, $($var_names: &mut $extend_ty_names,)*) {
|
||||
fn extend<'a, $($ty_names,)*>(
|
||||
$($var_names: &'a mut impl Extend<$ty_names>,)*
|
||||
) -> impl FnMut((), ($($ty_names,)*)) + 'a {
|
||||
#[allow(non_snake_case)]
|
||||
// SAFETY: We reserve enough space for the `size_hint`, and the iterator is `TrustedLen`
|
||||
// so its `size_hint` is exact.
|
||||
move |(), (t, u)| unsafe {
|
||||
a.extend_one_unchecked(t);
|
||||
b.extend_one_unchecked(u);
|
||||
move |(), ($($extend_ty_names,)*)| unsafe {
|
||||
$($var_names.extend_one_unchecked($extend_ty_names);)*
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,15 +610,32 @@ where
|
|||
|
||||
if upper_bound.is_none() {
|
||||
// We cannot reserve more than `usize::MAX` items, and this is likely to go out of memory anyway.
|
||||
default_extend_tuple(self, a, b);
|
||||
$default_fn_name(self, $($var_names,)*);
|
||||
return;
|
||||
}
|
||||
|
||||
if lower_bound > 0 {
|
||||
a.extend_reserve(lower_bound);
|
||||
b.extend_reserve(lower_bound);
|
||||
$($var_names.extend_reserve(lower_bound);)*
|
||||
}
|
||||
|
||||
self.fold((), extend(a, b));
|
||||
self.fold((), extend($($var_names,)*));
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
spec_tuple_impl!(
|
||||
(L, l, EL, TraitL, default_extend_tuple_l, 11),
|
||||
(K, k, EK, TraitK, default_extend_tuple_k, 10),
|
||||
(J, j, EJ, TraitJ, default_extend_tuple_j, 9),
|
||||
(I, i, EI, TraitI, default_extend_tuple_i, 8),
|
||||
(H, h, EH, TraitH, default_extend_tuple_h, 7),
|
||||
(G, g, EG, TraitG, default_extend_tuple_g, 6),
|
||||
(F, f, EF, TraitF, default_extend_tuple_f, 5),
|
||||
(E, e, EE, TraitE, default_extend_tuple_e, 4),
|
||||
(D, d, ED, TraitD, default_extend_tuple_d, 3),
|
||||
(C, c, EC, TraitC, default_extend_tuple_c, 2),
|
||||
(B, b, EB, TraitB, default_extend_tuple_b, 1),
|
||||
(A, a, EA, TraitA, default_extend_tuple_a, 0),
|
||||
);
|
||||
|
|
|
@ -617,6 +617,19 @@ fn test_next_chunk() {
|
|||
assert_eq!(it.next_chunk::<0>().unwrap(), []);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_collect_into_tuples() {
|
||||
let a = vec![(1, 2, 3), (4, 5, 6), (7, 8, 9)];
|
||||
let b = vec![1, 4, 7];
|
||||
let c = vec![2, 5, 8];
|
||||
let d = vec![3, 6, 9];
|
||||
let mut e = (Vec::new(), Vec::new(), Vec::new());
|
||||
a.iter().cloned().collect_into(&mut e);
|
||||
assert!(e.0 == b);
|
||||
assert!(e.1 == c);
|
||||
assert!(e.2 == d);
|
||||
}
|
||||
|
||||
// just tests by whether or not this compiles
|
||||
fn _empty_impl_all_auto_traits<T>() {
|
||||
use std::panic::{RefUnwindSafe, UnwindSafe};
|
||||
|
|
|
@ -338,9 +338,9 @@ pub enum ErrorKind {
|
|||
/// example, on Unix, a named pipe opened with `File::open`.
|
||||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
NotSeekable,
|
||||
/// Filesystem quota was exceeded.
|
||||
#[unstable(feature = "io_error_more", issue = "86442")]
|
||||
FilesystemQuotaExceeded,
|
||||
/// Filesystem quota or some other kind of quota was exceeded.
|
||||
#[stable(feature = "io_error_quota_exceeded", since = "CURRENT_RUSTC_VERSION")]
|
||||
QuotaExceeded,
|
||||
/// File larger than allowed or supported.
|
||||
///
|
||||
/// This might arise from a hard limit of the underlying filesystem or file access API, or from
|
||||
|
@ -364,7 +364,7 @@ pub enum ErrorKind {
|
|||
#[stable(feature = "io_error_a_bit_more", since = "1.83.0")]
|
||||
Deadlock,
|
||||
/// Cross-device or cross-filesystem (hard) link or rename.
|
||||
#[unstable(feature = "io_error_more", issue = "86442")]
|
||||
#[stable(feature = "io_error_crosses_devices", since = "CURRENT_RUSTC_VERSION")]
|
||||
CrossesDevices,
|
||||
/// Too many (hard) links to the same filesystem object.
|
||||
///
|
||||
|
@ -446,8 +446,8 @@ pub enum ErrorKind {
|
|||
impl ErrorKind {
|
||||
pub(crate) fn as_str(&self) -> &'static str {
|
||||
use ErrorKind::*;
|
||||
// tidy-alphabetical-start
|
||||
match *self {
|
||||
// tidy-alphabetical-start
|
||||
AddrInUse => "address in use",
|
||||
AddrNotAvailable => "address not available",
|
||||
AlreadyExists => "entity already exists",
|
||||
|
@ -460,12 +460,11 @@ impl ErrorKind {
|
|||
Deadlock => "deadlock",
|
||||
DirectoryNotEmpty => "directory not empty",
|
||||
ExecutableFileBusy => "executable file busy",
|
||||
FileTooLarge => "file too large",
|
||||
FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)",
|
||||
FilesystemQuotaExceeded => "filesystem quota exceeded",
|
||||
FileTooLarge => "file too large",
|
||||
HostUnreachable => "host unreachable",
|
||||
Interrupted => "operation interrupted",
|
||||
InProgress => "in progress",
|
||||
Interrupted => "operation interrupted",
|
||||
InvalidData => "invalid data",
|
||||
InvalidFilename => "invalid filename",
|
||||
InvalidInput => "invalid input parameter",
|
||||
|
@ -479,6 +478,7 @@ impl ErrorKind {
|
|||
Other => "other error",
|
||||
OutOfMemory => "out of memory",
|
||||
PermissionDenied => "permission denied",
|
||||
QuotaExceeded => "quota exceeded",
|
||||
ReadOnlyFilesystem => "read-only filesystem or storage medium",
|
||||
ResourceBusy => "resource busy",
|
||||
StaleNetworkFileHandle => "stale network file handle",
|
||||
|
@ -490,10 +490,10 @@ impl ErrorKind {
|
|||
Unsupported => "unsupported",
|
||||
WouldBlock => "operation would block",
|
||||
WriteZero => "write zero",
|
||||
}
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "io_errorkind_display", since = "1.60.0")]
|
||||
impl fmt::Display for ErrorKind {
|
||||
|
|
|
@ -335,7 +335,7 @@ fn kind_from_prim(ek: u32) -> Option<ErrorKind> {
|
|||
WriteZero,
|
||||
StorageFull,
|
||||
NotSeekable,
|
||||
FilesystemQuotaExceeded,
|
||||
QuotaExceeded,
|
||||
FileTooLarge,
|
||||
ResourceBusy,
|
||||
ExecutableFileBusy,
|
||||
|
|
|
@ -71,7 +71,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
|||
libc::ECONNREFUSED => ConnectionRefused,
|
||||
libc::ECONNRESET => ConnectionReset,
|
||||
libc::EDEADLK => Deadlock,
|
||||
libc::EDQUOT => FilesystemQuotaExceeded,
|
||||
libc::EDQUOT => QuotaExceeded,
|
||||
libc::EEXIST => AlreadyExists,
|
||||
libc::EFBIG => FileTooLarge,
|
||||
libc::EHOSTUNREACH => HostUnreachable,
|
||||
|
|
|
@ -254,7 +254,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
|||
libc::ECONNREFUSED => ConnectionRefused,
|
||||
libc::ECONNRESET => ConnectionReset,
|
||||
libc::EDEADLK => Deadlock,
|
||||
libc::EDQUOT => FilesystemQuotaExceeded,
|
||||
libc::EDQUOT => QuotaExceeded,
|
||||
libc::EEXIST => AlreadyExists,
|
||||
libc::EFBIG => FileTooLarge,
|
||||
libc::EHOSTUNREACH => HostUnreachable,
|
||||
|
|
|
@ -113,7 +113,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
|||
c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem,
|
||||
c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull,
|
||||
c::ERROR_SEEK_ON_DEVICE => return NotSeekable,
|
||||
c::ERROR_DISK_QUOTA_EXCEEDED => return FilesystemQuotaExceeded,
|
||||
c::ERROR_DISK_QUOTA_EXCEEDED => return QuotaExceeded,
|
||||
c::ERROR_FILE_TOO_LARGE => return FileTooLarge,
|
||||
c::ERROR_BUSY => return ResourceBusy,
|
||||
c::ERROR_POSSIBLE_DEADLOCK => return Deadlock,
|
||||
|
@ -138,7 +138,7 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
|||
c::WSAEHOSTUNREACH => HostUnreachable,
|
||||
c::WSAENETDOWN => NetworkDown,
|
||||
c::WSAENETUNREACH => NetworkUnreachable,
|
||||
c::WSAEDQUOT => FilesystemQuotaExceeded,
|
||||
c::WSAEDQUOT => QuotaExceeded,
|
||||
|
||||
_ => Uncategorized,
|
||||
}
|
||||
|
|
|
@ -1070,6 +1070,7 @@ impl Step for Tidy {
|
|||
}
|
||||
|
||||
if builder.config.channel == "dev" || builder.config.channel == "nightly" {
|
||||
if !builder.config.json_output {
|
||||
builder.info("fmt check");
|
||||
if builder.initial_rustfmt().is_none() {
|
||||
let inferred_rustfmt_dir = builder.initial_sysroot.join("bin");
|
||||
|
@ -1085,8 +1086,17 @@ HELP: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to
|
|||
crate::exit!(1);
|
||||
}
|
||||
let all = false;
|
||||
crate::core::build_steps::format::format(builder, !builder.config.cmd.bless(), all, &[
|
||||
]);
|
||||
crate::core::build_steps::format::format(
|
||||
builder,
|
||||
!builder.config.cmd.bless(),
|
||||
all,
|
||||
&[],
|
||||
);
|
||||
} else {
|
||||
eprintln!(
|
||||
"WARNING: `--json-output` is not supported on rustfmt, formatting will be skipped"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
builder.info("tidy check");
|
||||
|
@ -2624,6 +2634,11 @@ fn prepare_cargo_test(
|
|||
if builder.kind == Kind::Test && !builder.fail_fast {
|
||||
cargo.arg("--no-fail-fast");
|
||||
}
|
||||
|
||||
if builder.config.json_output {
|
||||
cargo.arg("--message-format=json");
|
||||
}
|
||||
|
||||
match builder.doc_tests {
|
||||
DocTests::Only => {
|
||||
cargo.arg("--doc");
|
||||
|
|
|
@ -1241,19 +1241,6 @@ impl Attributes {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Attributes {
|
||||
fn eq(&self, rhs: &Self) -> bool {
|
||||
self.doc_strings == rhs.doc_strings
|
||||
&& self
|
||||
.other_attrs
|
||||
.iter()
|
||||
.map(|attr| attr.id)
|
||||
.eq(rhs.other_attrs.iter().map(|attr| attr.id))
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Attributes {}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
||||
pub(crate) enum GenericBound {
|
||||
TraitBound(PolyTrait, hir::TraitBoundModifiers),
|
||||
|
|
|
@ -44,7 +44,7 @@ const UNIX_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = {
|
|||
("ECONNREFUSED", ConnectionRefused),
|
||||
("ECONNRESET", ConnectionReset),
|
||||
("EDEADLK", Deadlock),
|
||||
("EDQUOT", FilesystemQuotaExceeded),
|
||||
("EDQUOT", QuotaExceeded),
|
||||
("EEXIST", AlreadyExists),
|
||||
("EFBIG", FileTooLarge),
|
||||
("EHOSTUNREACH", HostUnreachable),
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
//@ known-bug: #123809
|
||||
type Positive = std::pat::pattern_type!(std::pat is 0..);
|
||||
|
||||
pub fn main() {}
|
|
@ -26,12 +26,6 @@ LL | trait Parent2 { const C: &'static str; }
|
|||
LL |
|
||||
LL | fn take1(_: impl Trait1<C = "?">) {}
|
||||
| ^^^^^^^ ambiguous associated constant `C`
|
||||
|
|
||||
= help: consider introducing a new type parameter `T` and adding `where` constraints:
|
||||
where
|
||||
T: Trait1,
|
||||
T: Parent2::C = "?",
|
||||
T: Parent1::C = "?"
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
17
tests/ui/unsafe-fields/auto-traits.current.stderr
Normal file
17
tests/ui/unsafe-fields/auto-traits.current.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied
|
||||
--> $DIR/auto-traits.rs:24:22
|
||||
|
|
||||
LL | impl_unsafe_auto(UnsafeEnum::Safe(42));
|
||||
| ---------------- ^^^^^^^^^^^^^^^^^^^^ the trait `UnsafeAuto` is not implemented for `UnsafeEnum`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `impl_unsafe_auto`
|
||||
--> $DIR/auto-traits.rs:20:29
|
||||
|
|
||||
LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {}
|
||||
| ^^^^^^^^^^ required by this bound in `impl_unsafe_auto`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
17
tests/ui/unsafe-fields/auto-traits.next.stderr
Normal file
17
tests/ui/unsafe-fields/auto-traits.next.stderr
Normal file
|
@ -0,0 +1,17 @@
|
|||
error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied
|
||||
--> $DIR/auto-traits.rs:24:22
|
||||
|
|
||||
LL | impl_unsafe_auto(UnsafeEnum::Safe(42));
|
||||
| ---------------- ^^^^^^^^^^^^^^^^^^^^ the trait `UnsafeAuto` is not implemented for `UnsafeEnum`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `impl_unsafe_auto`
|
||||
--> $DIR/auto-traits.rs:20:29
|
||||
|
|
||||
LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {}
|
||||
| ^^^^^^^^^^ required by this bound in `impl_unsafe_auto`
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
26
tests/ui/unsafe-fields/auto-traits.rs
Normal file
26
tests/ui/unsafe-fields/auto-traits.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
//@ compile-flags: --crate-type=lib
|
||||
//@ revisions: current next
|
||||
//@[next] compile-flags: -Znext-solver
|
||||
|
||||
#![feature(auto_traits)]
|
||||
#![feature(unsafe_fields)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
enum UnsafeEnum {
|
||||
Safe(u8),
|
||||
Unsafe { unsafe field: u8 },
|
||||
}
|
||||
|
||||
auto trait SafeAuto {}
|
||||
|
||||
fn impl_safe_auto(_: impl SafeAuto) {}
|
||||
|
||||
unsafe auto trait UnsafeAuto {}
|
||||
|
||||
fn impl_unsafe_auto(_: impl UnsafeAuto) {}
|
||||
|
||||
fn tests() {
|
||||
impl_safe_auto(UnsafeEnum::Safe(42));
|
||||
impl_unsafe_auto(UnsafeEnum::Safe(42));
|
||||
//~^ ERROR the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied
|
||||
}
|
|
@ -3,15 +3,11 @@ trait Foo<const N: Bar<2>> {
|
|||
//~^ WARN trait objects without an explicit `dyn` are deprecated
|
||||
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
|
||||
//~| ERROR cycle detected when computing type of `Foo::N`
|
||||
//~| ERROR the trait `Foo` cannot be made into an object
|
||||
//~| ERROR `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter
|
||||
fn func() {}
|
||||
}
|
||||
|
||||
trait Bar<const M: Foo<2>> {}
|
||||
//~^ WARN trait objects without an explicit `dyn` are deprecated
|
||||
//~| WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
|
||||
//~| ERROR the trait `Foo` cannot be made into an object
|
||||
//~| ERROR `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter
|
||||
|
||||
fn main() {}
|
||||
|
|
|
@ -13,7 +13,7 @@ LL | trait Foo<const N: dyn Bar<2>> {
|
|||
| +++
|
||||
|
||||
warning: trait objects without an explicit `dyn` are deprecated
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:20
|
||||
|
|
||||
LL | trait Bar<const M: Foo<2>> {}
|
||||
| ^^^^^^
|
||||
|
@ -32,7 +32,7 @@ LL | trait Foo<const N: Bar<2>> {
|
|||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires computing type of `Bar::M`...
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:9:11
|
||||
|
|
||||
LL | trait Bar<const M: Foo<2>> {}
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
@ -44,69 +44,6 @@ LL | trait Foo<const N: Bar<2>> {
|
|||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
|
||||
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:24
|
||||
|
|
||||
LL | trait Foo<const N: Bar<2>> {
|
||||
| ^ `Foo` cannot be made into an object
|
||||
|
|
||||
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8
|
||||
|
|
||||
LL | trait Foo<const N: Bar<2>> {
|
||||
| --- this trait cannot be made into an object...
|
||||
...
|
||||
LL | fn func() {}
|
||||
| ^^^^ ...because associated function `func` has no `self` parameter
|
||||
help: consider turning `func` into a method by giving it a `&self` argument
|
||||
|
|
||||
LL | fn func(&self) {}
|
||||
| +++++
|
||||
help: alternatively, consider constraining `func` so it does not apply to trait objects
|
||||
|
|
||||
LL | fn func() where Self: Sized {}
|
||||
| +++++++++++++++++
|
||||
error: aborting due to 1 previous error; 2 warnings emitted
|
||||
|
||||
error: `(dyn Bar<2> + 'static)` is forbidden as the type of a const generic parameter
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:2:20
|
||||
|
|
||||
LL | trait Foo<const N: Bar<2>> {
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool`, and `char`
|
||||
|
||||
error[E0038]: the trait `Foo` cannot be made into an object
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:11
|
||||
|
|
||||
LL | trait Bar<const M: Foo<2>> {}
|
||||
| ^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
|
||||
|
|
||||
note: for a trait to be "dyn-compatible" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:8:8
|
||||
|
|
||||
LL | trait Foo<const N: Bar<2>> {
|
||||
| --- this trait cannot be made into an object...
|
||||
...
|
||||
LL | fn func() {}
|
||||
| ^^^^ ...because associated function `func` has no `self` parameter
|
||||
help: consider turning `func` into a method by giving it a `&self` argument
|
||||
|
|
||||
LL | fn func(&self) {}
|
||||
| +++++
|
||||
help: alternatively, consider constraining `func` so it does not apply to trait objects
|
||||
|
|
||||
LL | fn func() where Self: Sized {}
|
||||
| +++++++++++++++++
|
||||
|
||||
error: `(dyn Foo<2> + 'static)` is forbidden as the type of a const generic parameter
|
||||
--> $DIR/ice-hir-wf-check-anon-const-issue-122989.rs:11:20
|
||||
|
|
||||
LL | trait Bar<const M: Foo<2>> {}
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: the only supported types are integers, `bool`, and `char`
|
||||
|
||||
error: aborting due to 5 previous errors; 2 warnings emitted
|
||||
|
||||
Some errors have detailed explanations: E0038, E0391.
|
||||
For more information about an error, try `rustc --explain E0038`.
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue