@@ -326,12 +326,112 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
326
326
if receiver_ty != self . mk_self_type ( ) {
327
327
if !self . receiver_is_dispatchable ( method, receiver_ty) {
328
328
return Some ( MethodViolationCode :: UndispatchableReceiver ) ;
329
+ } else {
330
+ // sanity check to make sure the receiver actually has the layout of a pointer
331
+
332
+ use ty:: layout:: Abi ;
333
+
334
+ let param_env = self . param_env ( method. def_id ) ;
335
+
336
+ let abi_of_ty = |ty : Ty < ' tcx > | -> & Abi {
337
+ match self . layout_of ( param_env. and ( ty) ) {
338
+ Ok ( layout) => & layout. abi ,
339
+ Err ( err) => bug ! (
340
+ "Error: {}\n while computing layout for type {:?}" , err, ty
341
+ )
342
+ }
343
+ } ;
344
+
345
+ // e.g. Rc<()>
346
+ let unit_receiver_ty = self . receiver_for_self_ty (
347
+ receiver_ty, self . mk_unit ( ) , method. def_id
348
+ ) ;
349
+
350
+ match abi_of_ty ( unit_receiver_ty) {
351
+ & Abi :: Scalar ( ..) => ( ) ,
352
+ abi => bug ! ( "Receiver when Self = () should have a Scalar ABI, found {:?}" , abi)
353
+ }
354
+
355
+ let trait_object_ty = self . object_ty_for_trait (
356
+ trait_def_id, self . mk_region ( ty:: ReStatic )
357
+ ) ;
358
+
359
+ // e.g. Rc<dyn Trait>
360
+ let trait_object_receiver = self . receiver_for_self_ty (
361
+ receiver_ty, trait_object_ty, method. def_id
362
+ ) ;
363
+
364
+ match abi_of_ty ( trait_object_receiver) {
365
+ & Abi :: ScalarPair ( ..) => ( ) ,
366
+ abi => bug ! (
367
+ "Receiver when Self = {} should have a ScalarPair ABI, found {:?}" ,
368
+ trait_object_ty, abi
369
+ )
370
+ }
329
371
}
330
372
}
331
373
332
374
None
333
375
}
334
376
377
+ /// performs a type substitution to produce the version of receiver_ty when `Self = self_ty`
378
+ /// e.g. for receiver_ty = `Rc<Self>` and self_ty = `Foo`, returns `Rc<Foo>`
379
+ fn receiver_for_self_ty (
380
+ self , receiver_ty : Ty < ' tcx > , self_ty : Ty < ' tcx > , method_def_id : DefId
381
+ ) -> Ty < ' tcx > {
382
+ let substs = Substs :: for_item ( self , method_def_id, |param, _| {
383
+ if param. index == 0 {
384
+ self_ty. into ( )
385
+ } else {
386
+ self . mk_param_from_def ( param)
387
+ }
388
+ } ) ;
389
+
390
+ receiver_ty. subst ( self , substs)
391
+ }
392
+
393
+ /// creates the object type for the current trait. For example,
394
+ /// if the current trait is `Deref`, then this will be
395
+ /// `dyn Deref<Target=Self::Target> + 'static`
396
+ fn object_ty_for_trait ( self , trait_def_id : DefId , lifetime : ty:: Region < ' tcx > ) -> Ty < ' tcx > {
397
+ debug ! ( "object_ty_for_trait: trait_def_id={:?}" , trait_def_id) ;
398
+
399
+ let trait_ref = ty:: TraitRef :: identity ( self , trait_def_id) ;
400
+
401
+ let trait_predicate = ty:: ExistentialPredicate :: Trait (
402
+ ty:: ExistentialTraitRef :: erase_self_ty ( self , trait_ref)
403
+ ) ;
404
+
405
+ let mut associated_types = traits:: supertraits ( self , ty:: Binder :: dummy ( trait_ref) )
406
+ . flat_map ( |trait_ref| self . associated_items ( trait_ref. def_id ( ) ) )
407
+ . filter ( |item| item. kind == ty:: AssociatedKind :: Type )
408
+ . collect :: < Vec < _ > > ( ) ;
409
+
410
+ // existential predicates need to be in a specific order
411
+ associated_types. sort_by_key ( |item| self . def_path_hash ( item. def_id ) ) ;
412
+
413
+ let projection_predicates = associated_types. into_iter ( ) . map ( |item| {
414
+ ty:: ExistentialPredicate :: Projection ( ty:: ExistentialProjection {
415
+ ty : self . mk_projection ( item. def_id , trait_ref. substs ) ,
416
+ item_def_id : item. def_id ,
417
+ substs : trait_ref. substs ,
418
+ } )
419
+ } ) ;
420
+
421
+ let existential_predicates = self . mk_existential_predicates (
422
+ iter:: once ( trait_predicate) . chain ( projection_predicates)
423
+ ) ;
424
+
425
+ let object_ty = self . mk_dynamic (
426
+ ty:: Binder :: dummy ( existential_predicates) ,
427
+ lifetime,
428
+ ) ;
429
+
430
+ debug ! ( "object_ty_for_trait: object_ty=`{}`" , object_ty) ;
431
+
432
+ object_ty
433
+ }
434
+
335
435
/// checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
336
436
/// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
337
437
/// in the following way:
0 commit comments