@@ -326,12 +326,112 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
326326 if receiver_ty != self . mk_self_type ( ) {
327327 if !self . receiver_is_dispatchable ( method, receiver_ty) {
328328 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+ }
329371 }
330372 }
331373
332374 None
333375 }
334376
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+
335435 /// checks the method's receiver (the `self` argument) can be dispatched on when `Self` is a
336436 /// trait object. We require that `DispatchableFromDyn` be implemented for the receiver type
337437 /// in the following way:
0 commit comments