Auto merge of #133818 - matthiaskrgr:rollup-iav1wq7, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #132937 (a release operation synchronizes with an acquire operation)
 - #133681 (improve TagEncoding::Niche docs, sanity check, and UB checks)
 - #133726 (Add `core::arch::breakpoint` and test)
 - #133768 (Remove `generic_associated_types_extended` feature gate)
 - #133811 ([AIX] change AIX default codemodel=large)
 - #133812 (Update wasm-component-ld to 0.5.11)
 - #133813 (compiletest: explain that UI tests are expected not to compile by default)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-12-04 00:47:09 +00:00
commit 3b382642ab
51 changed files with 566 additions and 240 deletions

View file

@ -5803,17 +5803,20 @@ checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]] [[package]]
name = "wasm-component-ld" name = "wasm-component-ld"
version = "0.5.10" version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d4aa6bd7fbe7cffbed29fe3e236fda74419def1bdef6f80f989ec51137edf44" checksum = "a2b05c3820968b335f10e703218459e4fd2cc91fdfc8f7936a993f1aacaa0938"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"clap", "clap",
"lexopt", "lexopt",
"libc",
"tempfile", "tempfile",
"wasi-preview1-component-adapter-provider", "wasi-preview1-component-adapter-provider",
"wasmparser 0.219.1", "wasmparser 0.219.1",
"wat", "wat",
"windows-sys 0.59.0",
"winsplit",
"wit-component", "wit-component",
"wit-parser", "wit-parser",
] ]
@ -6185,6 +6188,12 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "winsplit"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956"
[[package]] [[package]]
name = "wit-component" name = "wit-component"
version = "0.219.1" version = "0.219.1"

View file

@ -1215,6 +1215,15 @@ impl Scalar {
Scalar::Union { .. } => true, Scalar::Union { .. } => true,
} }
} }
/// Returns `true` if this is a signed integer scalar
#[inline]
pub fn is_signed(&self) -> bool {
match self.primitive() {
Primitive::Int(_, signed) => signed,
_ => false,
}
}
} }
// NOTE: This struct is generic over the FieldIdx for rust-analyzer usage. // NOTE: This struct is generic over the FieldIdx for rust-analyzer usage.
@ -1401,10 +1410,7 @@ impl BackendRepr {
#[inline] #[inline]
pub fn is_signed(&self) -> bool { pub fn is_signed(&self) -> bool {
match self { match self {
BackendRepr::Scalar(scal) => match scal.primitive() { BackendRepr::Scalar(scal) => scal.is_signed(),
Primitive::Int(_, signed) => signed,
_ => false,
},
_ => panic!("`is_signed` on non-scalar ABI {self:?}"), _ => panic!("`is_signed` on non-scalar ABI {self:?}"),
} }
} }
@ -1499,7 +1505,11 @@ impl BackendRepr {
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> { pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
/// Single enum variants, structs/tuples, unions, and all non-ADTs. /// Single enum variants, structs/tuples, unions, and all non-ADTs.
Single { index: VariantIdx }, Single {
/// Always 0 for non-enums/generators.
/// For enums without a variant, this is an invalid index!
index: VariantIdx,
},
/// Enum-likes with more than one variant: each variant comes with /// Enum-likes with more than one variant: each variant comes with
/// a *discriminant* (usually the same as the variant index but the user can /// a *discriminant* (usually the same as the variant index but the user can
@ -1528,14 +1538,22 @@ pub enum TagEncoding<VariantIdx: Idx> {
/// The variant `untagged_variant` contains a niche at an arbitrary /// The variant `untagged_variant` contains a niche at an arbitrary
/// offset (field `tag_field` of the enum), which for a variant with /// offset (field `tag_field` of the enum), which for a variant with
/// discriminant `d` is set to /// discriminant `d` is set to
/// `(d - niche_variants.start).wrapping_add(niche_start)`. /// `(d - niche_variants.start).wrapping_add(niche_start)`
/// (this is wrapping arithmetic using the type of the niche field).
/// ///
/// For example, `Option<(usize, &T)>` is represented such that /// For example, `Option<(usize, &T)>` is represented such that
/// `None` has a null pointer for the second tuple field, and /// `None` has a null pointer for the second tuple field, and
/// `Some` is the identity function (with a non-null reference). /// `Some` is the identity function (with a non-null reference).
///
/// Other variants that are not `untagged_variant` and that are outside the `niche_variants`
/// range cannot be represented; they must be uninhabited.
Niche { Niche {
untagged_variant: VariantIdx, untagged_variant: VariantIdx,
/// This range *may* contain `untagged_variant`; that is then just a "dead value" and
/// not used to encode anything.
niche_variants: RangeInclusive<VariantIdx>, niche_variants: RangeInclusive<VariantIdx>,
/// This is inbounds of the type of the niche field
/// (not sign-extended, i.e., all bits beyond the niche field size are 0).
niche_start: u128, niche_start: u128,
}, },
} }

View file

@ -2,6 +2,7 @@
use rustc_abi::VariantIdx; use rustc_abi::VariantIdx;
use rustc_middle::query::{Key, TyCtxtAt}; use rustc_middle::query::{Key, TyCtxtAt};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::{bug, mir}; use rustc_middle::{bug, mir};
use tracing::instrument; use tracing::instrument;
@ -85,5 +86,6 @@ pub fn tag_for_variant_provider<'tcx>(
crate::const_eval::DummyMachine, crate::const_eval::DummyMachine,
); );
ecx.tag_for_variant(ty, variant_index).unwrap().map(|(tag, _tag_field)| tag) let layout = ecx.layout_of(ty).unwrap();
ecx.tag_for_variant(layout, variant_index).unwrap().map(|(tag, _tag_field)| tag)
} }

View file

