Remove support for dyn*

This commit is contained in:
Michael Goulet 2025-06-26 02:01:38 +00:00
parent 4e97337005
commit 2516c33982
143 changed files with 114 additions and 2203 deletions

View file

@ -2585,8 +2585,7 @@ pub enum TyPatKind {
pub enum TraitObjectSyntax {
// SAFETY: When adding new variants make sure to update the `Tag` impl.
Dyn = 0,
DynStar = 1,
None = 2,
None = 1,
}
/// SAFETY: `TraitObjectSyntax` only has 3 data-less variants which means
@ -2602,8 +2601,7 @@ unsafe impl Tag for TraitObjectSyntax {
unsafe fn from_usize(tag: usize) -> Self {
match tag {
0 => TraitObjectSyntax::Dyn,
1 => TraitObjectSyntax::DynStar,
2 => TraitObjectSyntax::None,
1 => TraitObjectSyntax::None,
_ => unreachable!(),
}
}

View file

@ -505,7 +505,6 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
);
gate_all!(associated_const_equality, "associated const equality is incomplete");
gate_all!(yeet_expr, "`do yeet` expression is experimental");
gate_all!(dyn_star, "`dyn*` trait objects are experimental");
gate_all!(const_closures, "const closures are experimental");
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
gate_all!(ergonomic_clones, "ergonomic clones are experimental");

View file

@ -1303,7 +1303,6 @@ impl<'a> State<'a> {
ast::TyKind::TraitObject(bounds, syntax) => {
match syntax {
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
ast::TraitObjectSyntax::None => {}
}
self.print_type_bounds(bounds);

View file

@ -25,9 +25,9 @@ use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::cast::CastTy;
use rustc_middle::ty::{
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
Dynamic, GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt,
TypeVisitableExt, UserArgs, UserTypeAnnotationIndex, fold_regions,
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, CoroutineArgsExt,
GenericArgsRef, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, TypeVisitableExt,
UserArgs, UserTypeAnnotationIndex, fold_regions,
};
use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::move_paths::MoveData;
@ -1233,38 +1233,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
);
}
CastKind::PointerCoercion(PointerCoercion::DynStar, coercion_source) => {
// get the constraints from the target type (`dyn* Clone`)
//
// apply them to prove that the source type `Foo` implements `Clone` etc
let (existential_predicates, region) = match ty.kind() {
Dynamic(predicates, region, ty::DynStar) => (predicates, region),
_ => panic!("Invalid dyn* cast_ty"),
};
let self_ty = op.ty(self.body, tcx);
let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
self.prove_predicates(
existential_predicates
.iter()
.map(|predicate| predicate.with_self_ty(tcx, self_ty)),
location.to_locations(),
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
);
let outlives_predicate = tcx.mk_predicate(Binder::dummy(
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
ty::OutlivesPredicate(self_ty, *region),
)),
));
self.prove_predicate(
outlives_predicate,
location.to_locations(),
ConstraintCategory::Cast { is_implicit_coercion, unsize_to: None },
);
}
CastKind::PointerCoercion(
PointerCoercion::MutToConstPointer,
coercion_source,

View file

@ -753,51 +753,6 @@ pub(crate) fn codegen_drop<'tcx>(
fx.bcx.ins().call_indirect(sig, drop_fn, &[ptr]);
fx.bcx.ins().jump(ret_block, &[]);
}
ty::Dynamic(_, _, ty::DynStar) => {
// IN THIS ARM, WE HAVE:
// ty = *mut (dyn* Trait)
// which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
//
// args = [ * ]
// |
// v
// ( Data, Vtable )
// |
// v
// /-------\
// | ... |
// \-------/
//
//
// WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
//
// data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
// vtable = (*args[0]).1 // loads the vtable out
// (data, vtable) // an equivalent Rust `*mut dyn Trait`
//
// SO THEN WE CAN USE THE ABOVE CODE.
let (data, vtable) = drop_place.to_cvalue(fx).dyn_star_force_data_on_stack(fx);
let drop_fn = crate::vtable::drop_fn_of_obj(fx, vtable);
let is_null = fx.bcx.ins().icmp_imm(IntCC::Equal, drop_fn, 0);
let target_block = fx.get_block(target);
let continued = fx.bcx.create_block();
fx.bcx.ins().brif(is_null, target_block, &[], continued, &[]);
fx.bcx.switch_to_block(continued);
let virtual_drop = Instance {
def: ty::InstanceKind::Virtual(drop_instance.def_id(), 0),
args: drop_instance.args,
};
let fn_abi = FullyMonomorphizedLayoutCx(fx.tcx)
.fn_abi_of_instance(virtual_drop, ty::List::empty());
let sig = clif_sig_from_fn_abi(fx.tcx, fx.target_config.default_call_conv, &fn_abi);
let sig = fx.bcx.import_signature(sig);
fx.bcx.ins().call_indirect(sig, drop_fn, &[data]);
// FIXME implement cleanup on exceptions
fx.bcx.ins().jump(ret_block, &[]);
}
_ => {
assert!(!matches!(drop_instance.def, InstanceKind::Virtual(_, _)));

View file

@ -790,14 +790,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
let operand = codegen_operand(fx, operand);
crate::unsize::coerce_unsized_into(fx, operand, lval);
}
Rvalue::Cast(
CastKind::PointerCoercion(PointerCoercion::DynStar, _),
ref operand,
_,
) => {
let operand = codegen_operand(fx, operand);
crate::unsize::coerce_dyn_star(fx, operand, lval);
}
Rvalue::Cast(CastKind::Transmute, ref operand, _to_ty) => {
let operand = codegen_operand(fx, operand);
lval.write_cvalue_transmute(fx, operand);

View file

@ -112,21 +112,6 @@ fn unsize_ptr<'tcx>(
}
}
/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
pub(crate) fn cast_to_dyn_star<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
src: Value,
src_ty_and_layout: TyAndLayout<'tcx>,
dst_ty: Ty<'tcx>,
old_info: Option<Value>,
) -> (Value, Value) {
assert!(
matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
"destination type must be a dyn*"
);
(src, unsized_info(fx, src_ty_and_layout.ty, dst_ty, old_info))
}
/// Coerce `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty` and store the result in `dst`
pub(crate) fn coerce_unsized_into<'tcx>(
@ -174,24 +159,6 @@ pub(crate) fn coerce_unsized_into<'tcx>(
}
}
pub(crate) fn coerce_dyn_star<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
src: CValue<'tcx>,
dst: CPlace<'tcx>,
) {
let (data, extra) = if let ty::Dynamic(_, _, ty::DynStar) = src.layout().ty.kind() {
let (data, vtable) = src.load_scalar_pair(fx);
(data, Some(vtable))
} else {
let data = src.load_scalar(fx);
(data, None)
};
let (data, vtable) = cast_to_dyn_star(fx, data, src.layout(), dst.layout().ty, extra);
dst.write_cvalue(fx, CValue::by_val_pair(data, vtable, dst.layout()));
}
// Adapted from https://github.com/rust-lang/rust/blob/2a663555ddf36f6b041445894a8c175cd1bc718c/src/librustc_codegen_ssa/glue.rs
pub(crate) fn size_and_align_of<'tcx>(

View file

