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:
commit
3b382642ab
51 changed files with 566 additions and 240 deletions
13
Cargo.lock
13
Cargo.lock
|
@ -5803,17 +5803,20 @@ checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-component-ld"
|
||||
version = "0.5.10"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d4aa6bd7fbe7cffbed29fe3e236fda74419def1bdef6f80f989ec51137edf44"
|
||||
checksum = "a2b05c3820968b335f10e703218459e4fd2cc91fdfc8f7936a993f1aacaa0938"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
"lexopt",
|
||||
"libc",
|
||||
"tempfile",
|
||||
"wasi-preview1-component-adapter-provider",
|
||||
"wasmparser 0.219.1",
|
||||
"wat",
|
||||
"windows-sys 0.59.0",
|
||||
"winsplit",
|
||||
"wit-component",
|
||||
"wit-parser",
|
||||
]
|
||||
|
@ -6185,6 +6188,12 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winsplit"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ab703352da6a72f35c39a533526393725640575bb211f61987a2748323ad956"
|
||||
|
||||
[[package]]
|
||||
name = "wit-component"
|
||||
version = "0.219.1"
|
||||
|
|
|
@ -1215,6 +1215,15 @@ impl Scalar {
|
|||
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.
|
||||
|
@ -1401,10 +1410,7 @@ impl BackendRepr {
|
|||
#[inline]
|
||||
pub fn is_signed(&self) -> bool {
|
||||
match self {
|
||||
BackendRepr::Scalar(scal) => match scal.primitive() {
|
||||
Primitive::Int(_, signed) => signed,
|
||||
_ => false,
|
||||
},
|
||||
BackendRepr::Scalar(scal) => scal.is_signed(),
|
||||
_ => panic!("`is_signed` on non-scalar ABI {self:?}"),
|
||||
}
|
||||
}
|
||||
|
@ -1499,7 +1505,11 @@ impl BackendRepr {
|
|||
#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
|
||||
pub enum Variants<FieldIdx: Idx, VariantIdx: Idx> {
|
||||
/// 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
|
||||
/// 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
|
||||
/// offset (field `tag_field` of the enum), which for a variant with
|
||||
/// 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
|
||||
/// `None` has a null pointer for the second tuple field, and
|
||||
/// `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 {
|
||||
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>,
|
||||
/// 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,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
use rustc_abi::VariantIdx;
|
||||
use rustc_middle::query::{Key, TyCtxtAt};
|
||||
use rustc_middle::ty::layout::LayoutOf;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_middle::{bug, mir};
|
||||
use tracing::instrument;
|
||||
|
@ -85,5 +86,6 @@ pub fn tag_for_variant_provider<'tcx>(
|
|||
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)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines).
|
||||
|
||||
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::{mir, span_bug};
|
||||
use tracing::{instrument, trace};
|
||||
|
@ -21,17 +21,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
variant_index: VariantIdx,
|
||||
dest: &impl Writeable<'tcx, M::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
// 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 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)? {
|
||||
match self.tag_for_variant(dest.layout(), variant_index)? {
|
||||
Some((tag, tag_field)) => {
|
||||
// No need to validate that the discriminant here because 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() {
|
||||
// Hilariously, `Single` is used even for 0-variant enums.
|
||||
// (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))
|
||||
}
|
||||
// For consistency with `write_discriminant`, and to make sure that
|
||||
|
@ -188,6 +178,11 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
let variants =
|
||||
ty.ty_adt_def().expect("tagged layout for non adt").variants();
|
||||
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
|
||||
} else {
|
||||
untagged_variant
|
||||
|
@ -236,10 +231,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
/// given field index.
|
||||
pub(crate) fn tag_for_variant(
|
||||
&self,
|
||||
ty: Ty<'tcx>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
variant_index: VariantIdx,
|
||||
) -> 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 { .. } => {
|
||||
// The tag of a `Single` enum is like the tag of the niched
|
||||
// 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
|
||||
// their computation, but the in-memory tag is the smallest possible
|
||||
// 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_val = discr.to_scalar().to_bits(discr_size)?;
|
||||
let tag_size = tag_layout.size(self);
|
||||
|
@ -286,11 +289,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
|||
..
|
||||
} => {
|
||||
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 variant_index_relative = variant_index
|
||||
.as_u32()
|
||||
.checked_sub(variants_start)
|
||||
.expect("overflow computing relative variant idx");
|
||||
let variant_index_relative = variant_index.as_u32().strict_sub(variants_start);
|
||||
// We need to use machine arithmetic when taking into account `niche_start`:
|
||||
// tag_val = variant_index_relative + niche_start_val
|
||||
let tag_layout = self.layout_of(tag_layout.primitive().to_int_ty(*self.tcx))?;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#![feature(never_type)]
|
||||
#![feature(rustdoc_internals)]
|
||||
#![feature(slice_ptr_get)]
|
||||
#![feature(strict_overflow_ops)]
|
||||
#![feature(trait_alias)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(unqualified_local_imports)]
|
||||
|
|
|
@ -7,10 +7,11 @@ Erroneous code example:
|
|||
#![allow(internal_features)]
|
||||
|
||||
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
|
||||
|
@ -22,8 +23,8 @@ error, just declare a function. Example:
|
|||
#![allow(internal_features)]
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
pub fn breakpoint(); // ok!
|
||||
pub fn atomic_singlethreadfence_seqcst(); // ok!
|
||||
}
|
||||
|
||||
fn main() { unsafe { breakpoint(); } }
|
||||
fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
|
||||
```
|
||||
|
|
|
@ -119,6 +119,13 @@ declare_features! (
|
|||
(removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")),
|
||||
/// Allows defining generators.
|
||||
(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`).
|
||||
(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")),
|
||||
|
|
|
@ -499,8 +499,6 @@ declare_features! (
|
|||
(unstable, gen_blocks, "1.75.0", Some(117078)),
|
||||
/// Infer generic args for both consts and types.
|
||||
(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
|
||||
(incomplete, generic_const_exprs, "1.56.0", Some(76560)),
|
||||
/// Allows generic parameters and where-clauses on free & associated const items.
|
||||
|
|
|
@ -87,6 +87,7 @@ pub fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -
|
|||
| sym::assert_inhabited
|
||||
| sym::assert_zero_valid
|
||||
| sym::assert_mem_uninitialized_valid
|
||||
| sym::breakpoint
|
||||
| sym::size_of
|
||||
| sym::min_align_of
|
||||
| sym::needs_drop
|
||||
|
|
|
@ -1081,6 +1081,8 @@ rustc_queries! {
|
|||
}
|
||||
|
||||
/// 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(
|
||||
key: (Ty<'tcx>, abi::VariantIdx)
|
||||
) -> Option<ty::ScalarInt> {
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::spec::{Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions, cr
|
|||
pub(crate) fn opts() -> TargetOptions {
|
||||
TargetOptions {
|
||||
abi: "vec-extabi".into(),
|
||||
code_model: Some(CodeModel::Small),
|
||||
code_model: Some(CodeModel::Large),
|
||||
cpu: "pwr7".into(),
|
||||
os: "aix".into(),
|
||||
vendor: "ibm".into(),
|
||||
|
|
|
@ -328,10 +328,7 @@ pub fn dyn_compatibility_violations_for_assoc_item(
|
|||
.collect(),
|
||||
// Associated types can only be dyn-compatible if they have `Self: Sized` bounds.
|
||||
ty::AssocKind::Type => {
|
||||
if !tcx.features().generic_associated_types_extended()
|
||||
&& !tcx.generics_of(item.def_id).is_own_empty()
|
||||
&& !item.is_impl_trait_in_trait()
|
||||
{
|
||||
if !tcx.generics_of(item.def_id).is_own_empty() && !item.is_impl_trait_in_trait() {
|
||||
vec![DynCompatibilityViolation::GAT(item.name, item.ident(tcx).span)]
|
||||
} else {
|
||||
// We will permit associated types if they are explicitly mentioned in the trait object.
|
||||
|
|
|
@ -14,7 +14,7 @@ use rustc_middle::traits::select::OverflowError;
|
|||
use rustc_middle::traits::{BuiltinImplSource, ImplSource, ImplSourceUserDefinedData};
|
||||
use rustc_middle::ty::fast_reject::DeepRejectCtxt;
|
||||
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::{bug, span_bug};
|
||||
use rustc_span::symbol::sym;
|
||||
|
@ -179,35 +179,11 @@ pub(super) fn poly_project_and_unify_term<'cx, 'tcx>(
|
|||
) -> ProjectAndUnifyResult<'tcx> {
|
||||
let infcx = selcx.infcx;
|
||||
let r = infcx.commit_if_ok(|_snapshot| {
|
||||
let old_universe = infcx.universe();
|
||||
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);
|
||||
match project_and_unify_term(selcx, &placeholder_obligation) {
|
||||
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),
|
||||
}
|
||||
});
|
||||
|
|
|
@ -626,7 +626,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||
for assoc_type in assoc_types {
|
||||
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(
|
||||
obligation.cause.span,
|
||||
"GATs in trait object shouldn't have been considered",
|
||||
|
|
|
@ -319,11 +319,15 @@ pub(crate) mod rustc {
|
|||
) -> Result<Self, Err> {
|
||||
assert!(def.is_enum());
|
||||
|
||||
// Computes the variant of a given index.
|
||||
let layout_of_variant = |index, encoding: Option<TagEncoding<VariantIdx>>| {
|
||||
// Computes the layout of a variant.
|
||||
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 variant_def = Def::Variant(def.variant(index));
|
||||
let variant_layout = ty_variant(cx, (ty, layout), index);
|
||||
Self::from_variant(
|
||||
variant_def,
|
||||
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() {
|
||||
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 } => {
|
||||
// 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
|
||||
// the enum delegates its layout to the variant at `index`.
|
||||
layout_of_variant(*index, None)
|
||||
}
|
||||
}
|
||||
Variants::Multiple { tag, tag_encoding, tag_field, .. } => {
|
||||
// `Variants::Multiple` denotes an enum with multiple
|
||||
// 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ fn layout_of<'tcx>(
|
|||
record_layout_for_printing(&cx, layout);
|
||||
}
|
||||
|
||||
invariant::partially_check_layout(&cx, &layout);
|
||||
invariant::layout_sanity_check(&cx, &layout);
|
||||
|
||||
Ok(layout)
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
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::ty::layout::{HasTyCtxt, LayoutCx, TyAndLayout};
|
||||
|
||||
/// 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();
|
||||
|
||||
// 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);
|
||||
|
||||
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() {
|
||||
// No nested "multiple".
|
||||
assert_matches!(variant.variants, Variants::Single { .. });
|
||||
|
|
|
@ -42,3 +42,30 @@ pub macro naked_asm("assembly template", $(operands,)* $(options($(option),*))?)
|
|||
pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))?) {
|
||||
/* 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();
|
||||
}
|
||||
|
|
|
@ -1381,6 +1381,18 @@ pub unsafe fn prefetch_write_instruction<T>(_data: *const T, _locality: i32) {
|
|||
#[rustc_intrinsic]
|
||||
#[rustc_intrinsic_must_be_overridden]
|
||||
#[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() {
|
||||
unreachable!()
|
||||
}
|
||||
|
|
|
@ -1021,11 +1021,11 @@ impl Drop for PanicGuard {
|
|||
///
|
||||
/// # 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
|
||||
/// 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
|
||||
/// _all_ prior `unpark` operations.
|
||||
/// operations for a given thread form a total order and _all_ prior `unpark` operations
|
||||
/// synchronize-with `park`.
|
||||
///
|
||||
/// In atomic ordering terms, `unpark` performs a `Release` operation and `park`
|
||||
/// performs the corresponding `Acquire` operation. Calls to `unpark` for the same
|
||||
|
|
|
@ -350,10 +350,13 @@ impl<'test> TestCx<'test> {
|
|||
}
|
||||
} else {
|
||||
if proc_res.status.success() {
|
||||
self.fatal_proc_rec(
|
||||
&format!("{} test compiled successfully!", self.config.mode)[..],
|
||||
proc_res,
|
||||
);
|
||||
{
|
||||
self.error(&format!("{} test did not emit an error", self.config.mode));
|
||||
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 {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#![feature(core_intrinsics)]
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap
|
||||
};
|
||||
core::intrinsics::breakpoint(); //~ ERROR: trace/breakpoint trap
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
error: abnormal termination: trace/breakpoint trap
|
||||
--> tests/fail/breakpoint.rs:LL:CC
|
||||
|
|
||||
LL | core::intrinsics::breakpoint()
|
||||
LL | core::intrinsics::breakpoint();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
|
||||
|
|
||||
= note: BACKTRACE:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -10,4 +10,4 @@ name = "wasm-component-ld"
|
|||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
wasm-component-ld = "0.5.10"
|
||||
wasm-component-ld = "0.5.11"
|
||||
|
|
14
tests/assembly/breakpoint.rs
Normal file
14
tests/assembly/breakpoint.rs
Normal 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();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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,
|
||||
{
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
#![feature(intrinsics)]
|
||||
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]
|
||||
}
|
||||
fn main() { unsafe { breakpoint(); } }
|
||||
fn main() { unsafe { atomic_singlethreadfence_seqcst(); } }
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error[E0622]: intrinsic must be a function
|
||||
--> $DIR/E0622.rs:3:5
|
||||
|
|
||||
LL | pub static breakpoint : unsafe extern "rust-intrinsic" fn();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function
|
||||
LL | pub static atomic_singlethreadfence_seqcst : unsafe extern "rust-intrinsic" fn();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected a function
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
|
@ -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() {}
|
|
@ -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`.
|
|
@ -1,9 +1,4 @@
|
|||
//@ revisions: base extended
|
||||
//@[base] check-fail
|
||||
//@[extended] check-pass
|
||||
|
||||
#![cfg_attr(extended, feature(generic_associated_types_extended))]
|
||||
#![cfg_attr(extended, allow(incomplete_features))]
|
||||
//@ known-bug: #133805
|
||||
|
||||
pub trait FromLendingIterator<A>: Sized {
|
||||
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> {
|
||||
fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
|
||||
//[base]~^ impl has stricter
|
||||
let mut v = vec![];
|
||||
while let Some(item) = iter.next() {
|
||||
v.push(item);
|
||||
|
@ -32,7 +26,6 @@ pub trait LendingIterator {
|
|||
Self: for<'q> LendingIterator<Item<'q> = A>,
|
||||
{
|
||||
<B as FromLendingIterator<A>>::from_iter(self)
|
||||
//[base]~^ ERROR: does not live long enough
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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;
|
||||
| ------------------------------------------------------------------------ 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`
|
||||
|
||||
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)
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
@ -1,9 +1,4 @@
|
|||
//@ revisions: base extended
|
||||
//@[base] check-fail
|
||||
//@[extended] check-pass
|
||||
|
||||
#![cfg_attr(extended, feature(generic_associated_types_extended))]
|
||||
#![cfg_attr(extended, allow(incomplete_features))]
|
||||
//@ known-bug: #133805
|
||||
|
||||
pub trait FromLendingIterator<A>: Sized {
|
||||
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> {
|
||||
fn from_iter<I: for<'x> LendingIterator<Item<'x> = A>>(mut iter: I) -> Self {
|
||||
//[base]~^ impl has stricter
|
||||
let mut v = vec![];
|
||||
while let Some(item) = iter.next() {
|
||||
v.push(item);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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;
|
||||
| ------------------------------------------------------------------------ definition of `from_iter` from trait
|
|
@ -1,10 +1,6 @@
|
|||
//@ revisions: base extended
|
||||
//@[base] check-fail
|
||||
//@[extended] check-pass
|
||||
//@ check-fail
|
||||
|
||||
#![feature(associated_type_defaults)]
|
||||
#![cfg_attr(extended, feature(generic_associated_types_extended))]
|
||||
#![cfg_attr(extended, allow(incomplete_features))]
|
||||
|
||||
trait Foo {
|
||||
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 ()>>) {}
|
||||
//[base]~^ the trait `Foo` cannot be made into an object
|
||||
//~^ the trait `Foo` cannot be made into an object
|
||||
|
||||
|
||||
fn main() {
|
||||
let foo = Fooer(5);
|
||||
f(Box::new(foo));
|
||||
//[base]~^ 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
|
||||
//~| the trait `Foo` cannot be made into an object
|
||||
}
|
||||
|
|
58
tests/ui/generic-associated-types/gat-in-trait-path.stderr
Normal file
58
tests/ui/generic-associated-types/gat-in-trait-path.stderr
Normal 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`.
|
|
@ -1,15 +1,10 @@
|
|||
//@ revisions: base extended
|
||||
//@[base] check-fail
|
||||
//@[extended] check-pass
|
||||
|
||||
#![cfg_attr(extended, feature(generic_associated_types_extended))]
|
||||
#![cfg_attr(extended, allow(incomplete_features))]
|
||||
//@ check-fail
|
||||
|
||||
trait X {
|
||||
type Y<'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() {}
|
||||
|
|
18
tests/ui/generic-associated-types/issue-67510-pass.stderr
Normal file
18
tests/ui/generic-associated-types/issue-67510-pass.stderr
Normal 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`.
|
|
@ -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 SuperTrait {
|
||||
|
@ -38,6 +33,6 @@ impl SuperTrait for SuperStruct {
|
|||
fn main() {
|
||||
let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
|
||||
//~^ ERROR missing generics for associated type
|
||||
//[base]~^^ ERROR the trait
|
||||
//[base]~| ERROR the trait
|
||||
//~^^ ERROR the trait
|
||||
//~| ERROR the trait
|
||||
}
|
||||
|
|
55
tests/ui/generic-associated-types/issue-76535.stderr
Normal file
55
tests/ui/generic-associated-types/issue-76535.stderr
Normal 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`.
|
|
@ -1,15 +1,10 @@
|
|||
//@ revisions: base extended
|
||||
|
||||
#![cfg_attr(extended, feature(generic_associated_types_extended))]
|
||||
#![cfg_attr(extended, allow(incomplete_features))]
|
||||
|
||||
trait CollectionFamily {
|
||||
type Member<T>;
|
||||
}
|
||||
fn floatify() {
|
||||
Box::new(Family) as &dyn CollectionFamily<Member=usize>
|
||||
//~^ 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;
|
||||
|
|
35
tests/ui/generic-associated-types/issue-78671.stderr
Normal file
35
tests/ui/generic-associated-types/issue-78671.stderr
Normal 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`.
|
|
@ -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> {
|
||||
fn t(&'a self) -> &'a T;
|
||||
}
|
||||
|
@ -42,9 +37,8 @@ impl<K, V: Default> MapLike<K, V> for Source {
|
|||
|
||||
fn main() {
|
||||
let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
|
||||
//[base]~^ ERROR the trait
|
||||
//[extended]~^^ type mismatch
|
||||
//~^ ERROR the trait
|
||||
as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
|
||||
//~^ ERROR missing generics for associated type
|
||||
//[base]~^^ ERROR the trait
|
||||
//~| ERROR the trait
|
||||
}
|
||||
|
|
57
tests/ui/generic-associated-types/issue-79422.stderr
Normal file
57
tests/ui/generic-associated-types/issue-79422.stderr
Normal 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`.
|
|
@ -1,8 +1,3 @@
|
|||
//@ revisions: base extended
|
||||
|
||||
#![cfg_attr(extended, feature(generic_associated_types_extended))]
|
||||
#![cfg_attr(extended, allow(incomplete_features))]
|
||||
|
||||
trait StreamingIterator {
|
||||
type Item<'a> where Self: 'a;
|
||||
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 {
|
||||
//[base]~^ the trait `StreamingIterator` cannot be made into an object
|
||||
//~^ the trait `StreamingIterator` cannot be made into an object
|
||||
x.size_hint().0
|
||||
//[extended]~^ borrowed data escapes
|
||||
//[base]~^^ 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
|
||||
//~| the trait `StreamingIterator` cannot be made into an object
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
48
tests/ui/generic-associated-types/trait-objects.stderr
Normal file
48
tests/ui/generic-associated-types/trait-objects.stderr
Normal 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`.
|
|
@ -91,3 +91,19 @@ fn distant_void() {
|
|||
assert::is_maybe_transmutable::<DistantVoid, &'static Void>();
|
||||
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
|
||||
}
|
||||
|
|
|
@ -110,7 +110,29 @@ LL | | }
|
|||
LL | | }>
|
||||
| |__________^ 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.
|
||||
For more information about an error, try `rustc --explain E0080`.
|
||||
|
|
Loading…
Add table
Reference in a new issue