@ -1,7 +1,7 @@
//! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines). //! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines).
use rustc_abi::{self as abi, TagEncoding, VariantIdx, Variants}; use rustc_abi::{self as abi, TagEncoding, VariantIdx, Variants};
use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt}; use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout};
use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty}; use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty};
use rustc_middle::{mir, span_bug}; use rustc_middle::{mir, span_bug};
use tracing::{instrument, trace}; use tracing::{instrument, trace};
@ -21,17 +21,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
variant_index: VariantIdx, variant_index: VariantIdx,
dest: &impl Writeable<'tcx, M::Provenance>, dest: &impl Writeable<'tcx, M::Provenance>,
) -> InterpResult<'tcx> { ) -> InterpResult<'tcx> {
// Layout computation excludes uninhabited variants from consideration match self.tag_for_variant(dest.layout(), variant_index)? {
// therefore there's no way to represent those variants in the given layout.
// Essentially, uninhabited variants do not have a tag that corresponds to their
// discriminant, so we cannot do anything here.
// When evaluating we will always error before even getting here, but ConstProp 'executes'
// dead code, so we cannot ICE here.
if dest.layout().for_variant(self, variant_index).is_uninhabited() {
throw_ub!(UninhabitedEnumVariantWritten(variant_index))
}
match self.tag_for_variant(dest.layout().ty, variant_index)? {
Some((tag, tag_field)) => { Some((tag, tag_field)) => {
// No need to validate that the discriminant here because the // No need to validate that the discriminant here because the
// `TyAndLayout::for_variant()` call earlier already checks the // `TyAndLayout::for_variant()` call earlier already checks the
@ -80,7 +70,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
if ty.is_enum() { if ty.is_enum() {
// Hilariously, `Single` is used even for 0-variant enums. // Hilariously, `Single` is used even for 0-variant enums.
// (See https://github.com/rust-lang/rust/issues/89765). // (See https://github.com/rust-lang/rust/issues/89765).
if matches!(ty.kind(), ty::Adt(def, ..) if def.variants().is_empty()) { if ty.ty_adt_def().unwrap().variants().is_empty() {
throw_ub!(UninhabitedEnumVariantRead(index)) throw_ub!(UninhabitedEnumVariantRead(index))
} }
// For consistency with `write_discriminant`, and to make sure that // For consistency with `write_discriminant`, and to make sure that
@ -188,6 +178,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let variants = let variants =
ty.ty_adt_def().expect("tagged layout for non adt").variants(); ty.ty_adt_def().expect("tagged layout for non adt").variants();
assert!(variant_index < variants.next_index()); assert!(variant_index < variants.next_index());
if variant_index == untagged_variant {
// The untagged variant can be in the niche range, but even then it
// is not a valid encoding.
throw_ub!(InvalidTag(Scalar::from_uint(tag_bits, tag_layout.size)))
}
variant_index variant_index
} else { } else {
untagged_variant untagged_variant
@ -236,10 +231,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
/// given field index. /// given field index.
pub(crate) fn tag_for_variant( pub(crate) fn tag_for_variant(
&self, &self,
ty: Ty<'tcx>, layout: TyAndLayout<'tcx>,
variant_index: VariantIdx, variant_index: VariantIdx,
) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> { ) -> InterpResult<'tcx, Option<(ScalarInt, usize)>> {
match self.layout_of(ty)?.variants { // Layout computation excludes uninhabited variants from consideration.
// Therefore, there's no way to represent those variants in the given layout.
// Essentially, uninhabited variants do not have a tag that corresponds to their
// discriminant, so we have to bail out here.
if layout.for_variant(self, variant_index).is_uninhabited() {
throw_ub!(UninhabitedEnumVariantWritten(variant_index))
}
match layout.variants {
abi::Variants::Single { .. } => { abi::Variants::Single { .. } => {
// The tag of a `Single` enum is like the tag of the niched // The tag of a `Single` enum is like the tag of the niched
// variant: there's no tag as the discriminant is encoded // variant: there's no tag as the discriminant is encoded
@ -260,7 +263,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// raw discriminants for enums are isize or bigger during // raw discriminants for enums are isize or bigger during
// their computation, but the in-memory tag is the smallest possible // their computation, but the in-memory tag is the smallest possible
// representation // representation
let discr = self.discriminant_for_variant(ty, variant_index)?; let discr = self.discriminant_for_variant(layout.ty, variant_index)?;
let discr_size = discr.layout.size; let discr_size = discr.layout.size;
let discr_val = discr.to_scalar().to_bits(discr_size)?; let discr_val = discr.to_scalar().to_bits(discr_size)?;
let tag_size = tag_layout.size(self); let tag_size = tag_layout.size(self);
@ -286,11 +289,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
.. ..
} => { } => {
assert!(variant_index != untagged_variant); assert!(variant_index != untagged_variant);
// We checked that this variant is inhabited, so it must be in the niche range.
assert!(
niche_variants.contains(&variant_index),
"invalid variant index for this enum"
);
let variants_start = niche_variants.start().as_u32(); let variants_start = niche_variants.start().as_u32();
let variant_index_relative = variant_index let variant_index_relative = variant_index.as_u32().strict_sub(variants_start);
.as_u32()
.checked_sub(variants_start)
.expect("overflow computing relative variant idx");
// We need to use machine arithmetic when taking into account `niche_start`: // We need to use machine arithmetic when taking into account `niche_start`:
// tag_val = variant_index_relative + niche_start_val // tag_val = variant_index_relative + niche_start_val
let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?; let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;

View file

@ -10,6 +10,7 @@
#![feature(never_type)] #![feature(never_type)]
#![feature(rustdoc_internals)] #![feature(rustdoc_internals)]
#![feature(slice_ptr_get)] #![feature(slice_ptr_get)]
#![feature(strict_overflow_ops)]
#![feature(trait_alias)] #![feature(trait_alias)]
#![feature(try_blocks)] #![feature(try_blocks)]
#![feature(unqualified_local_imports)] #![feature(unqualified_local_imports)]

View file

@ -7,10 +7,11 @@ Erroneous code example:
#![allow(internal_features)] #![allow(internal_features)]
extern "rust-intrinsic" { extern "rust-intrinsic" {
pub static breakpoint: fn(); // error: intrinsic must be a function pub static atomic_singlethreadfence_seqcst: fn();
// error: intrinsic must be a function
} }
fn main() { unsafe { breakpoint(); } } fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
``` ```
An intrinsic is a function available for use in a given programming language An intrinsic is a function available for use in a given programming language
@ -22,8 +23,8 @@ error, just declare a function. Example:
#![allow(internal_features)] #![allow(internal_features)]
extern "rust-intrinsic" { extern "rust-intrinsic" {
pub fn breakpoint(); // ok! pub fn atomic_singlethreadfence_seqcst(); // ok!
} }
fn main() { unsafe { breakpoint(); } } fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
``` ```

View file

@ -119,6 +119,13 @@ declare_features! (
(removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")), (removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")),
/// Allows defining generators. /// Allows defining generators.
(removed, generators, "1.21.0", Some(43122), Some("renamed to `coroutines`")), (removed, generators, "1.21.0", Some(43122), Some("renamed to `coroutines`")),
/// An extension to the `generic_associated_types` feature, allowing incomplete features.
(removed, generic_associated_types_extended, "CURRENT_RUSTC_VERSION", Some(95451),
Some(
"feature needs overhaul and reimplementation pending \
better implied higher-ranked implied bounds support"
)
),
/// Allows `impl Trait` in bindings (`let`, `const`, `static`). /// Allows `impl Trait` in bindings (`let`, `const`, `static`).
(removed, impl_trait_in_bindings, "1.55.0", Some(63065), (removed, impl_trait_in_bindings, "1.55.0", Some(63065),
Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")), Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")),

View file

@ -499,8 +499,6 @@ declare_features! (
(unstable, gen_blocks, "1.75.0", Some(117078)), (unstable, gen_blocks, "1.75.0", Some(117078)),
/// Infer generic args for both consts and types. /// Infer generic args for both consts and types.
(unstable, generic_arg_infer, "1.55.0", Some(85077)), (unstable, generic_arg_infer, "1.55.0", Some(85077)),
/// An extension to the `generic_associated_types` feature, allowing incomplete features.
(incomplete, generic_associated_types_extended, "1.61.0", Some(95451)),
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers /// Allows non-trivial generic constants which have to have wfness manually propagated to callers
(incomplete, generic_const_exprs, "1.56.0", Some(76560)), (incomplete, generic_const_exprs, "1.56.0", Some(76560)),
/// Allows generic parameters and where-clauses on free & associated const items. /// Allows generic parameters and where-clauses on free & associated const items.

View file

@ -87,6 +87,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
| sym::assert_inhabited | sym::assert_inhabited
| sym::assert_zero_valid | sym::assert_zero_valid
| sym::assert_mem_uninitialized_valid | sym::assert_mem_uninitialized_valid
| sym::breakpoint
| sym::size_of | sym::size_of
| sym::min_align_of | sym::min_align_of
| sym::needs_drop | sym::needs_drop

View file

@ -1081,6 +1081,8 @@ rustc_queries! {
} }
/// Computes the tag (if any) for a given type and variant. /// Computes the tag (if any) for a given type and variant.
/// `None` means that the variant doesn't need a tag (because it is niched).
/// Will panic for uninhabited variants.
query tag_for_variant( query tag_for_variant(
key: (Ty<'tcx>, abi::VariantIdx) key: (Ty<'tcx>, abi::VariantIdx)
) -> Option<ty::ScalarInt> { ) -> Option<ty::ScalarInt> {

View file

@ -4,7 +4,7 @@ use crate::spec::{Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions, cr
pub(crate) fn opts() -> TargetOptions { pub(crate) fn opts() -> TargetOptions {
TargetOptions { TargetOptions {
abi: "vec-extabi".into(), abi: "vec-extabi".into(),
code_model: Some(CodeModel::Small), code_model: Some(CodeModel::Large),
cpu: "pwr7".into(), cpu: "pwr7".into(),
os: "aix".into(), os: "aix".into(),
vendor: "ibm".into(), vendor: "ibm".into(),

View file

@ -328,10 +328,7 @@ pub fn dyn_compatibility_violations_for_assoc_item(
.collect(), .collect(),
// Associated types can only be dyn-compatible if they have `Self: Sized` bounds. // Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
ty::AssocKind::Type => { ty::AssocKind::Type => {
if !tcx.features().generic_associated_types_extended() if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
&& !tcx.generics_of(item.def_id).is_own_empty()
&& !item.is_impl_trait_in_trait()
{
vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)] vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)]
} else { } else {
// We will permit associated types if they are explicitly mentioned in the trait object. // We will permit associated types if they are explicitly mentioned in the trait object.

View file

@ -14,7 +14,7 @@ use rustc_middle::traits::select::OverflowError;
use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData}; use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData};
use rustc_middle::ty::fast_reject::DeepRejectCtxt; use rustc_middle::ty::fast_reject::DeepRejectCtxt;
use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::fold::TypeFoldable;
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable, TypeVisitableExt}; use rustc_middle::ty::visit::TypeVisitableExt;
use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast}; use rustc_middle::ty::{self, Term, Ty, TyCtxt, TypingMode, Upcast};
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -179,35 +179,11 @@ pub(super) fn poly_project_and_unify_term<'cx, 'tcx>(
) -> ProjectAndUnifyResult<'tcx> { ) -> ProjectAndUnifyResult<'tcx> {
let infcx = selcx.infcx; let infcx = selcx.infcx;
let r = infcx.commit_if_ok(|_snapshot| { let r = infcx.commit_if_ok(|_snapshot| {
let old_universe = infcx.universe();
let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate); let placeholder_predicate = infcx.enter_forall_and_leak_universe(obligation.predicate);
let new_universe = infcx.universe();
let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate); let placeholder_obligation = obligation.with(infcx.tcx, placeholder_predicate);
match project_and_unify_term(selcx, &placeholder_obligation) { match project_and_unify_term(selcx, &placeholder_obligation) {
ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e), ProjectAndUnifyResult::MismatchedProjectionTypes(e) => Err(e),
ProjectAndUnifyResult::Holds(obligations)
if old_universe != new_universe
&& selcx.tcx().features().generic_associated_types_extended() =>
{
// If the `generic_associated_types_extended` feature is active, then we ignore any
// obligations references lifetimes from any universe greater than or equal to the
// universe just created. Otherwise, we can end up with something like `for<'a> I: 'a`,
// which isn't quite what we want. Ideally, we want either an implied
// `for<'a where I: 'a> I: 'a` or we want to "lazily" check these hold when we
// instantiate concrete regions. There is design work to be done here; until then,
// however, this allows experimenting potential GAT features without running into
// well-formedness issues.
let new_obligations = obligations
.into_iter()
.filter(|obligation| {
let mut visitor = MaxUniverse::new();
obligation.predicate.visit_with(&mut visitor);
visitor.max_universe() < new_universe
})
.collect();
Ok(ProjectAndUnifyResult::Holds(new_obligations))
}
other => Ok(other), other => Ok(other),
} }
}); });

View file

@ -626,7 +626,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
for assoc_type in assoc_types { for assoc_type in assoc_types {
let defs: &ty::Generics = tcx.generics_of(assoc_type); let defs: &ty::Generics = tcx.generics_of(assoc_type);
if !defs.own_params.is_empty() && !tcx.features().generic_associated_types_extended() { if !defs.own_params.is_empty() {
tcx.dcx().span_delayed_bug( tcx.dcx().span_delayed_bug(
obligation.cause.span, obligation.cause.span,
"GATs in trait object shouldn't have been considered", "GATs in trait object shouldn't have been considered",

View file

@ -319,11 +319,15 @@ pub(crate) mod rustc {
) -> Result<Self, Err> { ) -> Result<Self, Err> {
assert!(def.is_enum()); assert!(def.is_enum());
// Computes the variant of a given index. // Computes the layout of a variant.
let layout_of_variant = |index, encoding: Option<TagEncoding<VariantIdx>>| { let layout_of_variant =
|index, encoding: Option<TagEncoding<VariantIdx>>| -> Result<Self, Err> {
let variant_layout = ty_variant(cx, (ty, layout), index);
if variant_layout.is_uninhabited() {
return Ok(Self::uninhabited());
}
let tag = cx.tcx().tag_for_variant((cx.tcx().erase_regions(ty), index)); let tag = cx.tcx().tag_for_variant((cx.tcx().erase_regions(ty), index));
let variant_def = Def::Variant(def.variant(index)); let variant_def = Def::Variant(def.variant(index));
let variant_layout = ty_variant(cx, (ty, layout), index);
Self::from_variant( Self::from_variant(
variant_def, variant_def,
tag.map(|tag| (tag, index, encoding.unwrap())), tag.map(|tag| (tag, index, encoding.unwrap())),
@ -333,25 +337,18 @@ pub(crate) mod rustc {
) )
}; };
// We consider three kinds of enums, each demanding a different
// treatment of their layout computation:
// 1. enums that are uninhabited ZSTs
// 2. enums that delegate their layout to a variant
// 3. enums with multiple variants
match layout.variants() { match layout.variants() {
Variants::Single { .. } if layout.is_uninhabited() && layout.size == Size::ZERO => {
// The layout representation of uninhabited, ZST enums is
// defined to be like that of the `!` type, as opposed of a
// typical enum. Consequently, they cannot be descended into
// as if they typical enums. We therefore special-case this
// scenario and simply return an uninhabited `Tree`.
Ok(Self::uninhabited())
}
Variants::Single { index } => { Variants::Single { index } => {
// Hilariously, `Single` is used even for 0-variant enums;
// `index` is just junk in that case.
if ty.ty_adt_def().unwrap().variants().is_empty() {
Ok(Self::uninhabited())
} else {
// `Variants::Single` on enums with variants denotes that // `Variants::Single` on enums with variants denotes that
// the enum delegates its layout to the variant at `index`. // the enum delegates its layout to the variant at `index`.
layout_of_variant(*index, None) layout_of_variant(*index, None)
} }
}
Variants::Multiple { tag, tag_encoding, tag_field, .. } => { Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
// `Variants::Multiple` denotes an enum with multiple // `Variants::Multiple` denotes an enum with multiple
// variants. The layout of such an enum is the disjunction // variants. The layout of such an enum is the disjunction
@ -369,7 +366,7 @@ pub(crate) mod rustc {
}, },
)?; )?;
return Ok(Self::def(Def::Adt(def)).then(variants)); Ok(Self::def(Def::Adt(def)).then(variants))
} }
} }
} }

View file

@ -81,7 +81,7 @@ fn layout_of<'tcx>(
record_layout_for_printing(&cx, layout); record_layout_for_printing(&cx, layout);
} }
invariant::partially_check_layout(&cx, &layout); invariant::layout_sanity_check(&cx, &layout);
Ok(layout) Ok(layout)
} }

View file

@ -1,11 +1,11 @@
use std::assert_matches::assert_matches; use std::assert_matches::assert_matches;
use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, Variants}; use rustc_abi::{BackendRepr, FieldsShape, Scalar, Size, TagEncoding, Variants};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout};
/// Enforce some basic invariants on layouts. /// Enforce some basic invariants on layouts.
pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) { pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) {
let tcx = cx.tcx(); let tcx = cx.tcx();
// Type-level uninhabitedness should always imply ABI uninhabitedness. // Type-level uninhabitedness should always imply ABI uninhabitedness.
@ -241,7 +241,17 @@ pub(super) fn partially_check_layout<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLa
check_layout_abi(cx, layout); check_layout_abi(cx, layout);
if let Variants::Multiple { variants, .. } = &layout.variants { if let Variants::Multiple { variants, tag, tag_encoding, .. } = &layout.variants {
if let TagEncoding::Niche { niche_start, untagged_variant, niche_variants } = tag_encoding {
let niche_size = tag.size(cx);
assert!(*niche_start <= niche_size.unsigned_int_max());
for (idx, variant) in variants.iter_enumerated() {
// Ensure all inhabited variants are accounted for.
if !variant.is_uninhabited() {
assert!(idx == *untagged_variant || niche_variants.contains(&idx));
}
}
}
for variant in variants.iter() { for variant in variants.iter() {
// No nested "multiple". // No nested "multiple".
assert_matches!(variant.variants, Variants::Single { .. }); assert_matches!(variant.variants, Variants::Single { .. });

View file

@ -42,3 +42,30 @@ pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?)
pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) { pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) {
/* compiler built-in */ /* compiler built-in */
} }
/// Compiles to a target-specific software breakpoint instruction or equivalent.
///
/// This will typically abort the program. It may result in a core dump, and/or the system logging
/// debug information. Additional target-specific capabilities may be possible depending on
/// debuggers or other tooling; in particular, a debugger may be able to resume execution.
///
/// If possible, this will produce an instruction sequence that allows a debugger to resume *after*
/// the breakpoint, rather than resuming *at* the breakpoint; however, the exact behavior is
/// target-specific and debugger-specific, and not guaranteed.
///
/// If the target platform does not have any kind of debug breakpoint instruction, this may compile
/// to a trapping instruction (e.g. an undefined instruction) instead, or to some other form of
/// target-specific abort that may or may not support convenient resumption.
///
/// The precise behavior and the precise instruction generated are not guaranteed, except that in
/// normal execution with no debug tooling involved this will not continue executing.
///
/// - On x86 targets, this produces an `int3` instruction.
/// - On aarch64 targets, this produces a `brk #0xf000` instruction.
// When stabilizing this, update the comment on `core::intrinsics::breakpoint`.
#[unstable(feature = "breakpoint", issue = "133724")]
#[inline(always)]
#[cfg(not(bootstrap))]
pub fn breakpoint() {
core::intrinsics::breakpoint();
}

View file

@ -1381,6 +1381,18 @@ pub unsafe fn prefetch_write_instruction<T>(_data: *const T, _locality: i32) {
#[rustc_intrinsic] #[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden] #[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind] #[rustc_nounwind]
#[cfg(not(bootstrap))]
pub fn breakpoint() {
unreachable!()
}
/// Executes a breakpoint trap, for inspection by a debugger.
///
/// This intrinsic does not have a stable counterpart.
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
#[rustc_nounwind]
#[cfg(bootstrap)]
pub unsafe fn breakpoint() { pub unsafe fn breakpoint() {
unreachable!() unreachable!()
} }

View file

@ -1021,11 +1021,11 @@ impl Drop for PanicGuard {
/// ///
/// # Memory Ordering /// # Memory Ordering
/// ///
/// Calls to `park` _synchronize-with_ calls to `unpark`, meaning that memory /// Calls to `unpark` _synchronize-with_ calls to `park`, meaning that memory
/// operations performed before a call to `unpark` are made visible to the thread that /// operations performed before a call to `unpark` are made visible to the thread that
/// consumes the token and returns from `park`. Note that all `park` and `unpark` /// consumes the token and returns from `park`. Note that all `park` and `unpark`
/// operations for a given thread form a total order and `park` synchronizes-with /// operations for a given thread form a total order and _all_ prior `unpark` operations
/// _all_ prior `unpark` operations. /// synchronize-with `park`.
/// ///
/// In atomic ordering terms, `unpark` performs a `Release` operation and `park` /// In atomic ordering terms, `unpark` performs a `Release` operation and `park`
/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same /// performs the corresponding `Acquire` operation. Calls to `unpark` for the same

View file

@ -350,10 +350,13 @@ impl<'test> TestCx<'test> {
} }
} else { } else {
if proc_res.status.success() { if proc_res.status.success() {
self.fatal_proc_rec( {
&format!("{} test compiled successfully!", self.config.mode)[..], self.error(&format!("{} test did not emit an error", self.config.mode));
proc_res, if self.config.mode == crate::common::Mode::Ui {
); println!("note: by default, ui tests are expected not to compile");
}
proc_res.fatal(None, || ());
};
} }
if !self.props.dont_check_failure_status { if !self.props.dont_check_failure_status {

View file

@ -1,7 +1,5 @@
#![feature(core_intrinsics)] #![feature(core_intrinsics)]
fn main() { fn main() {
unsafe { core::intrinsics::breakpoint(); //~ ERROR: trace/breakpoint trap
core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap
};
} }

View file

@ -1,7 +1,7 @@
error: abnormal termination: trace/breakpoint trap error: abnormal termination: trace/breakpoint trap
--> tests/fail/breakpoint.rs:LL:CC --> tests/fail/breakpoint.rs:LL:CC
| |
LL | core::intrinsics::breakpoint() LL | core::intrinsics::breakpoint();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
| |
= note: BACKTRACE: = note: BACKTRACE:

View file

@ -0,0 +1,27 @@
// Validity makes this fail at the wrong place.
//@compile-flags: -Zmiri-disable-validation
use std::mem;
// This enum has untagged variant idx 1, with niche_variants being 0..=2
// and niche_start being 2.
// That means the untagged variants is in the niche variant range!
// However, using the corresponding value (2+1 = 3) is not a valid encoding of this variant.
#[derive(Copy, Clone, PartialEq)]
enum Foo {
Var1,
Var2(bool),
Var3,
}
fn main() {
unsafe {
assert!(Foo::Var2(false) == mem::transmute(0u8));
assert!(Foo::Var2(true) == mem::transmute(1u8));
assert!(Foo::Var1 == mem::transmute(2u8));
assert!(Foo::Var3 == mem::transmute(4u8));
let invalid: Foo = mem::transmute(3u8);
assert!(matches!(invalid, Foo::Var2(_)));
//~^ ERROR: invalid tag
}
}

View file

@ -0,0 +1,15 @@
error: Undefined Behavior: enum value has invalid tag: 0x03
--> tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC
|
LL | assert!(matches!(invalid, Foo::Var2(_)));
| ^^^^^^^ enum value has invalid tag: 0x03
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at tests/fail/enum-untagged-variant-invalid-encoding.rs:LL:CC
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error

View file

@ -10,4 +10,4 @@ name = "wasm-component-ld"
path = "src/main.rs" path = "src/main.rs"
[dependencies] [dependencies]
wasm-component-ld = "0.5.10" wasm-component-ld = "0.5.11"

View file

@ -0,0 +1,14 @@
//@ revisions: aarch64 x86_64
//@ assembly-output: emit-asm
//@[aarch64] only-aarch64
//@[x86_64] only-x86_64
#![feature(breakpoint)]
#![crate_type = "lib"]
// CHECK-LABEL: use_bp
// aarch64: brk #0xf000
// x86_64: int3
pub fn use_bp() {
core::arch::breakpoint();
}

View file

@ -1,30 +0,0 @@
//@ known-bug: rust-lang/rust#126267
#![feature(transmutability)]
#![crate_type = "lib"]
pub enum ApiError {}
pub struct TokioError {
b: bool,
}
pub enum Error {
Api { source: ApiError },
Ethereum,
Tokio { source: TokioError },
}
mod assert {
use std::mem::TransmuteFrom;
pub fn is_transmutable<Src, Dst>()
where
Dst: TransmuteFrom<Src>, // safety is NOT assumed
{
}
}
fn test() {
struct Src;
type Dst = Error;
assert::is_transmutable::<Src, Dst>();
}

View file

@ -1,13 +0,0 @@
//@ known-bug: #131538
#![feature(generic_associated_types_extended)]
#![feature(trivial_bounds)]
trait HealthCheck {
async fn check<const N: usize>();
}
fn do_health_check_par()
where
HealthCheck: HealthCheck,
{
}

View file

@ -1,6 +1,6 @@
#![feature(intrinsics)] #![feature(intrinsics)]
extern "rust-intrinsic" { extern "rust-intrinsic" {
pub static breakpoint : unsafe extern "rust-intrinsic" fn(); pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn();
//~^ ERROR intrinsic must be a function [E0622] //~^ ERROR intrinsic must be a function [E0622]
} }
fn main() { unsafe { breakpoint(); } } fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }

View file

@ -1,8 +1,8 @@
error[E0622]: intrinsic must be a function error[E0622]: intrinsic must be a function
--> $DIR/E0622.rs:3:5 --> $DIR/E0622.rs:3:5
| |
LL | pub static breakpoint : unsafe extern "rust-intrinsic" fn(); LL | pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -1,4 +0,0 @@
// This feature doesn't *currently* fire on any specific code; it's just a
// behavior change. Future changes might.
#[rustc_error] //~ the
fn main() {}

View file

@ -1,12 +0,0 @@
error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
--> $DIR/feature-gate-generic_associated_types_extended.rs:3:1
|
LL | #[rustc_error]
| ^^^^^^^^^^^^^^
|
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -1,9 +1,4 @@
//@ revisions: base extended //@ known-bug: #133805
//@[base] check-fail
//@[extended] check-pass
#![cfg_attr(extended, feature(generic_associated_types_extended))]
#![cfg_attr(extended, allow(incomplete_features))]
pub trait FromLendingIterator<A>: Sized { pub trait FromLendingIterator<A>: Sized {
fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
@ -11,7 +6,6 @@ pub trait FromLendingIterator<A>: Sized {
impl<A> FromLendingIterator<A> for Vec<A> { impl<A> FromLendingIterator<A> for Vec<A> {
fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
//[base]~^ impl has stricter
let mut v = vec![]; let mut v = vec![];
while let Some(item) = iter.next() { while let Some(item) = iter.next() {
v.push(item); v.push(item);
@ -32,7 +26,6 @@ pub trait LendingIterator {
Self: for<'q> LendingIterator<Item<'q> = A>, Self: for<'q> LendingIterator<Item<'q> = A>,
{ {
<B as FromLendingIterator<A>>::from_iter(self) <B as FromLendingIterator<A>>::from_iter(self)
//[base]~^ ERROR: does not live long enough
} }
} }

View file

@ -1,5 +1,5 @@
error[E0276]: impl has stricter requirements than trait error[E0276]: impl has stricter requirements than trait
--> $DIR/lending_iterator.rs:13:45 --> $DIR/lending_iterator.rs:8:45
| |
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
| ------------------------------------------------------------------------ definition of `from_iter` from trait | ------------------------------------------------------------------------ definition of `from_iter` from trait
@ -8,7 +8,7 @@ LL | fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) ->
| ^^^^^^^^^^^^ impl has extra requirement `I: 'x` | ^^^^^^^^^^^^ impl has extra requirement `I: 'x`
error: `Self` does not live long enough error: `Self` does not live long enough
--> $DIR/lending_iterator.rs:34:9 --> $DIR/lending_iterator.rs:28:9
| |
LL | <B as FromLendingIterator<A>>::from_iter(self) LL | <B as FromLendingIterator<A>>::from_iter(self)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

View file

@ -1,9 +1,4 @@
//@ revisions: base extended //@ known-bug: #133805
//@[base] check-fail
//@[extended] check-pass
#![cfg_attr(extended, feature(generic_associated_types_extended))]
#![cfg_attr(extended, allow(incomplete_features))]
pub trait FromLendingIterator<A>: Sized { pub trait FromLendingIterator<A>: Sized {
fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
@ -11,7 +6,6 @@ pub trait FromLendingIterator<A>: Sized {
impl<A> FromLendingIterator<A> for Vec<A> { impl<A> FromLendingIterator<A> for Vec<A> {
fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self { fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
//[base]~^ impl has stricter
let mut v = vec![]; let mut v = vec![];
while let Some(item) = iter.next() { while let Some(item) = iter.next() {
v.push(item); v.push(item);

View file

@ -1,5 +1,5 @@
error[E0276]: impl has stricter requirements than trait error[E0276]: impl has stricter requirements than trait
--> $DIR/lending_iterator_2.rs:13:45 --> $DIR/lending_iterator_2.rs:8:45
| |
LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self; LL | fn from_iter<T: for<'x> LendingIterator<Item<'x> = A>>(iter: T) -> Self;
| ------------------------------------------------------------------------ definition of `from_iter` from trait | ------------------------------------------------------------------------ definition of `from_iter` from trait

View file

@ -1,10 +1,6 @@
//@ revisions: base extended //@ check-fail
//@[base] check-fail
//@[extended] check-pass
#![feature(associated_type_defaults)] #![feature(associated_type_defaults)]
#![cfg_attr(extended, feature(generic_associated_types_extended))]
#![cfg_attr(extended, allow(incomplete_features))]
trait Foo { trait Foo {
type A<'a> where Self: 'a; type A<'a> where Self: 'a;
@ -24,12 +20,12 @@ impl<T> Foo for Fooer<T> {
} }
fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {} fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
//[base]~^ the trait `Foo` cannot be made into an object //~^ the trait `Foo` cannot be made into an object
fn main() { fn main() {
let foo = Fooer(5); let foo = Fooer(5);
f(Box::new(foo)); f(Box::new(foo));
//[base]~^ the trait `Foo` cannot be made into an object //~^ the trait `Foo` cannot be made into an object
//[base]~| the trait `Foo` cannot be made into an object //~| the trait `Foo` cannot be made into an object
} }

View file

@ -0,0 +1,58 @@
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/gat-in-trait-path.rs:22:17
|
LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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/gat-in-trait-path.rs:6:10
|
LL | trait Foo {
| --- this trait cannot be made into an object...
LL | type A<'a> where Self: 'a;
| ^ ...because it contains the generic associated type `A`
= help: consider moving `A` to another trait
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
Fooy
Fooer<T>
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/gat-in-trait-path.rs:28:5
|
LL | f(Box::new(foo));
| ^^^^^^^^^^^^^ `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/gat-in-trait-path.rs:6:10
|
LL | trait Foo {
| --- this trait cannot be made into an object...
LL | type A<'a> where Self: 'a;
| ^ ...because it contains the generic associated type `A`
= help: consider moving `A` to another trait
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
Fooy
Fooer<T>
error[E0038]: the trait `Foo` cannot be made into an object
--> $DIR/gat-in-trait-path.rs:28:5
|
LL | f(Box::new(foo));
| ^^^^^^^^^^^^^ `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/gat-in-trait-path.rs:6:10
|
LL | trait Foo {
| --- this trait cannot be made into an object...
LL | type A<'a> where Self: 'a;
| ^ ...because it contains the generic associated type `A`
= help: consider moving `A` to another trait
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `Foo` for this new enum and using it instead:
Fooy
Fooer<T>
= note: required for the cast from `Box<Fooer<{integer}>>` to `Box<(dyn Foo<A<'a> = &'a ()> + 'static)>`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0038`.

View file

@ -1,15 +1,10 @@
//@ revisions: base extended //@ check-fail
//@[base] check-fail
//@[extended] check-pass
#![cfg_attr(extended, feature(generic_associated_types_extended))]
#![cfg_attr(extended, allow(incomplete_features))]
trait X { trait X {
type Y<'a>; type Y<'a>;
} }
fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {} fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
//[base]~^ ERROR the trait `X` cannot be made into an object //~^ ERROR the trait `X` cannot be made into an object
fn main() {} fn main() {}

View file

@ -0,0 +1,18 @@
error[E0038]: the trait `X` cannot be made into an object
--> $DIR/issue-67510-pass.rs:7:23
|
LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
| ^^^^^^^^^^^^^^^^^^^ `X` 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/issue-67510-pass.rs:4:10
|
LL | trait X {
| - this trait cannot be made into an object...
LL | type Y<'a>;
| ^ ...because it contains the generic associated type `Y`
= help: consider moving `Y` to another trait
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0038`.

View file

@ -1,8 +1,3 @@
//@ revisions: base extended
#![cfg_attr(extended, feature(generic_associated_types_extended))]
#![cfg_attr(extended, allow(incomplete_features))]
pub trait SubTrait {} pub trait SubTrait {}
pub trait SuperTrait { pub trait SuperTrait {
@ -38,6 +33,6 @@ impl SuperTrait for SuperStruct {
fn main() { fn main() {
let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0)); let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
//~^ ERROR missing generics for associated type //~^ ERROR missing generics for associated type
//[base]~^^ ERROR the trait //~^^ ERROR the trait
//[base]~| ERROR the trait //~| ERROR the trait
} }

View file

@ -0,0 +1,55 @@
error[E0107]: missing generics for associated type `SuperTrait::SubType`
--> $DIR/issue-76535.rs:34:33
|
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
| ^^^^^^^ expected 1 lifetime argument
|
note: associated type defined here, with 1 lifetime parameter: `'a`
--> $DIR/issue-76535.rs:4:10
|
LL | type SubType<'a>: SubTrait where Self: 'a;
| ^^^^^^^ --
help: add missing lifetime argument
|
LL | let sub: Box<dyn SuperTrait<SubType<'a> = SubStruct>> = Box::new(SuperStruct::new(0));
| ++++
error[E0038]: the trait `SuperTrait` cannot be made into an object
--> $DIR/issue-76535.rs:34:14
|
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` 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/issue-76535.rs:4:10
|
LL | pub trait SuperTrait {
| ---------- this trait cannot be made into an object...
LL | type SubType<'a>: SubTrait where Self: 'a;
| ^^^^^^^ ...because it contains the generic associated type `SubType`
= help: consider moving `SubType` to another trait
= help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead
= note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
error[E0038]: the trait `SuperTrait` cannot be made into an object
--> $DIR/issue-76535.rs:34:57
|
LL | let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` 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/issue-76535.rs:4:10
|
LL | pub trait SuperTrait {
| ---------- this trait cannot be made into an object...
LL | type SubType<'a>: SubTrait where Self: 'a;
| ^^^^^^^ ...because it contains the generic associated type `SubType`
= help: consider moving `SubType` to another trait
= help: only type `SuperStruct` is seen to implement the trait in this crate, consider using it directly instead
= note: `SuperTrait` can be implemented in other crates; if you want to support your users passing their own types here, you can't refer to a specific type
= note: required for the cast from `Box<SuperStruct>` to `Box<dyn SuperTrait<SubType<'_> = SubStruct<'_>>>`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0038, E0107.
For more information about an error, try `rustc --explain E0038`.

View file

@ -1,15 +1,10 @@
//@ revisions: base extended
#![cfg_attr(extended, feature(generic_associated_types_extended))]
#![cfg_attr(extended, allow(incomplete_features))]
trait CollectionFamily { trait CollectionFamily {
type Member<T>; type Member<T>;
} }
fn floatify() { fn floatify() {
Box::new(Family) as &dyn CollectionFamily<Member=usize> Box::new(Family) as &dyn CollectionFamily<Member=usize>
//~^ ERROR: missing generics for associated type //~^ ERROR: missing generics for associated type
//[base]~^^ ERROR: the trait `CollectionFamily` cannot be made into an object //~| ERROR: the trait `CollectionFamily` cannot be made into an object
} }
struct Family; struct Family;

View file

@ -0,0 +1,35 @@
error[E0107]: missing generics for associated type `CollectionFamily::Member`
--> $DIR/issue-78671.rs:5:47
|
LL | Box::new(Family) as &dyn CollectionFamily<Member=usize>
| ^^^^^^ expected 1 generic argument
|
note: associated type defined here, with 1 generic parameter: `T`
--> $DIR/issue-78671.rs:2:10
|
LL | type Member<T>;
| ^^^^^^ -
help: add missing generic argument
|
LL | Box::new(Family) as &dyn CollectionFamily<Member<T>=usize>
| +++
error[E0038]: the trait `CollectionFamily` cannot be made into an object
--> $DIR/issue-78671.rs:5:25
|
LL | Box::new(Family) as &dyn CollectionFamily<Member=usize>
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` 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/issue-78671.rs:2:10
|
LL | trait CollectionFamily {
| ---------------- this trait cannot be made into an object...
LL | type Member<T>;
| ^^^^^^ ...because it contains the generic associated type `Member`
= help: consider moving `Member` to another trait
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0038, E0107.
For more information about an error, try `rustc --explain E0038`.

View file

@ -1,8 +1,3 @@
//@ revisions: base extended
#![cfg_attr(extended, feature(generic_associated_types_extended))]
#![cfg_attr(extended, allow(incomplete_features))]
trait RefCont<'a, T> { trait RefCont<'a, T> {
fn t(&'a self) -> &'a T; fn t(&'a self) -> &'a T;
} }
@ -42,9 +37,8 @@ impl<K, V: Default> MapLike<K, V> for Source {
fn main() { fn main() {
let m = Box::new(std::collections::BTreeMap::<u8, u8>::new()) let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
//[base]~^ ERROR the trait //~^ ERROR the trait
//[extended]~^^ type mismatch
as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>; as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
//~^ ERROR missing generics for associated type //~^ ERROR missing generics for associated type
//[base]~^^ ERROR the trait //~| ERROR the trait
} }

View file

@ -0,0 +1,57 @@
error[E0107]: missing generics for associated type `MapLike::VRefCont`
--> $DIR/issue-79422.rs:41:36
|
LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
| ^^^^^^^^ expected 1 lifetime argument
|
note: associated type defined here, with 1 lifetime parameter: `'a`
--> $DIR/issue-79422.rs:18:10
|
LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
| ^^^^^^^^ --
help: add missing lifetime argument
|
LL | as Box<dyn MapLike<u8, u8, VRefCont<'a> = dyn RefCont<'_, u8>>>;
| ++++
error[E0038]: the trait `MapLike` cannot be made into an object
--> $DIR/issue-79422.rs:41:12
|
LL | as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` 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/issue-79422.rs:18:10
|
LL | trait MapLike<K, V> {
| ------- this trait cannot be made into an object...
LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
= help: consider moving `VRefCont` to another trait
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
std::collections::BTreeMap<K, V>
Source
error[E0038]: the trait `MapLike` cannot be made into an object
--> $DIR/issue-79422.rs:39:13
|
LL | let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` 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/issue-79422.rs:18:10
|
LL | trait MapLike<K, V> {
| ------- this trait cannot be made into an object...
LL | type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
| ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
= help: consider moving `VRefCont` to another trait
= help: the following types implement the trait, consider defining an enum where each variant holds one of these types, implementing `MapLike` for this new enum and using it instead:
std::collections::BTreeMap<K, V>
Source
= note: required for the cast from `Box<BTreeMap<u8, u8>>` to `Box<dyn MapLike<u8, u8, VRefCont<'_> = (dyn RefCont<'_, u8> + 'static)>>`
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0038, E0107.
For more information about an error, try `rustc --explain E0038`.

View file

@ -1,8 +1,3 @@
//@ revisions: base extended
#![cfg_attr(extended, feature(generic_associated_types_extended))]
#![cfg_attr(extended, allow(incomplete_features))]
trait StreamingIterator { trait StreamingIterator {
type Item<'a> where Self: 'a; type Item<'a> where Self: 'a;
fn size_hint(&self) -> (usize, Option<usize>); fn size_hint(&self) -> (usize, Option<usize>);
@ -11,11 +6,10 @@ trait StreamingIterator {
} }
fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize { fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
//[base]~^ the trait `StreamingIterator` cannot be made into an object //~^ the trait `StreamingIterator` cannot be made into an object
x.size_hint().0 x.size_hint().0
//[extended]~^ borrowed data escapes //~^ the trait `StreamingIterator` cannot be made into an object
//[base]~^^ the trait `StreamingIterator` cannot be made into an object //~| the trait `StreamingIterator` cannot be made into an object
//[base]~| the trait `StreamingIterator` cannot be made into an object
} }
fn main() {} fn main() {}

View file

@ -0,0 +1,48 @@
error[E0038]: the trait `StreamingIterator` cannot be made into an object
--> $DIR/trait-objects.rs:8:21
|
LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` 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/trait-objects.rs:2:10
|
LL | trait StreamingIterator {
| ----------------- this trait cannot be made into an object...
LL | type Item<'a> where Self: 'a;
| ^^^^ ...because it contains the generic associated type `Item`
= help: consider moving `Item` to another trait
error[E0038]: the trait `StreamingIterator` cannot be made into an object
--> $DIR/trait-objects.rs:10:7
|
LL | x.size_hint().0
| ^^^^^^^^^ `StreamingIterator` 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/trait-objects.rs:2:10
|
LL | trait StreamingIterator {
| ----------------- this trait cannot be made into an object...
LL | type Item<'a> where Self: 'a;
| ^^^^ ...because it contains the generic associated type `Item`
= help: consider moving `Item` to another trait
error[E0038]: the trait `StreamingIterator` cannot be made into an object
--> $DIR/trait-objects.rs:10:5
|
LL | x.size_hint().0
| ^^^^^^^^^^^^^ `StreamingIterator` 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/trait-objects.rs:2:10
|
LL | trait StreamingIterator {
| ----------------- this trait cannot be made into an object...
LL | type Item<'a> where Self: 'a;
| ^^^^ ...because it contains the generic associated type `Item`
= help: consider moving `Item` to another trait
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0038`.

View file

@ -91,3 +91,19 @@ fn distant_void() {
assert::is_maybe_transmutable::<DistantVoid, &'static Void>(); assert::is_maybe_transmutable::<DistantVoid, &'static Void>();
assert::is_maybe_transmutable::<u128, DistantVoid>(); //~ ERROR: cannot be safely transmuted assert::is_maybe_transmutable::<u128, DistantVoid>(); //~ ERROR: cannot be safely transmuted
} }
fn issue_126267() {
pub enum ApiError {}
pub struct TokioError {
b: bool,
}
pub enum Error {
Api { source: ApiError }, // this variant is uninhabited
Ethereum,
Tokio { source: TokioError },
}
struct Src;
type Dst = Error;
assert::is_maybe_transmutable::<Src, Dst>(); //~ERROR: cannot be safely transmuted
}

View file

@ -110,7 +110,29 @@ LL | | }
LL | | }> LL | | }>
| |__________^ required by this bound in `is_maybe_transmutable` | |__________^ required by this bound in `is_maybe_transmutable`
error: aborting due to 7 previous errors error[E0277]: `Src` cannot be safely transmuted into `issue_126267::Error`
--> $DIR/uninhabited.rs:108:42
|
LL | assert::is_maybe_transmutable::<Src, Dst>();
| ^^^ the size of `Src` is smaller than the size of `issue_126267::Error`
|
note: required by a bound in `is_maybe_transmutable`
--> $DIR/uninhabited.rs:10:14
|
LL | pub fn is_maybe_transmutable<Src, Dst>()
| --------------------- required by a bound in this function
LL | where
LL | Dst: TransmuteFrom<Src, {
| ______________^
LL | | Assume {
LL | | alignment: true,
LL | | lifetimes: true,
... |
LL | | }
LL | | }>
| |__________^ required by this bound in `is_maybe_transmutable`
error: aborting due to 8 previous errors
Some errors have detailed explanations: E0080, E0277. Some errors have detailed explanations: E0080, E0277.
For more information about an error, try `rustc --explain E0080`. For more information about an error, try `rustc --explain E0080`.