@ -121,43 +121,6 @@ impl<'tcx> CValue<'tcx> {
}
}
// FIXME remove
/// Forces the data value of a dyn* value to the stack and returns a pointer to it as well as the
/// vtable pointer.
pub(crate) fn dyn_star_force_data_on_stack(
self,
fx: &mut FunctionCx<'_, '_, 'tcx>,
) -> (Value, Value) {
assert!(self.1.ty.is_dyn_star());
match self.0 {
CValueInner::ByRef(ptr, None) => {
let (a_scalar, b_scalar) = match self.1.backend_repr {
BackendRepr::ScalarPair(a, b) => (a, b),
_ => unreachable!("dyn_star_force_data_on_stack({:?})", self),
};
let b_offset = scalar_pair_calculate_b_offset(fx.tcx, a_scalar, b_scalar);
let clif_ty2 = scalar_to_clif_type(fx.tcx, b_scalar);
let mut flags = MemFlags::new();
flags.set_notrap();
let vtable = ptr.offset(fx, b_offset).load(fx, clif_ty2, flags);
(ptr.get_addr(fx), vtable)
}
CValueInner::ByValPair(data, vtable) => {
let data_ptr = fx.create_stack_slot(
u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(),
u32::try_from(fx.target_config.pointer_type().bytes()).unwrap(),
);
data_ptr.store(fx, data, MemFlags::trusted());
(data_ptr.get_addr(fx), vtable)
}
CValueInner::ByRef(_, Some(_)) | CValueInner::ByVal(_) => {
unreachable!("dyn_star_force_data_on_stack({:?})", self)
}
}
}
pub(crate) fn try_to_ptr(self) -> Option<(Pointer, Option<Value>)> {
match self.0 {
CValueInner::ByRef(ptr, meta) => Some((ptr, meta)),

View file

@ -46,34 +46,22 @@ pub(crate) fn get_ptr_and_method_ref<'tcx>(
mut arg: CValue<'tcx>,
idx: usize,
) -> (Pointer, Value) {
let (ptr, vtable) = 'block: {
if let BackendRepr::Scalar(_) = arg.layout().backend_repr {
while !arg.layout().ty.is_raw_ptr() && !arg.layout().ty.is_ref() {
let (idx, _) = arg
.layout()
.non_1zst_field(fx)
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type");
arg = arg.value_field(fx, idx);
}
if let BackendRepr::Scalar(_) = arg.layout().backend_repr {
while !arg.layout().ty.is_raw_ptr() && !arg.layout().ty.is_ref() {
let (idx, _) = arg
.layout()
.non_1zst_field(fx)
.expect("not exactly one non-1-ZST field in a `DispatchFromDyn` type");
arg = arg.value_field(fx, idx);
}
}
if let ty::Ref(_, ty, _) = arg.layout().ty.kind() {
if ty.is_dyn_star() {
let inner_layout = fx.layout_of(arg.layout().ty.builtin_deref(true).unwrap());
let dyn_star = CPlace::for_ptr(Pointer::new(arg.load_scalar(fx)), inner_layout);
let ptr = dyn_star.place_field(fx, FieldIdx::ZERO).to_ptr();
let vtable = dyn_star.place_field(fx, FieldIdx::ONE).to_cvalue(fx).load_scalar(fx);
break 'block (ptr, vtable);
}
}
if let BackendRepr::ScalarPair(_, _) = arg.layout().backend_repr {
let (ptr, vtable) = arg.load_scalar_pair(fx);
(Pointer::new(ptr), vtable)
} else {
let (ptr, vtable) = arg.try_to_ptr().unwrap();
(ptr, vtable.unwrap())
}
let (ptr, vtable) = if let BackendRepr::ScalarPair(_, _) = arg.layout().backend_repr {
let (ptr, vtable) = arg.load_scalar_pair(fx);
(Pointer::new(ptr), vtable)
} else {
let (ptr, vtable) = arg.try_to_ptr().unwrap();
(ptr, vtable.unwrap())
};
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();

View file

@ -262,28 +262,6 @@ pub(crate) fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
}
}
/// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
pub(crate) fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
bx: &mut Bx,
src: Bx::Value,
src_ty_and_layout: TyAndLayout<'tcx>,
dst_ty: Ty<'tcx>,
old_info: Option<Bx::Value>,
) -> (Bx::Value, Bx::Value) {
debug!("cast_to_dyn_star: {:?} => {:?}", src_ty_and_layout.ty, dst_ty);
assert!(
matches!(dst_ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
"destination type must be a dyn*"
);
let src = match bx.cx().type_kind(bx.cx().backend_type(src_ty_and_layout)) {
TypeKind::Pointer => src,
TypeKind::Integer => bx.inttoptr(src, bx.type_ptr()),
// FIXME(dyn-star): We probably have to do a bitcast first, then inttoptr.
kind => bug!("unexpected TypeKind for left-hand side of `dyn*` cast: {kind:?}"),
};
(src, unsized_info(bx, src_ty_and_layout.ty, dst_ty, old_info))
}
/// Coerces `src`, which is a reference to a value of type `src_ty`,
/// to a value of type `dst_ty`, and stores the result in `dst`.
pub(crate) fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(

View file

@ -628,50 +628,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
virtual_drop,
)
}
ty::Dynamic(_, _, ty::DynStar) => {
// IN THIS ARM, WE HAVE:
// ty = *mut (dyn* Trait)
// which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
//
// args = [ * ]
// |
// v
// ( Data, Vtable )
// |
// v
// /-------\
// | ... |
// \-------/
//
//
// WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
//
// data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
// vtable = (*args[0]).1 // loads the vtable out
// (data, vtable) // an equivalent Rust `*mut dyn Trait`
//
// SO THEN WE CAN USE THE ABOVE CODE.
let virtual_drop = Instance {
def: ty::InstanceKind::Virtual(drop_fn.def_id(), 0), // idx 0: the drop function
args: drop_fn.args,
};
debug!("ty = {:?}", ty);
debug!("drop_fn = {:?}", drop_fn);
debug!("args = {:?}", args);
let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
let meta_ptr = place.project_field(bx, 1);
let meta = bx.load_operand(meta_ptr);
// Truncate vtable off of args list
args = &args[..1];
debug!("args' = {:?}", args);
(
true,
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
.get_optional_fn(bx, meta.immediate(), ty, fn_abi),
fn_abi,
virtual_drop,
)
}
_ => (
false,
bx.get_fn_addr(drop_fn),
@ -1108,33 +1064,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
llargs.push(data_ptr);
continue;
}
Immediate(_) => {
// See comment above explaining why we peel these newtypes
while !op.layout.ty.is_raw_ptr() && !op.layout.ty.is_ref() {
let (idx, _) = op.layout.non_1zst_field(bx).expect(
"not exactly one non-1-ZST field in a `DispatchFromDyn` type",
);
op = op.extract_field(self, bx, idx.as_usize());
}
// Make sure that we've actually unwrapped the rcvr down
// to a pointer or ref to `dyn* Trait`.
if !op.layout.ty.builtin_deref(true).unwrap().is_dyn_star() {
span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op);
}
let place = op.deref(bx.cx());
let data_place = place.project_field(bx, 0);
let meta_place = place.project_field(bx, 1);
let meta = bx.load_operand(meta_place);
llfn = Some(meth::VirtualIndex::from_index(idx).get_fn(
bx,
meta.immediate(),
op.layout.ty,
fn_abi,
));
llargs.push(data_place.val.llval);
continue;
}
_ => {
span_bug!(fn_span, "can't codegen a virtual call on {:#?}", op);
}

View file

@ -468,12 +468,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
bug!("unexpected non-pair operand");
}
}
mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
let (lldata, llextra) = operand.val.pointer_parts();
let (lldata, llextra) =
base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);
OperandValue::Pair(lldata, llextra)
}
| mir::CastKind::IntToInt
| mir::CastKind::FloatToInt
| mir::CastKind::FloatToFloat

View file

@ -638,14 +638,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
// These are all okay; they only change the type, not the data.
}
Rvalue::Cast(
CastKind::PointerCoercion(PointerCoercion::Unsize | PointerCoercion::DynStar, _),
_,
_,
) => {
// Unsizing and `dyn*` coercions are implemented for CTFE.
}
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => {
self.check_op(ops::RawPtrToIntCast);
}

View file

