dyn* through more typechecking and MIR
This commit is contained in:
parent
7fccac3ea0
commit
549c105bb3
15 changed files with 168 additions and 13 deletions
|
@ -30,8 +30,9 @@ use rustc_middle::ty::cast::CastTy;
|
||||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
|
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
|
||||||
use rustc_middle::ty::visit::TypeVisitable;
|
use rustc_middle::ty::visit::TypeVisitable;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueHiddenType,
|
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
|
||||||
OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
|
OpaqueHiddenType, OpaqueTypeKey, RegionVid, ToPredicate, TraitObjectRepresentation, Ty, TyCtxt,
|
||||||
|
UserType, UserTypeAnnotationIndex,
|
||||||
};
|
};
|
||||||
use rustc_span::def_id::CRATE_DEF_ID;
|
use rustc_span::def_id::CRATE_DEF_ID;
|
||||||
use rustc_span::{Span, DUMMY_SP};
|
use rustc_span::{Span, DUMMY_SP};
|
||||||
|
@ -2009,6 +2010,38 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CastKind::DynStar => {
|
||||||
|
// 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, TraitObjectRepresentation::Sized) => {
|
||||||
|
(predicates, region)
|
||||||
|
}
|
||||||
|
_ => panic!("Invalid dyn* cast_ty"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let self_ty = op.ty(body, tcx);
|
||||||
|
|
||||||
|
self.prove_predicates(
|
||||||
|
existential_predicates
|
||||||
|
.iter()
|
||||||
|
.map(|predicate| predicate.with_self_ty(tcx, self_ty)),
|
||||||
|
location.to_locations(),
|
||||||
|
ConstraintCategory::Cast,
|
||||||
|
);
|
||||||
|
|
||||||
|
let outlives_predicate =
|
||||||
|
tcx.mk_predicate(Binder::dummy(ty::PredicateKind::TypeOutlives(
|
||||||
|
ty::OutlivesPredicate(self_ty, *region),
|
||||||
|
)));
|
||||||
|
self.prove_predicate(
|
||||||
|
outlives_predicate,
|
||||||
|
location.to_locations(),
|
||||||
|
ConstraintCategory::Cast,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
CastKind::Pointer(PointerCast::MutToConstPointer) => {
|
CastKind::Pointer(PointerCast::MutToConstPointer) => {
|
||||||
let ty::RawPtr(ty::TypeAndMut {
|
let ty::RawPtr(ty::TypeAndMut {
|
||||||
ty: ty_from,
|
ty: ty_from,
|
||||||
|
|
|
@ -16,7 +16,7 @@ use rustc_index::vec::Idx;
|
||||||
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
|
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
|
||||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
|
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
|
||||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||||
use rustc_middle::ty::{self, Instance, Ty, TypeVisitable};
|
use rustc_middle::ty::{self, Instance, Ty, TypeVisitable, TraitObjectRepresentation};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
use rustc_span::{sym, Symbol};
|
use rustc_span::{sym, Symbol};
|
||||||
use rustc_symbol_mangling::typeid::typeid_for_fnabi;
|
use rustc_symbol_mangling::typeid::typeid_for_fnabi;
|
||||||
|
@ -367,6 +367,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
bx.ret(llval);
|
bx.ret(llval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument(level = "debug", skip(self, helper, bx))]
|
||||||
fn codegen_drop_terminator(
|
fn codegen_drop_terminator(
|
||||||
&mut self,
|
&mut self,
|
||||||
helper: TerminatorCodegenHelper<'tcx>,
|
helper: TerminatorCodegenHelper<'tcx>,
|
||||||
|
@ -397,13 +398,29 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
let (drop_fn, fn_abi) = match ty.kind() {
|
let (drop_fn, fn_abi) = match ty.kind() {
|
||||||
// FIXME(eddyb) perhaps move some of this logic into
|
// FIXME(eddyb) perhaps move some of this logic into
|
||||||
// `Instance::resolve_drop_in_place`?
|
// `Instance::resolve_drop_in_place`?
|
||||||
ty::Dynamic(..) => {
|
ty::Dynamic(_, _, TraitObjectRepresentation::Unsized) => {
|
||||||
|
// IN THIS ARM, WE HAVE:
|
||||||
|
// ty = *mut (dyn Trait)
|
||||||
|
// which is: exists<T> ( *mut T, Vtable<T: Trait> )
|
||||||
|
// args[0] args[1]
|
||||||
|
//
|
||||||
|
// args = ( Data, Vtable )
|
||||||
|
// |
|
||||||
|
// v
|
||||||
|
// /-------\
|
||||||
|
// | ... |
|
||||||
|
// \-------/
|
||||||
|
//
|
||||||
let virtual_drop = Instance {
|
let virtual_drop = Instance {
|
||||||
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
|
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
|
||||||
substs: drop_fn.substs,
|
substs: drop_fn.substs,
|
||||||
};
|
};
|
||||||
|
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 fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
|
||||||
let vtable = args[1];
|
let vtable = args[1];
|
||||||
|
// Truncate vtable off of args list
|
||||||
args = &args[..1];
|
args = &args[..1];
|
||||||
(
|
(
|
||||||
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
|
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
|
||||||
|
@ -411,6 +428,31 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
fn_abi,
|
fn_abi,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
ty::Dynamic(_, _, TraitObjectRepresentation::Sized) => {
|
||||||
|
// 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.
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
_ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
|
_ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
|
||||||
};
|
};
|
||||||
helper.do_call(
|
helper.do_call(
|
||||||
|
|
|
@ -271,6 +271,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
bug!("unexpected non-pair operand");
|
bug!("unexpected non-pair operand");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[allow(unreachable_code, unused)] // FIXME: remove this
|
||||||
|
mir::CastKind::DynStar => {
|
||||||
|
let data = match operand.val {
|
||||||
|
OperandValue::Ref(_, _, _) => todo!(),
|
||||||
|
OperandValue::Immediate(_) => todo!(),
|
||||||
|
OperandValue::Pair(_, _) => todo!(),
|
||||||
|
};
|
||||||
|
let vtable = todo!();
|
||||||
|
OperandValue::Pair(data, vtable)
|
||||||
|
}
|
||||||
mir::CastKind::Pointer(
|
mir::CastKind::Pointer(
|
||||||
PointerCast::MutToConstPointer | PointerCast::ArrayToPointer,
|
PointerCast::MutToConstPointer | PointerCast::ArrayToPointer,
|
||||||
)
|
)
|
||||||
|
|
|
@ -108,6 +108,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||||
_ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty),
|
_ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DynStar => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -546,6 +546,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||||
// Since no pointer can ever get exposed (rejected above), this is easy to support.
|
// Since no pointer can ever get exposed (rejected above), this is easy to support.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rvalue::Cast(CastKind::DynStar, _, _) => {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
Rvalue::Cast(CastKind::Misc, _, _) => {}
|
Rvalue::Cast(CastKind::Misc, _, _) => {}
|
||||||
|
|
||||||
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
|
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}
|
||||||
|
|
|
@ -569,6 +569,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CastKind::DynStar => {
|
||||||
|
// FIXME: make sure nothing needs to be done here.
|
||||||
|
}
|
||||||
// Nothing to check here
|
// Nothing to check here
|
||||||
CastKind::PointerFromExposedAddress
|
CastKind::PointerFromExposedAddress
|
||||||
| CastKind::PointerExposeAddress
|
| CastKind::PointerExposeAddress
|
||||||
|
|
|
@ -1834,6 +1834,7 @@ impl<'tcx> Rvalue<'tcx> {
|
||||||
// While the model is undecided, we should be conservative. See
|
// While the model is undecided, we should be conservative. See
|
||||||
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
|
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
|
||||||
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false,
|
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false,
|
||||||
|
Rvalue::Cast(CastKind::DynStar, _, _) => false,
|
||||||
|
|
||||||
Rvalue::Use(_)
|
Rvalue::Use(_)
|
||||||
| Rvalue::CopyForDeref(_)
|
| Rvalue::CopyForDeref(_)
|
||||||
|
|
|
@ -1139,6 +1139,8 @@ pub enum CastKind {
|
||||||
/// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are
|
/// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are
|
||||||
/// translated into `&raw mut/const *r`, i.e., they are not actually casts.
|
/// translated into `&raw mut/const *r`, i.e., they are not actually casts.
|
||||||
Pointer(PointerCast),
|
Pointer(PointerCast),
|
||||||
|
/// Cast into a dyn* object.
|
||||||
|
DynStar,
|
||||||
/// Remaining unclassified casts.
|
/// Remaining unclassified casts.
|
||||||
Misc,
|
Misc,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
use crate::ty::{self, Ty};
|
use crate::ty::{self, Ty};
|
||||||
|
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
|
use rustc_type_ir::TraitObjectRepresentation;
|
||||||
|
|
||||||
/// Types that are represented as ints.
|
/// Types that are represented as ints.
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -33,6 +34,8 @@ pub enum CastTy<'tcx> {
|
||||||
FnPtr,
|
FnPtr,
|
||||||
/// Raw pointers.
|
/// Raw pointers.
|
||||||
Ptr(ty::TypeAndMut<'tcx>),
|
Ptr(ty::TypeAndMut<'tcx>),
|
||||||
|
/// Casting into a `dyn*` value.
|
||||||
|
DynStar,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html)
|
/// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html)
|
||||||
|
@ -50,6 +53,7 @@ pub enum CastKind {
|
||||||
ArrayPtrCast,
|
ArrayPtrCast,
|
||||||
FnPtrPtrCast,
|
FnPtrPtrCast,
|
||||||
FnPtrAddrCast,
|
FnPtrAddrCast,
|
||||||
|
DynStarCast,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> CastTy<'tcx> {
|
impl<'tcx> CastTy<'tcx> {
|
||||||
|
@ -67,6 +71,7 @@ impl<'tcx> CastTy<'tcx> {
|
||||||
ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)),
|
ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)),
|
||||||
ty::RawPtr(mt) => Some(CastTy::Ptr(mt)),
|
ty::RawPtr(mt) => Some(CastTy::Ptr(mt)),
|
||||||
ty::FnPtr(..) => Some(CastTy::FnPtr),
|
ty::FnPtr(..) => Some(CastTy::FnPtr),
|
||||||
|
ty::Dynamic(_, _, TraitObjectRepresentation::Sized) => Some(CastTy::DynStar),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ use rustc_target::abi::call::{
|
||||||
};
|
};
|
||||||
use rustc_target::abi::*;
|
use rustc_target::abi::*;
|
||||||
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
|
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
|
||||||
|
use rustc_type_ir::TraitObjectRepresentation;
|
||||||
|
|
||||||
use std::cmp::{self, Ordering};
|
use std::cmp::{self, Ordering};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -625,6 +626,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
tcx.intern_layout(self.scalar_pair(data_ptr, metadata))
|
tcx.intern_layout(self.scalar_pair(data_ptr, metadata))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ty::Dynamic(_, _, TraitObjectRepresentation::Sized) => {
|
||||||
|
let mut pointer = scalar_unit(Pointer);
|
||||||
|
pointer.valid_range_mut().start = 1;
|
||||||
|
let mut vtable = scalar_unit(Pointer);
|
||||||
|
vtable.valid_range_mut().start = 1;
|
||||||
|
tcx.intern_layout(self.scalar_pair(pointer, vtable))
|
||||||
|
}
|
||||||
|
|
||||||
// Arrays and slices.
|
// Arrays and slices.
|
||||||
ty::Array(element, mut count) => {
|
ty::Array(element, mut count) => {
|
||||||
if count.has_projections() {
|
if count.has_projections() {
|
||||||
|
@ -679,7 +688,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||||
|
|
||||||
// Odd unit types.
|
// Odd unit types.
|
||||||
ty::FnDef(..) => univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?,
|
ty::FnDef(..) => univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?,
|
||||||
ty::Dynamic(..) | ty::Foreign(..) => {
|
ty::Dynamic(_, _, TraitObjectRepresentation::Unsized) | ty::Foreign(..) => {
|
||||||
let mut unit = self.univariant_uninterned(
|
let mut unit = self.univariant_uninterned(
|
||||||
ty,
|
ty,
|
||||||
&[],
|
&[],
|
||||||
|
@ -2435,7 +2444,9 @@ where
|
||||||
| ty::FnDef(..)
|
| ty::FnDef(..)
|
||||||
| ty::GeneratorWitness(..)
|
| ty::GeneratorWitness(..)
|
||||||
| ty::Foreign(..)
|
| ty::Foreign(..)
|
||||||
| ty::Dynamic(..) => bug!("TyAndLayout::field({:?}): not applicable", this),
|
| ty::Dynamic(_, _, TraitObjectRepresentation::Unsized) => {
|
||||||
|
bug!("TyAndLayout::field({:?}): not applicable", this)
|
||||||
|
}
|
||||||
|
|
||||||
// Potentially-fat pointers.
|
// Potentially-fat pointers.
|
||||||
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
|
||||||
|
@ -2534,6 +2545,17 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dyn*
|
||||||
|
ty::Dynamic(_, _, TraitObjectRepresentation::Sized) => {
|
||||||
|
TyMaybeWithLayout::TyAndLayout(
|
||||||
|
tcx.layout_of(
|
||||||
|
ty::ParamEnv::reveal_all()
|
||||||
|
.and(tcx.mk_tup([tcx.types.usize, tcx.types.usize].into_iter())),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
ty::Projection(_)
|
ty::Projection(_)
|
||||||
| ty::Bound(..)
|
| ty::Bound(..)
|
||||||
| ty::Placeholder(..)
|
| ty::Placeholder(..)
|
||||||
|
|
|
@ -1113,6 +1113,12 @@ pub trait ToPredicate<'tcx> {
|
||||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>;
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ToPredicate<'tcx> for Predicate<'tcx> {
|
||||||
|
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
|
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||||
|
|
|
@ -216,6 +216,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
};
|
};
|
||||||
let from_ty = CastTy::from_ty(ty);
|
let from_ty = CastTy::from_ty(ty);
|
||||||
let cast_ty = CastTy::from_ty(expr.ty);
|
let cast_ty = CastTy::from_ty(expr.ty);
|
||||||
|
debug!(
|
||||||
|
"ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}",
|
||||||
|
expr.ty,
|
||||||
|
);
|
||||||
let cast_kind = match (from_ty, cast_ty) {
|
let cast_kind = match (from_ty, cast_ty) {
|
||||||
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
|
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
|
||||||
CastKind::PointerExposeAddress
|
CastKind::PointerExposeAddress
|
||||||
|
@ -223,6 +227,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
|
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
|
||||||
CastKind::PointerFromExposedAddress
|
CastKind::PointerFromExposedAddress
|
||||||
}
|
}
|
||||||
|
(_, Some(CastTy::DynStar)) => CastKind::DynStar,
|
||||||
(_, _) => CastKind::Misc,
|
(_, _) => CastKind::Misc,
|
||||||
};
|
};
|
||||||
block.and(Rvalue::Cast(cast_kind, source, expr.ty))
|
block.and(Rvalue::Cast(cast_kind, source, expr.ty))
|
||||||
|
|
|
@ -928,6 +928,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
|
||||||
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
|
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
|
||||||
|
|
||||||
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
|
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
|
||||||
|
|
||||||
|
// FIXME: this needs more conditions...
|
||||||
|
(_, DynStar) => Ok(CastKind::DynStarCast),
|
||||||
|
|
||||||
|
// FIXME: do we want to allow dyn* upcasting or other casts?
|
||||||
|
(DynStar, _) => Err(CastError::IllegalCast),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/test/ui/async-await/dyn-star-trait-const.rs
Normal file
14
src/test/ui/async-await/dyn-star-trait-const.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// run-pass
|
||||||
|
// ignore-test
|
||||||
|
#![feature(async_fn_in_traits)]
|
||||||
|
|
||||||
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
fn make_dyn_star() {
|
||||||
|
let i = 42usize;
|
||||||
|
let dyn_i: dyn* Debug = i as dyn* Debug;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
make_dyn_star();
|
||||||
|
}
|
|
@ -1,14 +1,12 @@
|
||||||
// check-pass
|
// run-pass
|
||||||
#![feature(dyn_star)]
|
#![feature(dyn_star)]
|
||||||
|
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub fn dyn_star_parameter(_: dyn* Send) {
|
fn make_dyn_star(i: usize) {
|
||||||
}
|
|
||||||
|
|
||||||
fn make_dyn_star() {
|
|
||||||
let i = 42usize;
|
|
||||||
let dyn_i: dyn* Debug = i as dyn* Debug;
|
let dyn_i: dyn* Debug = i as dyn* Debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {
|
||||||
|
make_dyn_star(42);
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue