Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 549c105

Browse files
committed
dyn* through more typechecking and MIR
1 parent 7fccac3 commit 549c105

File tree

15 files changed

+168
-13
lines changed

15 files changed

+168
-13
lines changed

compiler/rustc_borrowck/src/type_check/mod.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ use rustc_middle::ty::cast::CastTy;
3030
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef, UserSubsts};
3131
use rustc_middle::ty::visit::TypeVisitable;
3232
use rustc_middle::ty::{
33-
self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, OpaqueHiddenType,
34-
OpaqueTypeKey, RegionVid, ToPredicate, Ty, TyCtxt, UserType, UserTypeAnnotationIndex,
33+
self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic,
34+
OpaqueHiddenType, OpaqueTypeKey, RegionVid, ToPredicate, TraitObjectRepresentation, Ty, TyCtxt,
35+
UserType, UserTypeAnnotationIndex,
3536
};
3637
use rustc_span::def_id::CRATE_DEF_ID;
3738
use rustc_span::{Span, DUMMY_SP};
@@ -2009,6 +2010,38 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
20092010
);
20102011
}
20112012

2013+
CastKind::DynStar => {
2014+
// get the constraints from the target type (`dyn* Clone`)
2015+
//
2016+
// apply them to prove that the source type `Foo` implements `Clone` etc
2017+
let (existential_predicates, region) = match ty.kind() {
2018+
Dynamic(predicates, region, TraitObjectRepresentation::Sized) => {
2019+
(predicates, region)
2020+
}
2021+
_ => panic!("Invalid dyn* cast_ty"),
2022+
};
2023+
2024+
let self_ty = op.ty(body, tcx);
2025+
2026+
self.prove_predicates(
2027+
existential_predicates
2028+
.iter()
2029+
.map(|predicate| predicate.with_self_ty(tcx, self_ty)),
2030+
location.to_locations(),
2031+
ConstraintCategory::Cast,
2032+
);
2033+
2034+
let outlives_predicate =
2035+
tcx.mk_predicate(Binder::dummy(ty::PredicateKind::TypeOutlives(
2036+
ty::OutlivesPredicate(self_ty, *region),
2037+
)));
2038+
self.prove_predicate(
2039+
outlives_predicate,
2040+
location.to_locations(),
2041+
ConstraintCategory::Cast,
2042+
);
2043+
}
2044+
20122045
CastKind::Pointer(PointerCast::MutToConstPointer) => {
20132046
let ty::RawPtr(ty::TypeAndMut {
20142047
ty: ty_from,

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc_index::vec::Idx;
1616
use rustc_middle::mir::{self, AssertKind, SwitchTargets};
1717
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
1818
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
19-
use rustc_middle::ty::{self, Instance, Ty, TypeVisitable};
19+
use rustc_middle::ty::{self, Instance, Ty, TypeVisitable, TraitObjectRepresentation};
2020
use rustc_span::source_map::Span;
2121
use rustc_span::{sym, Symbol};
2222
use rustc_symbol_mangling::typeid::typeid_for_fnabi;
@@ -367,6 +367,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
367367
bx.ret(llval);
368368
}
369369

370+
#[tracing::instrument(level = "debug", skip(self, helper, bx))]
370371
fn codegen_drop_terminator(
371372
&mut self,
372373
helper: TerminatorCodegenHelper<'tcx>,
@@ -397,20 +398,61 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
397398
let (drop_fn, fn_abi) = match ty.kind() {
398399
// FIXME(eddyb) perhaps move some of this logic into
399400
// `Instance::resolve_drop_in_place`?
400-
ty::Dynamic(..) => {
401+
ty::Dynamic(_, _, TraitObjectRepresentation::Unsized) => {
402+
// IN THIS ARM, WE HAVE:
403+
// ty = *mut (dyn Trait)
404+
// which is: exists<T> ( *mut T, Vtable<T: Trait> )
405+
// args[0] args[1]
406+
//
407+
// args = ( Data, Vtable )
408+
// |
409+
// v
410+
// /-------\
411+
// | ... |
412+
// \-------/
413+
//
401414
let virtual_drop = Instance {
402415
def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0),
403416
substs: drop_fn.substs,
404417
};
418+
debug!("ty = {:?}", ty);
419+
debug!("drop_fn = {:?}", drop_fn);
420+
debug!("args = {:?}", args);
405421
let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty());
406422
let vtable = args[1];
423+
// Truncate vtable off of args list
407424
args = &args[..1];
408425
(
409426
meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE)
410427
.get_fn(&mut bx, vtable, ty, &fn_abi),
411428
fn_abi,
412429
)
413430
}
431+
ty::Dynamic(_, _, TraitObjectRepresentation::Sized) => {
432+
// IN THIS ARM, WE HAVE:
433+
// ty = *mut (dyn* Trait)
434+
// which is: *mut exists<T: sizeof(T) == sizeof(usize)> (T, Vtable<T: Trait>)
435+
//
436+
// args = [ * ]
437+
// |
438+
// v
439+
// ( Data, Vtable )
440+
// |
441+
// v
442+
// /-------\
443+
// | ... |
444+
// \-------/
445+
//
446+
//
447+
// WE CAN CONVERT THIS INTO THE ABOVE LOGIC BY DOING
448+
//
449+
// data = &(*args[0]).0 // gives a pointer to Data above (really the same pointer)
450+
// vtable = (*args[0]).1 // loads the vtable out
451+
// (data, vtable) // an equivalent Rust `*mut dyn Trait`
452+
//
453+
// SO THEN WE CAN USE THE ABOVE CODE.
454+
todo!()
455+
}
414456
_ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())),
415457
};
416458
helper.do_call(

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
271271
bug!("unexpected non-pair operand");
272272
}
273273
}
274+
#[allow(unreachable_code, unused)] // FIXME: remove this
275+
mir::CastKind::DynStar => {
276+
let data = match operand.val {
277+
OperandValue::Ref(_, _, _) => todo!(),
278+
OperandValue::Immediate(_) => todo!(),
279+
OperandValue::Pair(_, _) => todo!(),
280+
};
281+
let vtable = todo!();
282+
OperandValue::Pair(data, vtable)
283+
}
274284
mir::CastKind::Pointer(
275285
PointerCast::MutToConstPointer | PointerCast::ArrayToPointer,
276286
)

compiler/rustc_const_eval/src/interpret/cast.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
108108
_ => span_bug!(self.cur_span(), "closure fn pointer on {:?}", src.layout.ty),
109109
}
110110
}
111+
112+
DynStar => {
113+
unimplemented!()
114+
}
111115
}
112116
Ok(())
113117
}

compiler/rustc_const_eval/src/transform/check_consts/check.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
546546
// Since no pointer can ever get exposed (rejected above), this is easy to support.
547547
}
548548

549+
Rvalue::Cast(CastKind::DynStar, _, _) => {
550+
unimplemented!()
551+
}
552+
549553
Rvalue::Cast(CastKind::Misc, _, _) => {}
550554

551555
Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {}

compiler/rustc_const_eval/src/transform/validate.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
569569
);
570570
}
571571
}
572+
CastKind::DynStar => {
573+
// FIXME: make sure nothing needs to be done here.
574+
}
572575
// Nothing to check here
573576
CastKind::PointerFromExposedAddress
574577
| CastKind::PointerExposeAddress

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1834,6 +1834,7 @@ impl<'tcx> Rvalue<'tcx> {
18341834
// While the model is undecided, we should be conservative. See
18351835
// <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html>
18361836
Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false,
1837+
Rvalue::Cast(CastKind::DynStar, _, _) => false,
18371838

18381839
Rvalue::Use(_)
18391840
| Rvalue::CopyForDeref(_)

compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,6 +1139,8 @@ pub enum CastKind {
11391139
/// All sorts of pointer-to-pointer casts. Note that reference-to-raw-ptr casts are
11401140
/// translated into `&raw mut/const *r`, i.e., they are not actually casts.
11411141
Pointer(PointerCast),
1142+
/// Cast into a dyn* object.
1143+
DynStar,
11421144
/// Remaining unclassified casts.
11431145
Misc,
11441146
}

compiler/rustc_middle/src/ty/cast.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use crate::ty::{self, Ty};
55

66
use rustc_macros::HashStable;
7+
use rustc_type_ir::TraitObjectRepresentation;
78

89
/// Types that are represented as ints.
910
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -33,6 +34,8 @@ pub enum CastTy<'tcx> {
3334
FnPtr,
3435
/// Raw pointers.
3536
Ptr(ty::TypeAndMut<'tcx>),
37+
/// Casting into a `dyn*` value.
38+
DynStar,
3639
}
3740

3841
/// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html)
@@ -50,6 +53,7 @@ pub enum CastKind {
5053
ArrayPtrCast,
5154
FnPtrPtrCast,
5255
FnPtrAddrCast,
56+
DynStarCast,
5357
}
5458

5559
impl<'tcx> CastTy<'tcx> {
@@ -67,6 +71,7 @@ impl<'tcx> CastTy<'tcx> {
6771
ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)),
6872
ty::RawPtr(mt) => Some(CastTy::Ptr(mt)),
6973
ty::FnPtr(..) => Some(CastTy::FnPtr),
74+
ty::Dynamic(_, _, TraitObjectRepresentation::Sized) => Some(CastTy::DynStar),
7075
_ => None,
7176
}
7277
}

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use rustc_target::abi::call::{
2121
};
2222
use rustc_target::abi::*;
2323
use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
24+
use rustc_type_ir::TraitObjectRepresentation;
2425