@ -643,13 +643,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
break self.ref_to_mplace(&val)?;
}
ty::Dynamic(.., ty::Dyn) => break receiver.assert_mem_place(), // no immediate unsized values
ty::Dynamic(.., ty::DynStar) => {
// Not clear how to handle this, so far we assume the receiver is always a pointer.
span_bug!(
self.cur_span(),
"by-value calls on a `dyn*`... are those a thing?"
);
}
_ => {
// Not there yet, search for the only non-ZST field.
// (The rules for `DispatchFromDyn` ensure there's exactly one such field.)
@ -662,39 +655,23 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
};
// Obtain the underlying trait we are working on, and the adjusted receiver argument.
let (trait_, dyn_ty, adjusted_recv) = if let ty::Dynamic(data, _, ty::DynStar) =
receiver_place.layout.ty.kind()
{
let recv = self.unpack_dyn_star(&receiver_place, data)?;
(data.principal(), recv.layout.ty, recv.ptr())
} else {
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
// (For that reason we also cannot use `unpack_dyn_trait`.)
let receiver_tail =
self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env);
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
span_bug!(
self.cur_span(),
"dynamic call on non-`dyn` type {}",
receiver_tail
)
};
assert!(receiver_place.layout.is_unsized());
// Get the required information from the vtable.
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
// It might be surprising that we use a pointer as the receiver even if this
// is a by-val case; this works because by-val passing of an unsized `dyn
// Trait` to a function is actually desugared to a pointer.
(receiver_trait.principal(), dyn_ty, receiver_place.ptr())
// Doesn't have to be a `dyn Trait`, but the unsized tail must be `dyn Trait`.
// (For that reason we also cannot use `unpack_dyn_trait`.)
let receiver_tail =
self.tcx.struct_tail_for_codegen(receiver_place.layout.ty, self.typing_env);
let ty::Dynamic(receiver_trait, _, ty::Dyn) = receiver_tail.kind() else {
span_bug!(self.cur_span(), "dynamic call on non-`dyn` type {}", receiver_tail)
};
assert!(receiver_place.layout.is_unsized());
// Get the required information from the vtable.
let vptr = receiver_place.meta().unwrap_meta().to_pointer(self)?;
let dyn_ty = self.get_ptr_vtable_ty(vptr, Some(receiver_trait))?;
let adjusted_recv = receiver_place.ptr();
// Now determine the actual method to call. Usually we use the easy way of just
// looking up the method at index `idx`.
let vtable_entries = self.vtable_entries(trait_, dyn_ty);
let vtable_entries = self.vtable_entries(receiver_trait.principal(), dyn_ty);
let Some(ty::VtblEntry::Method(fn_inst)) = vtable_entries.get(idx).copied() else {
// FIXME(fee1-dead) these could be variants of the UB info enum instead of this
throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method);
@ -830,10 +807,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
// Dropping a trait object. Need to find actual drop fn.
self.unpack_dyn_trait(&place, data)?
}
ty::Dynamic(data, _, ty::DynStar) => {
// Dropping a `dyn*`. Need to find actual drop fn.
self.unpack_dyn_star(&place, data)?
}
_ => {
debug_assert_eq!(
instance,

View file

@ -126,20 +126,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
}
CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
if let ty::Dynamic(data, _, ty::DynStar) = cast_ty.kind() {
// Initial cast from sized to dyn trait
let vtable = self.get_vtable_ptr(src.layout.ty, data)?;
let vtable = Scalar::from_maybe_pointer(vtable, self);
let data = self.read_immediate(src)?.to_scalar();
let _assert_pointer_like = data.to_pointer(self)?;
let val = Immediate::ScalarPair(data, vtable);
self.write_immediate(val, dest)?;
} else {
bug!()
}
}
CastKind::Transmute => {
assert!(src.layout.is_sized());
assert!(dest.layout.is_sized());

View file

@ -499,8 +499,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Error(_)
| ty::Dynamic(_, _, ty::DynStar) => true,
| ty::Error(_) => true,
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) | ty::Foreign(..) => false,

View file

@ -1,4 +1,4 @@
use rustc_abi::{Align, FieldIdx, Size};
use rustc_abi::{Align, Size};
use rustc_middle::mir::interpret::{InterpResult, Pointer};
use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt, Ty, TyCtxt, VtblEntry};
use tracing::trace;
@ -125,24 +125,4 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
)?;
interp_ok(mplace)
}
/// Turn a `dyn* Trait` type into an value with the actual dynamic type.
pub(super) fn unpack_dyn_star<P: Projectable<'tcx, M::Provenance>>(
&self,
val: &P,
expected_trait: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
) -> InterpResult<'tcx, P> {
assert!(
matches!(val.layout().ty.kind(), ty::Dynamic(_, _, ty::DynStar)),
"`unpack_dyn_star` only makes sense on `dyn*` types"
);
let data = self.project_field(val, FieldIdx::ZERO)?;
let vtable = self.project_field(val, FieldIdx::ONE)?;
let vtable = self.read_pointer(&vtable.to_op(self)?)?;
let ty = self.get_ptr_vtable_ty(vtable, Some(expected_trait))?;
// `data` is already the right thing but has the wrong type. So we transmute it.
let layout = self.layout_of(ty)?;
let data = data.transmute(layout, self)?;
interp_ok(data)
}
}

View file

