@@ -7,7 +7,8 @@ use rustc_index::{IndexVec, Idx};
77use rustc_middle:: mir;
88use rustc_middle:: ty:: CoroutineArgsExt ;
99use rustc_const_eval:: interpret:: {
10- self , InterpCx , InterpResult , MPlaceTy , OffsetMode , Projectable ,
10+ self , InterpCx , InterpResult , MemPlaceMeta , MPlaceTy , OffsetMode ,
11+ Projectable ,
1112} ;
1213use rustc_middle:: ty;
1314use rustc_middle:: ty:: { AdtKind , DynKind , TyCtxt , TypeVisitableExt } ;
@@ -244,6 +245,13 @@ pub fn trait_inst_id_str<'tcx>(
244245 }
245246}
246247
248+ pub fn vtable_name < ' tcx > (
249+ mir : & mut MirState < ' _ , ' tcx > ,
250+ trait_ref : ty:: PolyTraitRef < ' tcx > ,
251+ ) -> String {
252+ ext_def_id_str ( mir. tcx , trait_ref. def_id ( ) , "_vtbl" , trait_ref)
253+ }
254+
247255/// Get the mangled name of a monomorphic function. As a side effect, this marks the function as
248256/// "used", so its body will be emitted too.
249257pub fn get_fn_def_name < ' tcx > (
@@ -1460,6 +1468,24 @@ fn make_allocation_body<'tcx>(
14601468) -> serde_json:: Value {
14611469 let tcx = mir. tcx ;
14621470
1471+ fn do_default < ' tcx > (
1472+ mir : & mut MirState < ' _ , ' tcx > ,
1473+ icx : & mut interpret:: InterpCx < ' tcx , RenderConstMachine < ' tcx > > ,
1474+ rty : ty:: Ty < ' tcx > ,
1475+ d : & MPlaceTy < ' tcx > ,
1476+ ) -> serde_json:: Value {
1477+ let rlayout = mir. tcx . layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( rty) ) . unwrap ( ) ;
1478+ let mpty: MPlaceTy = d. offset_with_meta ( Size :: ZERO , OffsetMode :: Inbounds , d. meta ( ) , rlayout, icx) . unwrap ( ) ;
1479+ let rendered = try_render_opty ( mir, icx, & mpty. into ( ) ) ;
1480+
1481+ json ! ( {
1482+ "kind" : "constant" ,
1483+ "mutable" : false ,
1484+ "ty" : rty. to_json( mir) ,
1485+ "rendered" : rendered,
1486+ } )
1487+ }
1488+
14631489 if !is_mut {
14641490 /// Common logic for emitting `"kind": "strbody"` constants, shared by the `str` and `CStr`
14651491 /// cases.
@@ -1490,10 +1516,15 @@ fn make_allocation_body<'tcx>(
14901516 }
14911517
14921518 match * rty. kind ( ) {
1493- // Special cases for &str, &CStr, and &[T]
1519+ // Special cases for references to unsized types. Currently, the
1520+ // following are supported:
1521+ //
1522+ // * String slices (&str and &CStr)
1523+ // * Array slices (&[T])
1524+ // * Trait objects (&dyn Trait)
14941525 //
1495- // These and the ones in try_render_ref_opty below should be
1496- // kept in sync.
1526+ // These special cases and the ones in try_render_ref_opty below
1527+ // should be kept in sync.
14971528 ty:: TyKind :: Str => {
14981529 let len = d. len ( icx) . unwrap ( ) ;
14991530 return do_strbody ( mir, icx, d, len) ;
@@ -1527,21 +1558,16 @@ fn make_allocation_body<'tcx>(
15271558 "rendered" : rendered,
15281559 } ) ;
15291560 } ,
1561+ ty:: TyKind :: Dynamic ( ref preds, _, _) => {
1562+ let unpacked_d = unpack_dyn_place ( icx, d, preds) . unwrap ( ) ;
1563+ return do_default ( mir, icx, unpacked_d. layout . ty , & unpacked_d) ;
1564+ } ,
15301565 _ => ( )
15311566 }
15321567 }
15331568
15341569 // Default case
1535- let rlayout = tcx. layout_of ( ty:: TypingEnv :: fully_monomorphized ( ) . as_query_input ( rty) ) . unwrap ( ) ;
1536- let mpty: MPlaceTy = d. offset_with_meta ( Size :: ZERO , OffsetMode :: Inbounds , d. meta ( ) , rlayout, icx) . unwrap ( ) ;
1537- let rendered = try_render_opty ( mir, icx, & mpty. into ( ) ) ;
1538-
1539- return json ! ( {
1540- "kind" : "constant" ,
1541- "mutable" : false ,
1542- "ty" : rty. to_json( mir) ,
1543- "rendered" : rendered,
1544- } ) ;
1570+ return do_default ( mir, icx, rty, d) ;
15451571}
15461572
15471573fn try_render_ref_opty < ' tcx > (
@@ -1601,24 +1627,60 @@ fn try_render_ref_opty<'tcx>(
16011627 assert ! ( d_offset == Size :: ZERO , "cannot handle nonzero reference offsets" ) ;
16021628
16031629 if !is_mut {
1604- // Special cases for &str, &CStr, and &[T]
1605- //
1606- // These and the ones in make_allocation_body above should be kept in sync.
1607- let do_slice_special_case = match * rty. kind ( ) {
1608- ty:: TyKind :: Str | ty:: TyKind :: Slice ( _) => true ,
1609- ty:: TyKind :: Adt ( adt_def, _) if tcx. is_lang_item ( adt_def. did ( ) , LangItem :: CStr ) => true ,
1610- _ => false ,
1611- } ;
1612- if do_slice_special_case {
1630+ fn do_slice < ' tcx > (
1631+ icx : & mut interpret:: InterpCx < ' tcx , RenderConstMachine < ' tcx > > ,
1632+ d : & MPlaceTy < ' tcx > ,
1633+ def_id_json : serde_json:: Value ,
1634+ ) -> serde_json:: Value {
16131635 // `<MPlaceTy as Projectable>::len` asserts that the input must have `Slice` or
16141636 // `Str` type. However, the implementation it uses works fine on `CStr` too, so we
16151637 // copy-paste the code here.
16161638 let len = d. meta ( ) . unwrap_meta ( ) . to_target_usize ( icx) . unwrap ( ) ;
1617- return Some ( json ! ( {
1639+ json ! ( {
16181640 "kind" : "slice" ,
16191641 "def_id" : def_id_json,
16201642 "len" : len
1621- } ) )
1643+ } )
1644+ }
1645+
1646+ // Special cases for references to unsized types. Currently, the
1647+ // following are supported:
1648+ //
1649+ // * String slices (&str and &CStr)
1650+ // * Array slices (&[T])
1651+ // * Trait objects (&dyn Trait)
1652+ //
1653+ // These special cases and the ones in make_allocation_body above should be kept in sync.
1654+ match * rty. kind ( ) {
1655+ ty:: TyKind :: Str | ty:: TyKind :: Slice ( _) =>
1656+ return Some ( do_slice ( icx, & d, def_id_json) ) ,
1657+ ty:: TyKind :: Adt ( adt_def, _) if tcx. is_lang_item ( adt_def. did ( ) , LangItem :: CStr ) =>
1658+ return Some ( do_slice ( icx, & d, def_id_json) ) ,
1659+ ty:: TyKind :: Dynamic ( ref preds, _, _) => {
1660+ let self_ty = unpack_dyn_ty ( icx, & d, preds) . unwrap ( ) ;
1661+ let vtable_desc = preds. principal ( ) . map ( |pred| pred. with_self_ty ( tcx, self_ty) ) ;
1662+ match vtable_desc {
1663+ Some ( vtable_desc) => {
1664+ mir. used . vtables . insert ( vtable_desc) ;
1665+ let ti = TraitInst :: from_dynamic_predicates ( tcx, preds) ;
1666+ return Some ( json ! ( {
1667+ "kind" : "trait_object" ,
1668+ "def_id" : def_id_json,
1669+ "trait_id" : trait_inst_id_str( tcx, & ti) ,
1670+ "vtable" : vtable_name( mir, vtable_desc) ,
1671+ } ) )
1672+ } ,
1673+ None =>
1674+ // If there is no principal trait bound, then all of
1675+ // the trait bounds are auto traits. We do not
1676+ // currently support computing vtables for these sorts
1677+ // of trait objects (see #239).
1678+ return Some ( json ! ( {
1679+ "kind" : "unsupported" ,
1680+ } ) )
1681+ }
1682+ } ,
1683+ _ => ( ) ,
16221684 }
16231685 }
16241686
@@ -1852,3 +1914,42 @@ pub fn eval_mir_constant<'tcx>(
18521914 . eval ( tcx, ty:: TypingEnv :: fully_monomorphized ( ) , constant. span )
18531915 . unwrap ( )
18541916}
1917+
1918+ // Turn a place with a `dyn Trait` type into the actual dynamic type.
1919+ //
1920+ // This is based on the internals of
1921+ // `rustc_const_eval::interpret::InterpCx::unpack_dyn_trait`.
1922+ fn unpack_dyn_ty < ' tcx > (
1923+ icx : & InterpCx < ' tcx , RenderConstMachine < ' tcx > > ,
1924+ mplace : & MPlaceTy < ' tcx > ,
1925+ expected_trait : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
1926+ ) -> InterpResult < ' tcx , ty:: Ty < ' tcx > > {
1927+ assert ! (
1928+ matches!( mplace. layout. ty. kind( ) , ty:: Dynamic ( _, _, ty:: Dyn ) ) ,
1929+ "`unpack_dyn_ty` only makes sense on `dyn*` types"
1930+ ) ;
1931+ let vtable = mplace. meta ( ) . unwrap_meta ( ) . to_pointer ( icx) ?;
1932+ icx. get_ptr_vtable_ty ( vtable, Some ( expected_trait) )
1933+ }
1934+
1935+ // Turn a place with a `dyn Trait` type into a place with the actual dynamic
1936+ // type.
1937+ //
1938+ // This is based on `rustc_const_eval::interpret::InterpCx::unpack_dyn_trait`.
1939+ fn unpack_dyn_place < ' tcx > (
1940+ icx : & InterpCx < ' tcx , RenderConstMachine < ' tcx > > ,
1941+ mplace : & MPlaceTy < ' tcx > ,
1942+ expected_trait : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
1943+ ) -> InterpResult < ' tcx , MPlaceTy < ' tcx > > {
1944+ let ty = unpack_dyn_ty ( icx, mplace, expected_trait) ?;
1945+ // This is a kind of transmute, from a place with unsized type and metadata to
1946+ // a place with sized type and no metadata.
1947+ let layout = icx. layout_of ( ty) ?;
1948+ mplace. offset_with_meta (
1949+ Size :: ZERO ,
1950+ OffsetMode :: Wrapping ,
1951+ MemPlaceMeta :: None ,
1952+ layout,
1953+ icx,
1954+ )
1955+ }
0 commit comments