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:
bors 2024-12-07 09:38:00 +00:00
commit 9c707a8b76
32 changed files with 295 additions and 236 deletions

View file

@ -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}",

View file

@ -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)
}

View file

@ -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

View file

@ -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,

View file

@ -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

View file

@ -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

View file

@ -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),

View file

@ -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;

View file

@ -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),
);

View file

@ -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};

View file

@ -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 {

View file

@ -335,7 +335,7 @@ fn kind_from_prim(ek: u32) -> Option<ErrorKind> {
WriteZero,
StorageFull,
NotSeekable,
FilesystemQuotaExceeded,
QuotaExceeded,
FileTooLarge,
ResourceBusy,
ExecutableFileBusy,

View file

@ -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,

View file

@ -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,

View file

@ -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,
}

View file

@ -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");

View file

@ -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),

View file

@ -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),

View file

@ -1,4 +0,0 @@
//@ known-bug: #123809
type Positive = std::pat::pattern_type!(std::pat is 0..);
pub fn main() {}

View file

@ -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

View 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`.

View 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`.

View 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
}

View file

@ -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() {}

View file

@ -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`.