@ -358,9 +358,6 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
// arrays/slices
ty::Array(..) | ty::Slice(..) => PathElem::ArrayElem(field),
// dyn* vtables
ty::Dynamic(_, _, ty::DynKind::DynStar) if field == 1 => PathElem::Vtable,
// dyn traits
ty::Dynamic(..) => {
assert_eq!(field, 0);

View file

@ -101,26 +101,6 @@ pub trait ValueVisitor<'tcx, M: Machine<'tcx>>: Sized {
// recurse with the inner type
return self.visit_field(v, 0, &inner_mplace.into());
}
ty::Dynamic(data, _, ty::DynStar) => {
// DynStar types. Very different from a dyn type (but strangely part of the
// same variant in `TyKind`): These are pairs where the 2nd component is the
// vtable, and the first component is the data (which must be ptr-sized).
// First make sure the vtable can be read at its type.
// The type of this vtable is fake, it claims to be a reference to some actual memory but that isn't true.
// So we transmute it to a raw pointer.
let raw_ptr_ty = Ty::new_mut_ptr(*self.ecx().tcx, self.ecx().tcx.types.unit);
let raw_ptr_ty = self.ecx().layout_of(raw_ptr_ty)?;
let vtable_field = self
.ecx()
.project_field(v, FieldIdx::ONE)?
.transmute(raw_ptr_ty, self.ecx())?;
self.visit_field(v, 1, &vtable_field)?;
// Then unpack the first field, and continue.
let data = self.ecx().unpack_dyn_star(v, data)?;
return self.visit_field(v, 0, &data);
}
// Slices do not need special handling here: they have `Array` field
// placement with length 0, so we enter the `Array` case below which
// indirectly uses the metadata to determine the actual length.

View file

@ -123,6 +123,9 @@ declare_features! (
/// [^1]: Formerly known as "object safe".
(removed, dyn_compatible_for_dispatch, "1.87.0", Some(43561),
Some("removed, not used heavily and represented additional complexity in dyn compatibility"), 136522),
/// Allows `dyn* Trait` objects.
(removed, dyn_star, "1.65.0", Some(102425),
Some("removed as it was no longer necessary for AFIDT (async fn in dyn trait) support")),
/// Uses generic effect parameters for [const] bounds
(removed, effects, "1.84.0", Some(102090),
Some("removed, redundant with `#![feature(const_trait_impl)]`"), 132479),

View file

@ -481,8 +481,6 @@ declare_features! (
(unstable, doc_cfg_hide, "1.57.0", Some(43781)),
/// Allows `#[doc(masked)]`.
(unstable, doc_masked, "1.21.0", Some(44027)),
/// Allows `dyn* Trait` objects.
(incomplete, dyn_star, "1.65.0", Some(102425)),
/// Allows the .use postfix syntax `x.use` and use closures `use |x| { ... }`
(incomplete, ergonomic_clones, "1.87.0", Some(132290)),
/// Allows exhaustive pattern matching on types that contain uninhabited types.

View file

@ -956,7 +956,7 @@ impl<'hir> Generics<'hir> {
&& let Some(ret_ty) = segment.args().paren_sugar_output()
&& let ret_ty = ret_ty.peel_refs()
&& let TyKind::TraitObject(_, tagged_ptr) = ret_ty.kind
&& let TraitObjectSyntax::Dyn | TraitObjectSyntax::DynStar = tagged_ptr.tag()
&& let TraitObjectSyntax::Dyn = tagged_ptr.tag()
&& ret_ty.span.can_be_used_for_suggestions()
{
Some(ret_ty.span)

View file

@ -45,7 +45,6 @@ define_tests! {
#[test]
fn trait_object_roundtrips() {
trait_object_roundtrips_impl(TraitObjectSyntax::Dyn);
trait_object_roundtrips_impl(TraitObjectSyntax::DynStar);
trait_object_roundtrips_impl(TraitObjectSyntax::None);
}

View file

@ -2433,7 +2433,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
} else {
let repr = match repr {
TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn,
TraitObjectSyntax::DynStar => ty::DynStar,
};
self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr)
}

View file

@ -420,7 +420,6 @@ impl<'a> State<'a> {
let syntax = lifetime.tag();
match syntax {
ast::TraitObjectSyntax::Dyn => self.word_nbsp("dyn"),
ast::TraitObjectSyntax::DynStar => self.word_nbsp("dyn*"),
ast::TraitObjectSyntax::None => {}
}
let mut first = true;

View file

@ -143,7 +143,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| ty::Coroutine(..)
| ty::Adt(..)
| ty::Never
| ty::Dynamic(_, _, ty::DynStar)
| ty::Error(_) => {
let guar = self
.dcx()
@ -734,14 +733,6 @@ impl<'a, 'tcx> CastCheck<'tcx> {
use rustc_middle::ty::cast::CastTy::*;
use rustc_middle::ty::cast::IntTy::*;
if self.cast_ty.is_dyn_star() {
// This coercion will fail if the feature is not enabled, OR
// if the coercion is (currently) illegal (e.g. `dyn* Foo + Send`
// to `dyn* Foo`). Report "casting is invalid" rather than
// "non-primitive cast".
return Err(CastError::IllegalCast);
}
let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty), CastTy::from_ty(self.cast_ty))
{
(Some(t_from), Some(t_cast)) => (t_from, t_cast),

View file

@ -231,9 +231,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
ty::Ref(r_b, _, mutbl_b) => {
return self.coerce_borrowed_pointer(a, b, r_b, mutbl_b);
}
ty::Dynamic(predicates, region, ty::DynStar) if self.tcx.features().dyn_star() => {
return self.coerce_dyn_star(a, b, predicates, region);
}
ty::Adt(pin, _)
if self.tcx.features().pin_ergonomics()
&& self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) =>
@ -773,71 +770,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
Ok(coercion)
}
fn coerce_dyn_star(
&self,
a: Ty<'tcx>,
b: Ty<'tcx>,
predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
b_region: ty::Region<'tcx>,
) -> CoerceResult<'tcx> {
if !self.tcx.features().dyn_star() {
return Err(TypeError::Mismatch);
}
// FIXME(dyn_star): We should probably allow things like casting from
// `dyn* Foo + Send` to `dyn* Foo`.
if let ty::Dynamic(a_data, _, ty::DynStar) = a.kind()
&& let ty::Dynamic(b_data, _, ty::DynStar) = b.kind()
&& a_data.principal_def_id() == b_data.principal_def_id()
{
return self.unify(a, b);
}
// Check the obligations of the cast -- for example, when casting
// `usize` to `dyn* Clone + 'static`:
let obligations = predicates
.iter()
.map(|predicate| {
// For each existential predicate (e.g., `?Self: Clone`) instantiate
// the type of the expression (e.g., `usize` in our example above)
// and then require that the resulting predicate (e.g., `usize: Clone`)
// holds (it does).
let predicate = predicate.with_self_ty(self.tcx, a);
Obligation::new(self.tcx, self.cause.clone(), self.param_env, predicate)
})
.chain([
// Enforce the region bound (e.g., `usize: 'static`, in our example).
Obligation::new(
self.tcx,
self.cause.clone(),
self.param_env,
ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
ty::OutlivesPredicate(a, b_region),
))),
),
// Enforce that the type is `usize`/pointer-sized.
Obligation::new(
self.tcx,
self.cause.clone(),
self.param_env,
ty::TraitRef::new(
self.tcx,
self.tcx.require_lang_item(hir::LangItem::PointerLike, self.cause.span),
[a],
),
),
])
.collect();
Ok(InferOk {
value: (
vec![Adjustment { kind: Adjust::Pointer(PointerCoercion::DynStar), target: b }],
b,
),
obligations,
})
}
/// Applies reborrowing for `Pin`
///
/// We currently only support reborrowing `Pin<&mut T>` as `Pin<&mut T>`. This is accomplished

View file

@ -36,9 +36,6 @@ pub enum PointerCoercion {
/// type. Codegen backends and miri figure out what has to be done
/// based on the precise source/target type at hand.
Unsize,
/// Go from a pointer-like type to a `dyn*` object.
DynStar,
}
/// Represents coercing a value to a different type of value.

View file

@ -946,21 +946,6 @@ where
}
}
ty::Dynamic(_, _, ty::DynStar) => {
if i == 0 {
TyMaybeWithLayout::Ty(Ty::new_mut_ptr(tcx, tcx.types.unit))
} else if i == 1 {
// FIXME(dyn-star) same FIXME as above applies here too
TyMaybeWithLayout::Ty(Ty::new_imm_ref(
tcx,
tcx.lifetimes.re_static,
Ty::new_array(tcx, tcx.types.usize, 3),
))
} else {
bug!("no field {i} on dyn*")
}
}
ty::Alias(..)
| ty::Bound(..)
| ty::Placeholder(..)

View file

