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]]
|
[[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"
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))?;
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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(); } }
|
||||||
```
|
```
|
||||||
|
|
|
@ -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")),
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 { .. });
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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!()
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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"
|
path = "src/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[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)]
|
#![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(); } }
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
//@ 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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
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
|
//@ 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() {}
|
||||||
|
|
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 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
|
||||||
}
|
}
|
||||||
|
|
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 {
|
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;
|
||||||
|
|
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> {
|
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
|
||||||
}
|
}
|
||||||
|
|
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 {
|
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() {}
|
||||||
|
|
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::<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
|
||||||
|
}
|
||||||
|
|
|
@ -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`.
|
||||||
|
|
Loading…
Add table
Reference in a new issue