2526
use std::cmp::{self, Ordering};
2627
use std::fmt;
@@ -625,6 +626,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
625626
tcx.intern_layout(self.scalar_pair(data_ptr, metadata))
626627
}
627628

629+
ty::Dynamic(_, _, TraitObjectRepresentation::Sized) => {
630+
let mut pointer = scalar_unit(Pointer);
631+
pointer.valid_range_mut().start = 1;
632+
let mut vtable = scalar_unit(Pointer);
633+
vtable.valid_range_mut().start = 1;
634+
tcx.intern_layout(self.scalar_pair(pointer, vtable))
635+
}
636+
628637
// Arrays and slices.
629638
ty::Array(element, mut count) => {
630639
if count.has_projections() {
@@ -679,7 +688,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
679688

680689
// Odd unit types.
681690
ty::FnDef(..) => univariant(&[], &ReprOptions::default(), StructKind::AlwaysSized)?,
682-
ty::Dynamic(..) | ty::Foreign(..) => {
691+
ty::Dynamic(_, _, TraitObjectRepresentation::Unsized) | ty::Foreign(..) => {
683692
let mut unit = self.univariant_uninterned(
684693
ty,
685694
&[],
@@ -2435,7 +2444,9 @@ where
24352444
| ty::FnDef(..)
24362445
| ty::GeneratorWitness(..)
24372446
| ty::Foreign(..)
2438-
| ty::Dynamic(..) => bug!("TyAndLayout::field({:?}): not applicable", this),
2447+
| ty::Dynamic(_, _, TraitObjectRepresentation::Unsized) => {
2448+
bug!("TyAndLayout::field({:?}): not applicable", this)
2449+
}
24392450

24402451
// Potentially-fat pointers.
24412452
ty::Ref(_, pointee, _) | ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
@@ -2534,6 +2545,17 @@ where
25342545
}
25352546
}
25362547

2548+
// dyn*
2549+
ty::Dynamic(_, _, TraitObjectRepresentation::Sized) => {
2550+
TyMaybeWithLayout::TyAndLayout(
2551+
tcx.layout_of(
2552+
ty::ParamEnv::reveal_all()
2553+
.and(tcx.mk_tup([tcx.types.usize, tcx.types.usize].into_iter())),
2554+
)
2555+
.unwrap(),
2556+
)
2557+
}
2558+
25372559
ty::Projection(_)
25382560
| ty::Bound(..)
25392561
| ty::Placeholder(..)

compiler/rustc_middle/src/ty/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,12 @@ pub trait ToPredicate<'tcx> {
11131113
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx>;
11141114
}
11151115

1116+
impl<'tcx> ToPredicate<'tcx> for Predicate<'tcx> {
1117+
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
1118+
self
1119+
}
1120+
}
1121+
11161122
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
11171123
#[inline(always)]
11181124
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
216216
};
217217
let from_ty = CastTy::from_ty(ty);
218218
let cast_ty = CastTy::from_ty(expr.ty);
219+
debug!(
220+
"ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}",
221+
expr.ty,
222+
);
219223
let cast_kind = match (from_ty, cast_ty) {
220224
(Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => {
221225
CastKind::PointerExposeAddress
222226
}
223227
(Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => {
224228
CastKind::PointerFromExposedAddress
225229
}
230+
(_, Some(CastTy::DynStar)) => CastKind::DynStar,
226231
(_, _) => CastKind::Misc,
227232
};
228233
block.and(Rvalue::Cast(cast_kind, source, expr.ty))

compiler/rustc_typeck/src/check/cast.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,12 @@ impl<'a, 'tcx> CastCheck<'tcx> {
928928
(Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast),
929929

930930
(Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast),
931+
932+
// FIXME: this needs more conditions...
933+
(_, DynStar) => Ok(CastKind::DynStarCast),
934+
935+
// FIXME: do we want to allow dyn* upcasting or other casts?
936+
(DynStar, _) => Err(CastError::IllegalCast),
931937
}
932938
}
933939

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// run-pass
2+
// ignore-test
3+
#![feature(async_fn_in_traits)]
4+
5+
use std::fmt::Debug;
6+
7+
fn make_dyn_star() {
8+
let i = 42usize;
9+
let dyn_i: dyn* Debug = i as dyn* Debug;
10+
}
11+
12+
fn main() {
13+
make_dyn_star();
14+
}

src/test/ui/dyn-star/make-dyn-star.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
// check-pass
1+
// run-pass
22
#![feature(dyn_star)]
33

44
use std::fmt::Debug;
55

6-
pub fn dyn_star_parameter(_: dyn* Send) {
7-
}
8-
9-
fn make_dyn_star() {
10-
let i = 42usize;
6+
fn make_dyn_star(i: usize) {
117
let dyn_i: dyn* Debug = i as dyn* Debug;
128
}
139

14-
fn main() {}
10+
fn main() {
11+
make_dyn_star(42);
12+
}

0 commit comments

Comments
 (0)