@@ -12,11 +12,11 @@ use super::elaborate_predicates;
12
12
13
13
use crate :: traits:: { self , Obligation , ObligationCause } ;
14
14
use crate :: ty:: subst:: { InternalSubsts , Subst } ;
15
- use crate :: ty:: { self , Predicate , ToPredicate , Ty , TyCtxt , TypeFoldable } ;
15
+ use crate :: ty:: { self , ParamTy , Predicate , ToPredicate , Ty , TyCtxt , TypeFoldable } ;
16
16
use rustc_hir as hir;
17
17
use rustc_hir:: def_id:: DefId ;
18
18
use rustc_session:: lint:: builtin:: WHERE_CLAUSES_OBJECT_SAFETY ;
19
- use rustc_span:: symbol:: Symbol ;
19
+ use rustc_span:: symbol:: { sym , Symbol } ;
20
20
use rustc_span:: { Span , DUMMY_SP } ;
21
21
use syntax:: ast;
22
22
@@ -269,6 +269,66 @@ fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_o
269
269
} )
270
270
}
271
271
272
+ fn generics_require_sized_param ( tcx : TyCtxt < ' _ > , def_id : DefId , param_ty : ParamTy ) -> bool {
273
+ debug ! ( "generics_require_sized_param(def_id={:?}, param_ty={:?})" , def_id, param_ty) ;
274
+
275
+ let sized_def_id = match tcx. lang_items ( ) . sized_trait ( ) {
276
+ Some ( def_id) => def_id,
277
+ None => {
278
+ return false ; /* No Sized trait, can't require it! */
279
+ }
280
+ } ;
281
+
282
+ // Search for a predicate like `Self : Sized` amongst the trait bounds.
283
+ let predicates = tcx. predicates_of ( def_id) ;
284
+ let predicates = predicates. instantiate_identity ( tcx) . predicates ;
285
+ predicates. iter ( ) . any ( |predicate| match predicate {
286
+ ty:: Predicate :: Trait ( ref trait_pred) => {
287
+ debug ! ( "generics_require_sized_param: trait_pred = {:?}" , trait_pred) ;
288
+
289
+ trait_pred. def_id ( ) == sized_def_id
290
+ && trait_pred. skip_binder ( ) . self_ty ( ) . is_param ( param_ty. index )
291
+ }
292
+ ty:: Predicate :: Projection ( ..)
293
+ | ty:: Predicate :: Subtype ( ..)
294
+ | ty:: Predicate :: RegionOutlives ( ..)
295
+ | ty:: Predicate :: WellFormed ( ..)
296
+ | ty:: Predicate :: ObjectSafe ( ..)
297
+ | ty:: Predicate :: ClosureKind ( ..)
298
+ | ty:: Predicate :: TypeOutlives ( ..)
299
+ | ty:: Predicate :: ConstEvaluatable ( ..) => false ,
300
+ } )
301
+ }
302
+
303
+ /// Searches for an impl that potentially overlaps `dyn Trait`
304
+ /// (where `Trait` is the trait with def-id `trait_def_id`). This
305
+ /// is used to distinguish between a trait being **fully**
306
+ /// object-safe and being **degenerate** object-safe -- the latter
307
+ /// means that we permit `dyn Foo` but we do not supply a `dyn
308
+ /// Foo: Foo` impl.
309
+ fn impl_potentially_overlapping_dyn_trait ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
310
+ debug ! ( "impl_potentially_overlapping_dyn_trait({:?})" , trait_def_id) ;
311
+ let mut found_match = false ;
312
+ tcx. for_each_impl ( trait_def_id, |impl_def_id| {
313
+ let impl_self_ty = tcx. type_of ( impl_def_id) ;
314
+ match impl_self_ty. kind {
315
+ ty:: Param ( param_ty) => {
316
+ if !generics_require_sized_param ( tcx, impl_def_id, param_ty) {
317
+ found_match = true ;
318
+ debug ! ( "Match found = {}; for param_ty {}" , found_match, param_ty. name) ;
319
+ tcx. sess . span_warn (
320
+ tcx. def_span ( impl_def_id) ,
321
+ "impl_potentially_overlapping_dyn_trait" ,
322
+ ) ;
323
+ }
324
+ }
325
+ _ => ( ) ,
326
+ }
327
+ } ) ;
328
+
329
+ found_match
330
+ }
331
+
272
332
fn trait_has_sized_self ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
273
333
generics_require_sized_self ( tcx, trait_def_id)
274
334
}
@@ -417,7 +477,7 @@ fn virtual_call_violation_for_method<'tcx>(
417
477
tcx. def_span ( method. def_id ) ,
418
478
& format ! (
419
479
"receiver when `Self = {}` should have a ScalarPair ABI; \
420
- found {:?}",
480
+ found {:?}",
421
481
trait_object_ty, abi
422
482
) ,
423
483
) ;
@@ -716,13 +776,37 @@ fn contains_illegal_self_type_reference<'tcx>(
716
776
}
717
777
}
718
778
719
- _ => true , // walk contained types, if any
779
+ _ => true ,
720
780
}
721
781
} ) ;
722
782
723
783
error
724
784
}
725
785
726
786
pub ( super ) fn is_object_safe_provider ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
727
- object_safety_violations ( tcx, trait_def_id) . is_empty ( )
787
+ object_safety_violations ( tcx, trait_def_id) . is_empty ( ) && {
788
+ if tcx. has_attr ( trait_def_id, sym:: rustc_dyn) {
789
+ true
790
+ } else {
791
+ // Issue #57893. A trait cannot be considered dyn-safe if:
792
+ //
793
+ // (a) it has associated items that are not functions and
794
+ // (b) it has a potentially dyn-overlapping impl.
795
+ //
796
+ // Why don't functions matter? Because we never resolve
797
+ // them to their normalizd type until code generation
798
+ // time, in short.
799
+ let has_associated_non_fn = traits:: supertrait_def_ids ( tcx, trait_def_id)
800
+ . flat_map ( |def_id| tcx. associated_items ( def_id) )
801
+ . any ( |assoc_item| match assoc_item. kind {
802
+ ty:: AssocKind :: Method => false ,
803
+ ty:: AssocKind :: Type | ty:: AssocKind :: OpaqueTy | ty:: AssocKind :: Const => true ,
804
+ } ) ;
805
+
806
+ let not_object_safe =
807
+ has_associated_non_fn && impl_potentially_overlapping_dyn_trait ( tcx, trait_def_id) ;
808
+
809
+ !not_object_safe
810
+ }
811
+ }
728
812
}
0 commit comments