@@ -14,13 +14,14 @@ use crate::hir;
14
14
use crate :: hir:: def_id:: DefId ;
15
15
use crate :: lint;
16
16
use crate :: traits:: { self , Obligation , ObligationCause } ;
17
- use crate :: ty:: { self , Ty , TyCtxt , TypeFoldable , Predicate , ToPredicate } ;
17
+ use crate :: ty:: { self , Ty , TyCtxt , TypeFoldable , Predicate , ToPredicate , ParamTy } ;
18
18
use crate :: ty:: subst:: { Subst , InternalSubsts } ;
19
19
use std:: borrow:: Cow ;
20
20
use std:: iter:: { self } ;
21
21
use syntax:: ast:: { self } ;
22
22
use syntax:: symbol:: Symbol ;
23
23
use syntax_pos:: { Span , DUMMY_SP } ;
24
+ use syntax:: symbol:: sym;
24
25
25
26
#[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
26
27
pub enum ObjectSafetyViolation {
@@ -281,7 +282,40 @@ impl<'tcx> TyCtxt<'tcx> {
281
282
false
282
283
}
283
284
}
284
- )
285
+ )
286
+ }
287
+
288
+ fn generics_require_sized_param ( self , def_id : DefId , param_ty : ParamTy ) -> bool {
289
+ debug ! ( "generics_require_sized_param(def_id={:?}, param_ty={:?})" , def_id, param_ty) ;
290
+
291
+ let sized_def_id = match self . lang_items ( ) . sized_trait ( ) {
292
+ Some ( def_id) => def_id,
293
+ None => { return false ; /* No Sized trait, can't require it! */ }
294
+ } ;
295
+
296
+ // Search for a predicate like `Self : Sized` amongst the trait bounds.
297
+ let predicates = self . predicates_of ( def_id) ;
298
+ let predicates = predicates. instantiate_identity ( self ) . predicates ;
299
+ predicates
300
+ . iter ( )
301
+ . any ( |predicate| match predicate {
302
+ ty:: Predicate :: Trait ( ref trait_pred) => {
303
+ debug ! ( "generics_require_sized_param: trait_pred = {:?}" , trait_pred) ;
304
+
305
+ trait_pred. def_id ( ) == sized_def_id
306
+ && trait_pred. skip_binder ( ) . self_ty ( ) . is_param ( param_ty. index )
307
+ }
308
+ ty:: Predicate :: Projection ( ..) |
309
+ ty:: Predicate :: Subtype ( ..) |
310
+ ty:: Predicate :: RegionOutlives ( ..) |
311
+ ty:: Predicate :: WellFormed ( ..) |
312
+ ty:: Predicate :: ObjectSafe ( ..) |
313
+ ty:: Predicate :: ClosureKind ( ..) |
314
+ ty:: Predicate :: TypeOutlives ( ..) |
315
+ ty:: Predicate :: ConstEvaluatable ( ..) => {
316
+ false
317
+ }
318
+ } )
285
319
}
286
320
287
321
/// Returns `Some(_)` if this method makes the containing trait not object safe.
@@ -724,8 +758,43 @@ impl<'tcx> TyCtxt<'tcx> {
724
758
725
759
error
726
760
}
761
+
762
+ /// Searches for an impl that potentially overlaps `dyn Trait`
763
+ /// (where `Trait` is the trait with def-id `trait_def_id`). This
764
+ /// is used to distinguish between a trait being **fully**
765
+ /// object-safe and being **degenerate** object-safe -- the latter
766
+ /// means that we permit `dyn Foo` but we do not supply a `dyn
767
+ /// Foo: Foo` impl.
768
+ fn impl_potentially_overlapping_dyn_trait ( self , tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
769
+ debug ! ( "impl_potentially_overlapping_dyn_trait({:?})" , trait_def_id) ;
770
+ let mut found_match = false ;
771
+ tcx. for_each_impl ( trait_def_id, |impl_def_id| {
772
+ let impl_self_ty = tcx. type_of ( impl_def_id) ;
773
+ match impl_self_ty. kind {
774
+ ty:: Param ( param_ty) => {
775
+ if !self . generics_require_sized_param ( impl_def_id, param_ty) {
776
+ found_match = true ;
777
+ debug ! ( "Match found = {}; for param_ty {}" , found_match, param_ty. name) ;
778
+ tcx. sess . span_warn (
779
+ self . def_span ( impl_def_id) ,
780
+ "impl_potentially_overlapping_dyn_trait" ,
781
+ ) ;
782
+ }
783
+ }
784
+ _ => ( )
785
+ }
786
+ } ) ;
787
+
788
+ found_match
789
+ }
727
790
}
728
791
729
792
pub ( super ) fn is_object_safe_provider ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
730
- tcx. object_safety_violations ( trait_def_id) . is_empty ( )
793
+ tcx. object_safety_violations ( trait_def_id) . is_empty ( ) && {
794
+ if tcx. has_attr ( trait_def_id, sym:: rustc_dyn) {
795
+ true
796
+ } else {
797
+ !tcx. impl_potentially_overlapping_dyn_trait ( tcx, trait_def_id)
798
+ }
799
+ }
731
800
}
0 commit comments