@ -810,7 +810,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
match repr {
ty::Dyn => p!("dyn "),
ty::DynStar => p!("dyn* "),
}
p!(print(data));
if print_r {

View file

@ -1321,11 +1321,6 @@ impl<'tcx> Ty<'tcx> {
matches!(self.kind(), Dynamic(_, _, ty::Dyn))
}
#[inline]
pub fn is_dyn_star(self) -> bool {
matches!(self.kind(), Dynamic(_, _, ty::DynStar))
}
#[inline]
pub fn is_enum(self) -> bool {
matches!(self.kind(), Adt(adt_def, _) if adt_def.is_enum())
@ -1629,8 +1624,6 @@ impl<'tcx> Ty<'tcx> {
| ty::Error(_)
// Extern types have metadata = ().
| ty::Foreign(..)
// `dyn*` has metadata = ().
| ty::Dynamic(_, _, ty::DynStar)
// If returned by `struct_tail_raw` this is a unit struct
// without any fields, or not a struct, and therefore is Sized.
| ty::Adt(..)
@ -1820,8 +1813,7 @@ impl<'tcx> Ty<'tcx> {
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Error(_)
| ty::Dynamic(_, _, ty::DynStar) => true,
| ty::Error(_) => true,
ty::Str | ty::Slice(_) | ty::Dynamic(_, _, ty::Dyn) => match sizedness {
SizedTraitKind::Sized => false,

View file

@ -74,8 +74,7 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
match *rvalue {
// We need to detect unsizing casts that required vtables.
mir::Rvalue::Cast(
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _)
| mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _),
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _),
ref operand,
target_ty,
) => {

View file

@ -1260,9 +1260,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.fail(location, format!("Unsize coercion, but `{op_ty}` isn't coercible to `{target_type}`"));
}
}
CastKind::PointerCoercion(PointerCoercion::DynStar, _) => {
// FIXME(dyn-star): make sure nothing needs to be done here.
}
CastKind::IntToInt | CastKind::IntToFloat => {
let input_valid = op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
let target_valid = target_type.is_numeric() || target_type.is_char();

View file

@ -694,8 +694,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
// have to instantiate all methods of the trait being cast to, so we
// can build the appropriate vtable.
mir::Rvalue::Cast(
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _)
| mir::CastKind::PointerCoercion(PointerCoercion::DynStar, _),
mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _),
ref operand,
target_ty,
) => {
@ -710,9 +709,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
// This could also be a different Unsize instruction, like
// from a fixed sized array to a slice. But we are only
// interested in things that produce a vtable.
if (target_ty.is_trait() && !source_ty.is_trait())
|| (target_ty.is_dyn_star() && !source_ty.is_dyn_star())
{
if target_ty.is_trait() && !source_ty.is_trait() {
create_mono_items_for_vtable_methods(
self.tcx,
target_ty,
@ -1109,14 +1106,6 @@ fn find_tails_for_unsizing<'tcx>(
find_tails_for_unsizing(tcx, source_field, target_field)
}
// `T` as `dyn* Trait` unsizes *directly*.
//
// FIXME(dyn_star): This case is a bit awkward, b/c we're not really computing
// a tail here. We probably should handle this separately in the *caller* of
// this function, rather than returning something that is semantically different
// than what we return above.
(_, &ty::Dynamic(_, _, ty::DynStar)) => (source_ty, target_ty),
_ => bug!(
"find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}",
source_ty,
@ -1344,9 +1333,7 @@ fn visit_mentioned_item<'tcx>(
// This could also be a different Unsize instruction, like
// from a fixed sized array to a slice. But we are only
// interested in things that produce a vtable.
if (target_ty.is_trait() && !source_ty.is_trait())
|| (target_ty.is_dyn_star() && !source_ty.is_dyn_star())
{
if target_ty.is_trait() && !source_ty.is_trait() {
create_mono_items_for_vtable_methods(tcx, target_ty, source_ty, span, output);
}
}

View file

@ -135,7 +135,6 @@ where
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Dynamic(_, _, ty::DynStar)
| ty::Error(_) => Ok(ty::Binder::dummy(vec![])),
// impl {Meta,}Sized for str, [T], dyn Trait

View file

@ -657,8 +657,7 @@ where
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Never
| ty::Foreign(..)
| ty::Dynamic(_, _, ty::DynStar) => Ty::new_unit(cx),
| ty::Foreign(..) => Ty::new_unit(cx),
ty::Error(e) => Ty::new_error(cx, e),

View file

@ -796,16 +796,10 @@ impl<'a> Parser<'a> {
///
/// Note that this does *not* parse bare trait objects.
fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> {
let lo = self.token.span;
self.bump(); // `dyn`
// parse dyn* types
let syntax = if self.eat(exp!(Star)) {
self.psess.gated_spans.gate(sym::dyn_star, lo.to(self.prev_token.span));
TraitObjectSyntax::DynStar
} else {
TraitObjectSyntax::Dyn
};
// We used to parse `*` for `dyn*` here.
let syntax = TraitObjectSyntax::Dyn;
// Always parse bounds greedily for better error recovery.
let bounds = self.parse_generic_bounds()?;

View file

@ -631,7 +631,6 @@ pub(crate) fn encode_ty<'tcx>(
// vendor extended type.
let mut s = String::from(match kind {
ty::Dyn => "u3dynI",
ty::DynStar => "u7dynstarI",
});
s.push_str(&encode_predicates(tcx, predicates, dict, options));
s.push_str(&encode_region(*region, dict));

View file

@ -369,7 +369,6 @@ impl RustcInternal for DynKind {
fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
DynKind::Dyn => rustc_ty::DynKind::Dyn,
DynKind::DynStar => rustc_ty::DynKind::DynStar,
}
}
}

View file

@ -301,11 +301,9 @@ impl<'tcx> Stable<'tcx> for mir::CastKind {
type T = stable_mir::mir::CastKind;
fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::CastKind::*;
use rustc_middle::ty::adjustment::PointerCoercion;
match self {
PointerExposeProvenance => stable_mir::mir::CastKind::PointerExposeAddress,
PointerWithExposedProvenance => stable_mir::mir::CastKind::PointerWithExposedProvenance,
PointerCoercion(PointerCoercion::DynStar, _) => stable_mir::mir::CastKind::DynStar,
PointerCoercion(c, _) => stable_mir::mir::CastKind::PointerCoercion(c.stable(tables)),
IntToInt => stable_mir::mir::CastKind::IntToInt,
FloatToInt => stable_mir::mir::CastKind::FloatToInt,

View file

@ -43,7 +43,6 @@ impl<'tcx> Stable<'tcx> for ty::DynKind {
fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
ty::Dyn => stable_mir::ty::DynKind::Dyn,
ty::DynStar => stable_mir::ty::DynKind::DynStar,
}
}
}
@ -120,7 +119,6 @@ impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
}
PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer,
PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize,
PointerCoercion::DynStar => unreachable!("represented as `CastKind::DynStar` in smir"),
}
}
}

View file

@ -1025,8 +1025,6 @@ pub enum CastKind {
PointerExposeAddress,
PointerWithExposedProvenance,
PointerCoercion(PointerCoercion),
// FIXME(smir-rename): change this to PointerCoercion(DynStar)
DynStar,
IntToInt,
FloatToInt,
FloatToFloat,

View file

@ -1205,7 +1205,6 @@ pub enum BoundRegionKind {
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
pub enum DynKind {
Dyn,
DynStar,
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]

View file

@ -576,8 +576,6 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
ty::Dynamic(predicates, r, kind) => {
self.push(match kind {
ty::Dyn => "D",
// FIXME(dyn-star): need to update v0 mangling docs
ty::DynStar => "D*",
});
self.print_dyn_existential(predicates)?;
r.print(self)?;

View file

@ -353,26 +353,6 @@ impl<T> Trait<T> for X {
));
}
}
(ty::Dynamic(t, _, ty::DynKind::DynStar), _)
if let Some(def_id) = t.principal_def_id() =>
{
let mut has_matching_impl = false;
tcx.for_each_relevant_impl(def_id, values.found, |did| {
if DeepRejectCtxt::relate_rigid_infer(tcx)
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
{
has_matching_impl = true;
}
});
if has_matching_impl {
let trait_name = tcx.item_name(def_id);
diag.help(format!(
"`{}` implements `{trait_name}`, `#[feature(dyn_star)]` is likely \
not enabled; that feature it is currently incomplete",
values.found,
));
}
}
(_, ty::Alias(ty::Opaque, opaque_ty))
| (ty::Alias(ty::Opaque, opaque_ty), _) => {
if opaque_ty.def_id.is_local()

View file

@ -2129,7 +2129,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
| ty::Closure(..)
| ty::CoroutineClosure(..)
| ty::Never
| ty::Dynamic(_, _, ty::DynStar)
| ty::Error(_) => {
// safe for everything
Where(ty::Binder::dummy(Vec::new()))

View file

@ -449,14 +449,6 @@ fn layout_of_uncached<'tcx>(
tcx.mk_layout(LayoutData::scalar_pair(cx, data_ptr, metadata))
}
ty::Dynamic(_, _, ty::DynStar) => {
let mut data = scalar_unit(Pointer(AddressSpace::DATA));
data.valid_range_mut().start = 0;
let mut vtable = scalar_unit(Pointer(AddressSpace::DATA));
vtable.valid_range_mut().start = 1;
tcx.mk_layout(LayoutData::scalar_pair(cx, data, vtable))
}
// Arrays and slices.
ty::Array(element, count) => {
let count = extract_const_value(cx, ty, count)?

View file

@ -38,8 +38,7 @@ fn sizedness_constraint_for_ty<'tcx>(
| ty::CoroutineClosure(..)
| ty::Coroutine(..)
| ty::CoroutineWitness(..)
| ty::Never
| ty::Dynamic(_, _, ty::DynStar) => None,
| ty::Never => None,
ty::Str | ty::Slice(..) | ty::Dynamic(_, _, ty::Dyn) => match sizedness {
// Never `Sized`
@ -383,8 +382,7 @@ fn impl_self_is_guaranteed_unsized<'tcx>(tcx: TyCtxt<'tcx>, impl_def_id: DefId)
| ty::Bound(_, _)
| ty::Placeholder(_)
| ty::Infer(_)
| ty::Error(_)
| ty::Dynamic(_, _, ty::DynStar) => false,
| ty::Error(_) => false,
}
}

View file

@ -183,8 +183,7 @@ pub trait Ty<I: Interner<Ty = Self>>:
| ty::Bound(_, _)
| ty::Placeholder(_)
| ty::Infer(_)
| ty::Error(_)
| ty::Dynamic(_, _, ty::DynStar) => false,
| ty::Error(_) => false,
}
}
}

View file

