Remove support for dyn*
This commit is contained in:
parent
4e97337005
commit
2516c33982
143 changed files with 114 additions and 2203 deletions
|
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(_, _)));
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>(
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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>>(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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(..)
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
) => {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
||||
|
|
|
|||
|
|
@ -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()?;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1025,8 +1025,6 @@ pub enum CastKind {
|
|||
PointerExposeAddress,
|
||||
PointerWithExposedProvenance,
|
||||
PointerCoercion(PointerCoercion),
|
||||
// FIXME(smir-rename): change this to PointerCoercion(DynStar)
|
||||
DynStar,
|
||||
IntToInt,
|
||||
FloatToInt,
|
||||
FloatToFloat,
|
||||
|
|
|
|||
|
|
@ -1205,7 +1205,6 @@ pub enum BoundRegionKind {
|
|||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
pub enum DynKind {
|
||||
Dyn,
|
||||
DynStar,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
|
|
|
|||
|
|
@ -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)?
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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}");
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
value: 1
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
43
|
||||
44
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
destructor called
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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:?}"));
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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());
|
||||
}
|
||||
|
|
@ -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`.
|
||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue