@@ -38,7 +38,7 @@ use rustc_session::Session;
3838use rustc_span:: symbol:: sym;
3939use rustc_span:: Symbol ;
4040use rustc_span:: { DebuggerVisualizerFile , DebuggerVisualizerType } ;
41- use rustc_target:: abi:: { Align , VariantIdx } ;
41+ use rustc_target:: abi:: { Align , Size , VariantIdx } ;
4242
4343use std:: collections:: BTreeSet ;
4444use std:: convert:: TryFrom ;
@@ -150,7 +150,12 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
150150 ( & ty:: Array ( _, len) , & ty:: Slice ( _) ) => {
151151 cx. const_usize ( len. eval_usize ( cx. tcx ( ) , ty:: ParamEnv :: reveal_all ( ) ) )
152152 }
153- ( & ty:: Dynamic ( ref data_a, ..) , & ty:: Dynamic ( ref data_b, ..) ) => {
153+ (
154+ & ty:: Dynamic ( ref data_a, _, src_dyn_kind) ,
155+ & ty:: Dynamic ( ref data_b, _, target_dyn_kind) ,
156+ ) => {
157+ assert_eq ! ( src_dyn_kind, target_dyn_kind) ;
158+
154159 let old_info =
155160 old_info. expect ( "unsized_info: missing old info for trait upcasting coercion" ) ;
156161 if data_a. principal_def_id ( ) == data_b. principal_def_id ( ) {
@@ -166,11 +171,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
166171 if let Some ( entry_idx) = vptr_entry_idx {
167172 let ptr_ty = cx. type_i8p ( ) ;
168173 let ptr_align = cx. tcx ( ) . data_layout . pointer_align . abi ;
169- let vtable_ptr_ty = cx. scalar_pair_element_backend_type (
170- cx. layout_of ( cx. tcx ( ) . mk_mut_ptr ( target) ) ,
171- 1 ,
172- true ,
173- ) ;
174+ let vtable_ptr_ty = vtable_ptr_ty ( cx, target, target_dyn_kind) ;
174175 let llvtable = bx. pointercast ( old_info, bx. type_ptr_to ( ptr_ty) ) ;
175176 let gep = bx. inbounds_gep (
176177 ptr_ty,
@@ -186,18 +187,32 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
186187 old_info
187188 }
188189 }
189- ( _, & ty:: Dynamic ( ref data, ..) ) => {
190- let vtable_ptr_ty = cx. scalar_pair_element_backend_type (
191- cx. layout_of ( cx. tcx ( ) . mk_mut_ptr ( target) ) ,
192- 1 ,
193- true ,
194- ) ;
190+ ( _, & ty:: Dynamic ( ref data, _, target_dyn_kind) ) => {
191+ let vtable_ptr_ty = vtable_ptr_ty ( cx, target, target_dyn_kind) ;
195192 cx. const_ptrcast ( meth:: get_vtable ( cx, source, data. principal ( ) ) , vtable_ptr_ty)
196193 }
197194 _ => bug ! ( "unsized_info: invalid unsizing {:?} -> {:?}" , source, target) ,
198195 }
199196}
200197
198+ // Returns the vtable pointer type of a `dyn` or `dyn*` type
199+ fn vtable_ptr_ty < ' tcx , Cx : CodegenMethods < ' tcx > > (
200+ cx : & Cx ,
201+ target : Ty < ' tcx > ,
202+ kind : ty:: DynKind ,
203+ ) -> <Cx as BackendTypes >:: Type {
204+ cx. scalar_pair_element_backend_type (
205+ cx. layout_of ( match kind {
206+ // vtable is the second field of `*mut dyn Trait`
207+ ty:: Dyn => cx. tcx ( ) . mk_mut_ptr ( target) ,
208+ // vtable is the second field of `dyn* Trait`
209+ ty:: DynStar => target,
210+ } ) ,
211+ 1 ,
212+ true ,
213+ )
214+ }
215+
201216/// Coerces `src` to `dst_ty`. `src_ty` must be a pointer.
202217pub fn unsize_ptr < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
203218 bx : & mut Bx ,
@@ -247,6 +262,29 @@ pub fn unsize_ptr<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
247262 }
248263}
249264
265+ /// Coerces `src` to `dst_ty` which is guaranteed to be a `dyn*` type.
266+ pub fn cast_to_dyn_star < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
267+ bx : & mut Bx ,
268+ src : Bx :: Value ,
269+ src_ty_and_layout : TyAndLayout < ' tcx > ,
270+ dst_ty : Ty < ' tcx > ,
271+ old_info : Option < Bx :: Value > ,
272+ ) -> ( Bx :: Value , Bx :: Value ) {
273+ debug ! ( "cast_to_dyn_star: {:?} => {:?}" , src_ty_and_layout. ty, dst_ty) ;
274+ assert ! (
275+ matches!( dst_ty. kind( ) , ty:: Dynamic ( _, _, ty:: DynStar ) ) ,
276+ "destination type must be a dyn*"
277+ ) ;
278+ // FIXME(dyn-star): this is probably not the best way to check if this is
279+ // a pointer, and really we should ensure that the value is a suitable
280+ // pointer earlier in the compilation process.
281+ let src = match src_ty_and_layout. pointee_info_at ( bx. cx ( ) , Size :: ZERO ) {
282+ Some ( _) => bx. ptrtoint ( src, bx. cx ( ) . type_isize ( ) ) ,
283+ None => bx. bitcast ( src, bx. type_isize ( ) ) ,
284+ } ;
285+ ( src, unsized_info ( bx, src_ty_and_layout. ty , dst_ty, old_info) )
286+ }
287+
250288/// Coerces `src`, which is a reference to a value of type `src_ty`,
251289/// to a value of type `dst_ty`, and stores the result in `dst`.
252290pub fn coerce_unsized_into < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
0 commit comments