@ -20,6 +20,9 @@ use crate::{self as ty, DebruijnIndex, Interner};
mod closure;
/// Specifies how a trait object is represented.
///
/// This used to have a variant `DynStar`, but that variant has been removed,
/// and it's likely this whole enum will be removed soon.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[cfg_attr(
feature = "nightly",
@ -28,13 +31,6 @@ mod closure;
pub enum DynKind {
/// An unsized `dyn Trait` object
Dyn,
/// A sized `dyn* Trait` object
///
/// These objects are represented as a `(data, vtable)` pair where `data` is a value of some
/// ptr-sized and ptr-aligned dynamically determined type `T` and `vtable` is a pointer to the
/// vtable of `impl T for Trait`. This allows a `dyn*` object to be treated agnostically with
/// respect to whether it points to a `Box<T>`, `Rc<T>`, etc.
DynStar,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
@ -371,7 +367,6 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
UnsafeBinder(binder) => write!(f, "{:?}", binder),
Dynamic(p, r, repr) => match repr {
DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
},
Closure(d, s) => f.debug_tuple("Closure").field(d).field(&s).finish(),
CoroutineClosure(d, s) => f.debug_tuple("CoroutineClosure").field(d).field(&s).finish(),

View file

@ -175,10 +175,6 @@ fn check_rvalue<'tcx>(
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) => {
Err((span, "casting pointers to ints is unstable in const fn".into()))
},
Rvalue::Cast(CastKind::PointerCoercion(PointerCoercion::DynStar, _), _, _) => {
// FIXME(dyn-star)
unimplemented!()
},
Rvalue::Cast(CastKind::Transmute, _, _) => Err((
span,
"transmute can attempt to turn pointers into integers, so is unstable in const fn".into(),

View file

@ -595,10 +595,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
} else if matches!(v.layout.fields, FieldsShape::Union(..)) {
// A (non-frozen) union. We fall back to whatever the type says.
(self.unsafe_cell_action)(v)
} else if matches!(v.layout.ty.kind(), ty::Dynamic(_, _, ty::DynStar)) {
// This needs to read the vtable pointer to proceed type-driven, but we don't
// want to reentrantly read from memory here.
(self.unsafe_cell_action)(v)
} else {
// We want to not actually read from memory for this visit. So, before
// walking this value, we have to make sure it is not a

View file

@ -1,103 +0,0 @@
#![feature(dyn_star)]
#![allow(incomplete_features)]
#![feature(custom_inner_attributes)]
// rustfmt destroys `dyn* Trait` syntax
#![rustfmt::skip]
use std::fmt::{Debug, Display};
fn main() {
make_dyn_star();
method();
box_();
dispatch_on_pin_mut();
dyn_star_to_dyn();
dyn_to_dyn_star();
}
fn dyn_star_to_dyn() {
let x: dyn* Debug = &42;
let x = Box::new(x) as Box<dyn Debug>;
assert_eq!("42", format!("{x:?}"));
}
fn dyn_to_dyn_star() {
let x: Box<dyn Debug> = Box::new(42);
let x = &x as dyn* Debug;
assert_eq!("42", format!("{x:?}"));
}
fn make_dyn_star() {
fn make_dyn_star_coercion(i: usize) {
let _dyn_i: dyn* Debug = i;
}
fn make_dyn_star_explicit(i: usize) {
let _dyn_i: dyn* Debug = i as dyn* Debug;
}
make_dyn_star_coercion(42);
make_dyn_star_explicit(42);
}
fn method() {
trait Foo {
fn get(&self) -> usize;
}
impl Foo for usize {
fn get(&self) -> usize {
*self
}
}
fn invoke_dyn_star(i: dyn* Foo) -> usize {
i.get()
}
fn make_and_invoke_dyn_star(i: usize) -> usize {
let dyn_i: dyn* Foo = i;
invoke_dyn_star(dyn_i)
}
assert_eq!(make_and_invoke_dyn_star(42), 42);
}
fn box_() {
fn make_dyn_star() -> dyn* Display {
Box::new(42) as dyn* Display
}
let x = make_dyn_star();
assert_eq!(format!("{x}"), "42");
}
fn dispatch_on_pin_mut() {
use std::future::Future;
async fn foo(f: dyn* Future<Output = i32>) {
println!("dispatch_on_pin_mut: value: {}", f.await);
}
async fn async_main() {
foo(Box::pin(async { 1 })).await
}
// ------------------------------------------------------------------------- //
// Implementation Details Below...
use std::pin::Pin;
use std::task::*;
let mut fut = async_main();
// Poll loop, just to test the future...
let ctx = &mut Context::from_waker(Waker::noop());
loop {
match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
Poll::Pending => {}
Poll::Ready(()) => break,
}
}
}

View file

@ -835,12 +835,6 @@ impl Rewrite for ast::Ty {
.max_width_error(shape.width, self.span())?;
(shape, "dyn ")
}
ast::TraitObjectSyntax::DynStar => {
let shape = shape
.offset_left(5)
.max_width_error(shape.width, self.span())?;
(shape, "dyn* ")
}
ast::TraitObjectSyntax::None => (shape, ""),
};
let mut res = bounds.rewrite_result(context, shape)?;

View file

@ -1,10 +0,0 @@
#![feature(dyn_star)]
#![allow(incomplete_features)]
use core::fmt::Debug;
fn main() {
let i = 42;
let dyn_i = i as dyn* Debug;
dbg!(dyn_i);
}

View file

@ -930,7 +930,6 @@ ui/dst/issue-90528-unsizing-suggestion-3.rs
ui/dst/issue-90528-unsizing-suggestion-4.rs
ui/dyn-keyword/issue-5153.rs
ui/dyn-keyword/issue-56327-dyn-trait-in-macro-is-okay.rs
ui/dyn-star/issue-102430.rs
ui/empty/issue-37026.rs
ui/entry-point/issue-118772.rs
ui/enum-discriminant/auxiliary/issue-41394.rs

View file

@ -1,7 +1,6 @@
//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes
#![crate_type = "lib"]
#![feature(rustc_attrs)]
#![feature(dyn_star)]
#![feature(allocator_api)]
use std::marker::PhantomPinned;
@ -277,11 +276,3 @@ pub fn enum_id_1(x: Option<Result<u16, u16>>) -> Option<Result<u16, u16>> {
pub fn enum_id_2(x: Option<u8>) -> Option<u8> {
x
}
// CHECK: { ptr, {{.+}} } @dyn_star(ptr noundef %x.0, {{.+}} noalias noundef readonly align {{.*}} dereferenceable({{.*}}) %x.1)
// Expect an ABI something like `{ {}*, [3 x i64]* }`, but that's hard to match on generically,
// so do like the `trait_box` test and just match on `{{.+}}` for the vtable.
#[no_mangle]
pub fn dyn_star(x: dyn* Drop) -> dyn* Drop {
x
}

View file

@ -1,14 +0,0 @@
//@ known-bug: #116979
//@ compile-flags: -Csymbol-mangling-version=v0
//@ needs-rustc-debug-assertions
#![feature(dyn_star)]
#![allow(incomplete_features)]
use std::fmt::Display;
pub fn require_dyn_star_display(_: dyn* Display) {}
fn main() {
require_dyn_star_display(1usize);
}

View file

@ -1,18 +0,0 @@
//@ known-bug: #119694
#![feature(dyn_star)]
trait Trait {
fn foo(self);
}
impl Trait for usize {
fn foo(self) {}
}
fn bar(x: dyn* Trait) {
x.foo();
}
fn main() {
bar(0usize);
}

View file

@ -484,10 +484,6 @@ The `dyn` keyword is used to highlight that calls to methods on the associated T
See [`dyn` keyword](https://doc.rust-lang.org/std/keyword.dyn.html).
## `tests/ui/dyn-star/`: `dyn*`, Sized `dyn`, `#![feature(dyn_star)]`
See [Tracking issue for dyn-star #102425](https://github.com/rust-lang/rust/issues/102425).
## `tests/ui/editions/`: Rust edition-specific peculiarities
These tests run in specific Rust editions, such as Rust 2015 or Rust 2018, and check errors and functionality related to specific now-deprecated idioms and features.

View file

@ -1,20 +0,0 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/align.rs:3:12
|
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: `AlignedUsize` needs to have the same ABI as a pointer
--> $DIR/align.rs:14:13
|
LL | let x = AlignedUsize(12) as dyn* Debug;
| ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-like type
|
= help: the trait `PointerLike` is not implemented for `AlignedUsize`
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,20 +0,0 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/align.rs:3:12
|
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: `AlignedUsize` needs to have the same ABI as a pointer
--> $DIR/align.rs:14:13
|
LL | let x = AlignedUsize(12) as dyn* Debug;
| ^^^^^^^^^^^^^^^^ `AlignedUsize` needs to be a pointer-like type
|
= help: the trait `PointerLike` is not implemented for `AlignedUsize`
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,16 +0,0 @@
//@ revisions: normal over_aligned
#![feature(dyn_star)]
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
use std::fmt::Debug;
#[cfg_attr(over_aligned, repr(C, align(1024)))]
#[cfg_attr(not(over_aligned), repr(C))]
#[derive(Debug)]
struct AlignedUsize(usize);
fn main() {
let x = AlignedUsize(12) as dyn* Debug;
//~^ ERROR `AlignedUsize` needs to have the same ABI as a pointer
}

View file

@ -1,9 +0,0 @@
//@ edition:2018
#![feature(dyn_star, const_async_blocks)]
//~^ WARN the feature `dyn_star` is incomplete
static S: dyn* Send + Sync = async { 42 };
//~^ ERROR needs to have the same ABI as a pointer
pub fn main() {}

View file

@ -1,20 +0,0 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/async-block-dyn-star.rs:3:12
|
LL | #![feature(dyn_star, const_async_blocks)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: `{async block@$DIR/async-block-dyn-star.rs:6:30: 6:35}` needs to have the same ABI as a pointer
--> $DIR/async-block-dyn-star.rs:6:30
|
LL | static S: dyn* Send + Sync = async { 42 };
| ^^^^^^^^^^^^ `{async block@$DIR/async-block-dyn-star.rs:6:30: 6:35}` needs to be a pointer-like type
|
= help: the trait `PointerLike` is not implemented for `{async block@$DIR/async-block-dyn-star.rs:6:30: 6:35}`
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,9 +0,0 @@
#![feature(dyn_star)]
use std::fmt::Display;
pub fn require_dyn_star_display(_: dyn* Display) {}
fn works_locally() {
require_dyn_star_display(1usize);
}

View file

@ -1,20 +0,0 @@
//@ run-pass
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[current] compile-flags: -C opt-level=0
//@[next] compile-flags: -Znext-solver -C opt-level=0
#![feature(dyn_star)]
#![allow(incomplete_features)]
use std::fmt::Display;
fn make_dyn_star() -> dyn* Display {
Box::new(42) as dyn* Display
}
fn main() {
let x = make_dyn_star();
println!("{x}");
}

View file

@ -1,34 +0,0 @@
// This test with Cell also indirectly exercises UnsafeCell in dyn*.
//
//@ run-pass
#![feature(dyn_star)]
#![allow(incomplete_features)]
use std::cell::Cell;
trait Rw<T> {
fn read(&self) -> T;
fn write(&self, v: T);
}
impl<T: Copy> Rw<T> for Cell<T> {
fn read(&self) -> T {
self.get()
}
fn write(&self, v: T) {
self.set(v)
}
}
fn make_dyn_star() -> dyn* Rw<usize> {
Cell::new(42usize) as dyn* Rw<usize>
}
fn main() {
let x = make_dyn_star();
assert_eq!(x.read(), 42);
x.write(24);
assert_eq!(x.read(), 24);
}

View file

@ -1,18 +0,0 @@
error[E0277]: `&T` needs to have the same ABI as a pointer
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) {
| - this type parameter needs to be `Sized`
LL | dyn_debug(t);
| ^ `&T` needs to be a pointer-like type
|
= note: required for `&T` to implement `PointerLike`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn polymorphic<T: Debug + ?Sized>(t: &T) {
LL + fn polymorphic<T: Debug>(t: &T) {
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,18 +0,0 @@
error[E0277]: `&T` needs to have the same ABI as a pointer
--> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
|
LL | fn polymorphic<T: Debug + ?Sized>(t: &T) {
| - this type parameter needs to be `Sized`
LL | dyn_debug(t);
| ^ `&T` needs to be a pointer-like type
|
= note: required for `&T` to implement `PointerLike`
help: consider removing the `?Sized` bound to make the type parameter `Sized`
|
LL - fn polymorphic<T: Debug + ?Sized>(t: &T) {
LL + fn polymorphic<T: Debug>(t: &T) {
|
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,19 +0,0 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
#![feature(dyn_star)]
#![allow(incomplete_features)]
use std::fmt::Debug;
fn dyn_debug(_: (dyn* Debug + '_)) {
}
fn polymorphic<T: Debug + ?Sized>(t: &T) {
dyn_debug(t);
//~^ ERROR `&T` needs to have the same ABI as a pointer
}
fn main() {}

View file

@ -1,16 +0,0 @@
//@ check-pass
#![feature(dyn_star)]
#![allow(incomplete_features)]
use std::fmt::Debug;
fn dyn_debug(_: (dyn* Debug + '_)) {
}
fn polymorphic<T: Debug>(t: &T) {
dyn_debug(t);
}
fn main() {}

View file

@ -1,10 +0,0 @@
#![feature(dyn_star)]
#![allow(incomplete_features)]
use std::fmt::Debug;
fn main() {
let i = [1, 2, 3, 4] as dyn* Debug;
//~^ ERROR `[i32; 4]` needs to have the same ABI as a pointer
dbg!(i);
}

View file

@ -1,11 +0,0 @@
error[E0277]: `[i32; 4]` needs to have the same ABI as a pointer
--> $DIR/check-size-at-cast.rs:7:13
|
LL | let i = [1, 2, 3, 4] as dyn* Debug;
| ^^^^^^^^^^^^ `[i32; 4]` needs to be a pointer-like type
|
= help: the trait `PointerLike` is not implemented for `[i32; 4]`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,10 +0,0 @@
//@ check-pass
#![feature(dyn_star)]
//~^ WARN the feature `dyn_star` is incomplete
const C: dyn* Send + Sync = &();
static S: dyn* Send + Sync = &();
fn main() {}

View file

@ -1,11 +0,0 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/const-and-static.rs:3:12
|
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View file

@ -1,14 +0,0 @@
//@ run-pass
#![feature(dyn_star)]
#![allow(unused, incomplete_features)]
use std::fmt::Debug;
fn make_dyn_star() {
let i = 42usize;
let dyn_i: dyn* Debug = i;
}
fn main() {
make_dyn_star();
}

View file

@ -1,36 +0,0 @@
//@ run-pass
//@ edition:2021
//@ check-run-results
#![feature(dyn_star)]
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
use std::future::Future;
async fn foo(f: dyn* Future<Output = i32>) {
println!("value: {}", f.await);
}
async fn async_main() {
foo(Box::pin(async { 1 })).await
}
// ------------------------------------------------------------------------- //
// Implementation Details Below...
use std::pin::pin;
use std::task::*;
fn main() {
let mut fut = pin!(async_main());
// Poll loop, just to test the future...
let ctx = &mut Context::from_waker(Waker::noop());
loop {
match fut.as_mut().poll(ctx) {
Poll::Pending => {}
Poll::Ready(()) => break,
}
}
}

View file

@ -1 +0,0 @@
value: 1

View file

@ -1,11 +0,0 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/dispatch-on-pin-mut.rs:5:12
|
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View file

@ -1,27 +0,0 @@
//@ run-pass
//@ check-run-results
#![feature(dyn_star)]
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
trait AddOne {
fn add1(&mut self) -> usize;
}
impl AddOne for usize {
fn add1(&mut self) -> usize {
*self += 1;
*self
}
}
fn add_one(i: &mut (dyn* AddOne + '_)) -> usize {
i.add1()
}
fn main() {
let mut x = 42usize as dyn* AddOne;
println!("{}", add_one(&mut x));
println!("{}", add_one(&mut x));
}

View file

@ -1,11 +0,0 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/dont-unsize-coerce-dyn-star.rs:4:12
|
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View file

@ -1,28 +0,0 @@
//@ run-pass
//@ check-run-results
#![feature(dyn_star, pointer_like_trait)]
#![allow(incomplete_features)]
use std::fmt::Debug;
use std::marker::PointerLike;
#[derive(Debug)]
#[repr(transparent)]
struct Foo(#[allow(dead_code)] usize);
// FIXME(dyn_star): Make this into a derive.
impl PointerLike for Foo {}
impl Drop for Foo {
fn drop(&mut self) {
println!("destructor called");
}
}
fn make_dyn_star(i: Foo) {
let _dyn_i: dyn* Debug = i;
}
fn main() {
make_dyn_star(Foo(42));
}

View file

@ -1 +0,0 @@
destructor called

View file

@ -1,36 +0,0 @@
//@ check-pass
//@ edition: 2021
// This test case is meant to demonstrate how close we can get to async
// functions in dyn traits with the current level of dyn* support.
#![feature(dyn_star)]
#![allow(incomplete_features)]
use std::future::Future;
trait DynAsyncCounter {
fn increment<'a>(&'a mut self) -> dyn* Future<Output = usize> + 'a;
}
struct MyCounter {
count: usize,
}
impl DynAsyncCounter for MyCounter {
fn increment<'a>(&'a mut self) -> dyn* Future<Output = usize> + 'a {
Box::pin(async {
self.count += 1;
self.count
})
}
}
async fn do_counter(counter: &mut dyn DynAsyncCounter) -> usize {
counter.increment().await
}
fn main() {
let mut counter = MyCounter { count: 0 };
let _ = do_counter(&mut counter);
}

View file

@ -1,23 +0,0 @@
// Test that `dyn PointerLike` and `dyn* PointerLike` do not implement `PointerLike`.
// This used to ICE during codegen.
#![crate_type = "lib"]
#![feature(pointer_like_trait, dyn_star)]
#![feature(unsized_fn_params)]
#![expect(incomplete_features)]
#![expect(internal_features)]
use std::marker::PointerLike;
pub fn lol(x: dyn* PointerLike) {
foo(x); //~ ERROR `dyn* PointerLike` needs to have the same ABI as a pointer
}
pub fn uwu(x: dyn PointerLike) {
foo(x); //~ ERROR `dyn PointerLike` needs to have the same ABI as a pointer
}
fn foo<T: PointerLike + ?Sized>(x: T) {
let _: dyn* PointerLike = x;
}

View file

@ -1,39 +0,0 @@
error[E0277]: `dyn* PointerLike` needs to have the same ABI as a pointer
--> $DIR/dyn-pointer-like.rs:14:9
|
LL | foo(x);
| --- ^ the trait `PointerLike` is not implemented for `dyn* PointerLike`
| |
| required by a bound introduced by this call
|
= note: the trait bound `dyn* PointerLike: PointerLike` is not satisfied
note: required by a bound in `foo`
--> $DIR/dyn-pointer-like.rs:21:11
|
LL | fn foo<T: PointerLike + ?Sized>(x: T) {
| ^^^^^^^^^^^ required by this bound in `foo`
help: consider borrowing here
|
LL | foo(&x);
| +
LL | foo(&mut x);
| ++++
error[E0277]: `dyn PointerLike` needs to have the same ABI as a pointer
--> $DIR/dyn-pointer-like.rs:18:9
|
LL | foo(x);
| --- ^ `dyn PointerLike` needs to be a pointer-like type
| |
| required by a bound introduced by this call
|
= help: the trait `PointerLike` is not implemented for `dyn PointerLike`
note: required by a bound in `foo`
--> $DIR/dyn-pointer-like.rs:21:11
|
LL | fn foo<T: PointerLike + ?Sized>(x: T) {
| ^^^^^^^^^^^ required by this bound in `foo`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,17 +0,0 @@
//@ run-pass
#![feature(dyn_star)]
//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
use std::fmt::Debug;
fn main() {
let x: dyn* Debug = &42;
let x = Box::new(x) as Box<dyn Debug>;
assert_eq!("42", format!("{x:?}"));
// Also test opposite direction.
let x: Box<dyn Debug> = Box::new(42);
let x = &x as dyn* Debug;
assert_eq!("42", format!("{x:?}"));
}

View file

@ -1,11 +0,0 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/dyn-star-to-dyn.rs:3:12
|
LL | #![feature(dyn_star)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
warning: 1 warning emitted

View file

@ -1,11 +0,0 @@
#![feature(dyn_star)]
#![allow(incomplete_features)]
trait Tr {}
fn f(x: dyn* Tr) -> usize {
x as usize
//~^ ERROR non-primitive cast: `(dyn* Tr + 'static)` as `usize`
}
fn main() {}

View file

@ -1,9 +0,0 @@
error[E0605]: non-primitive cast: `(dyn* Tr + 'static)` as `usize`
--> $DIR/dyn-to-rigid.rs:7:5
|
LL | x as usize
| ^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0605`.

View file

@ -1,23 +0,0 @@
//@ check-pass
// This used to ICE, because the compiler confused a pointer-like to dyn* coercion
// with a c-like enum to integer cast.
#![feature(dyn_star, pointer_like_trait)]
#![expect(incomplete_features)]
use std::marker::PointerLike;
#[repr(transparent)]
enum E {
Num(usize),
}
impl PointerLike for E {}
trait Trait {}
impl Trait for E {}
fn main() {
let _ = E::Num(42) as dyn* Trait;
}

View file

@ -1,13 +0,0 @@
#![feature(dyn_star)]
#![allow(incomplete_features)]
use std::fmt::Debug;
trait Foo {}
fn make_dyn_star() {
let i = 42usize;
let dyn_i: dyn* Foo = i; //~ ERROR trait bound `usize: Foo` is not satisfied
}
fn main() {}

View file

@ -1,15 +0,0 @@
error[E0277]: the trait bound `usize: Foo` is not satisfied
--> $DIR/error.rs:10:27
|
LL | let dyn_i: dyn* Foo = i;
| ^ the trait `Foo` is not implemented for `usize`
|
help: this trait has no implementations, consider adding one
--> $DIR/error.rs:6:1
|
LL | trait Foo {}
| ^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,9 +0,0 @@
// Feature gate test for dyn_star
/// dyn* is not necessarily the final surface syntax (if we have one at all),
/// but for now we will support it to aid in writing tests independently.
pub fn dyn_star_parameter(_: &dyn* Send) {
//~^ ERROR `dyn*` trait objects are experimental
}
fn main() {}

View file

@ -1,13 +0,0 @@
error[E0658]: `dyn*` trait objects are experimental
--> $DIR/feature-gate-dyn_star.rs:5:31
|
LL | pub fn dyn_star_parameter(_: &dyn* Send) {
| ^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= help: add `#![feature(dyn_star)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.

View file

@ -1,16 +0,0 @@
//@ only-x86_64
#![feature(dyn_star, pointer_like_trait)]
//~^ WARN the feature `dyn_star` is incomplete
use std::fmt::Debug;
use std::marker::PointerLike;
fn make_dyn_star() -> dyn* Debug + 'static {
f32::from_bits(0x1) as f64
//~^ ERROR `f64` needs to have the same ABI as a pointer
}
fn main() {
println!("{:?}", make_dyn_star());
}

View file

@ -1,23 +0,0 @@
warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/float-as-dyn-star.rs:3:12
|
LL | #![feature(dyn_star, pointer_like_trait)]
| ^^^^^^^^
|
= note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
= note: `#[warn(incomplete_features)]` on by default
error[E0277]: `f64` needs to have the same ABI as a pointer
--> $DIR/float-as-dyn-star.rs:10:5
|
LL | f32::from_bits(0x1) as f64
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ `f64` needs to be a pointer-like type
|
= help: the trait `PointerLike` is not implemented for `f64`
= help: the following other types implement trait `PointerLike`:
isize
usize
error: aborting due to 1 previous error; 1 warning emitted
For more information about this error, try `rustc --explain E0277`.

View file

@ -1,8 +0,0 @@
macro_rules! t {
($t:ty) => {}
}
t!(dyn* Send);
//~^ ERROR `dyn*` trait objects are experimental
fn main() {}

Some files were not shown because too many files have changed in this diff Show more