@@ -32,7 +32,7 @@ pub enum ObjectSafetyViolation {
32
32
33
33
/// Supertrait reference references `Self` an in illegal location
34
34
/// (e.g., `trait Foo : Bar<Self>`).
35
- SupertraitSelf ,
35
+ SupertraitSelf ( SmallVec < [ Span ; 1 ] > ) ,
36
36
37
37
/// Method has something illegal.
38
38
Method ( ast:: Name , MethodViolationCode , Span ) ,
@@ -45,9 +45,13 @@ impl ObjectSafetyViolation {
45
45
pub fn error_msg ( & self ) -> Cow < ' static , str > {
46
46
match * self {
47
47
ObjectSafetyViolation :: SizedSelf ( _) => "it requires `Self: Sized`" . into ( ) ,
48
- ObjectSafetyViolation :: SupertraitSelf => {
49
- "it cannot use `Self` as a type parameter in the supertraits or `where`-clauses"
50
- . into ( )
48
+ ObjectSafetyViolation :: SupertraitSelf ( ref spans) => {
49
+ if spans. iter ( ) . any ( |sp| * sp != DUMMY_SP ) {
50
+ "it uses `Self` as a type parameter in this" . into ( )
51
+ } else {
52
+ "it cannot use `Self` as a type parameter in a supertrait or `where`-clause"
53
+ . into ( )
54
+ }
51
55
}
52
56
ObjectSafetyViolation :: Method ( name, MethodViolationCode :: StaticMethod ( _) , _) => {
53
57
format ! ( "associated function `{}` has no `self` parameter" , name) . into ( )
@@ -87,7 +91,7 @@ impl ObjectSafetyViolation {
87
91
88
92
pub fn solution ( & self ) -> Option < ( String , Option < ( String , Span ) > ) > {
89
93
Some ( match * self {
90
- ObjectSafetyViolation :: SizedSelf ( _) | ObjectSafetyViolation :: SupertraitSelf => {
94
+ ObjectSafetyViolation :: SizedSelf ( _) | ObjectSafetyViolation :: SupertraitSelf ( _ ) => {
91
95
return None ;
92
96
}
93
97
ObjectSafetyViolation :: Method ( name, MethodViolationCode :: StaticMethod ( sugg) , _) => (
@@ -118,7 +122,8 @@ impl ObjectSafetyViolation {
118
122
// When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
119
123
// diagnostics use a `note` instead of a `span_label`.
120
124
match self {
121
- ObjectSafetyViolation :: SizedSelf ( spans) => spans. clone ( ) ,
125
+ ObjectSafetyViolation :: SupertraitSelf ( spans)
126
+ | ObjectSafetyViolation :: SizedSelf ( spans) => spans. clone ( ) ,
122
127
ObjectSafetyViolation :: AssocConst ( _, span)
123
128
| ObjectSafetyViolation :: Method ( _, _, span)
124
129
if * span != DUMMY_SP =>
@@ -162,8 +167,9 @@ pub fn astconv_object_safety_violations(
162
167
) -> Vec < ObjectSafetyViolation > {
163
168
debug_assert ! ( tcx. generics_of( trait_def_id) . has_self) ;
164
169
let violations = traits:: supertrait_def_ids ( tcx, trait_def_id)
165
- . filter ( |& def_id| predicates_reference_self ( tcx, def_id, true ) )
166
- . map ( |_| ObjectSafetyViolation :: SupertraitSelf )
170
+ . map ( |def_id| predicates_reference_self ( tcx, def_id, true ) )
171
+ . filter ( |spans| !spans. is_empty ( ) )
172
+ . map ( |spans| ObjectSafetyViolation :: SupertraitSelf ( spans) )
167
173
. collect ( ) ;
168
174
169
175
debug ! ( "astconv_object_safety_violations(trait_def_id={:?}) = {:?}" , trait_def_id, violations) ;
@@ -266,8 +272,9 @@ fn object_safety_violations_for_trait(
266
272
let spans = get_sized_bounds ( tcx, trait_def_id) ;
267
273
violations. push ( ObjectSafetyViolation :: SizedSelf ( spans) ) ;
268
274
}
269
- if predicates_reference_self ( tcx, trait_def_id, false ) {
270
- violations. push ( ObjectSafetyViolation :: SupertraitSelf ) ;
275
+ let spans = predicates_reference_self ( tcx, trait_def_id, false ) ;
276
+ if !spans. is_empty ( ) {
277
+ violations. push ( ObjectSafetyViolation :: SupertraitSelf ( spans) ) ;
271
278
}
272
279
273
280
violations. extend (
@@ -337,7 +344,11 @@ fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]>
337
344
. unwrap_or_else ( SmallVec :: new)
338
345
}
339
346
340
- fn predicates_reference_self ( tcx : TyCtxt < ' _ > , trait_def_id : DefId , supertraits_only : bool ) -> bool {
347
+ fn predicates_reference_self (
348
+ tcx : TyCtxt < ' _ > ,
349
+ trait_def_id : DefId ,
350
+ supertraits_only : bool ,
351
+ ) -> SmallVec < [ Span ; 1 ] > {
341
352
let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: identity ( tcx, trait_def_id) ) ;
342
353
let predicates = if supertraits_only {
343
354
tcx. super_predicates_of ( trait_def_id)
@@ -349,12 +360,16 @@ fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_o
349
360
predicates
350
361
. predicates
351
362
. iter ( )
352
- . map ( |( predicate, _ ) | predicate. subst_supertrait ( tcx, & trait_ref) )
353
- . any ( | predicate| {
363
+ . map ( |( predicate, sp ) | ( predicate. subst_supertrait ( tcx, & trait_ref) , sp ) )
364
+ . filter_map ( | ( predicate, & sp ) | {
354
365
match predicate {
355
366
ty:: Predicate :: Trait ( ref data, _) => {
356
367
// In the case of a trait predicate, we can skip the "self" type.
357
- data. skip_binder ( ) . input_types ( ) . skip ( 1 ) . any ( has_self_ty)
368
+ if data. skip_binder ( ) . input_types ( ) . skip ( 1 ) . any ( has_self_ty) {
369
+ Some ( sp)
370
+ } else {
371
+ None
372
+ }
358
373
}
359
374
ty:: Predicate :: Projection ( ref data) => {
360
375
// And similarly for projections. This should be redundant with
@@ -369,22 +384,29 @@ fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_o
369
384
//
370
385
// This is ALT2 in issue #56288, see that for discussion of the
371
386
// possible alternatives.
372
- data. skip_binder ( )
387
+ if data
388
+ . skip_binder ( )
373
389
. projection_ty
374
390
. trait_ref ( tcx)
375
391
. input_types ( )
376
392
. skip ( 1 )
377
393
. any ( has_self_ty)
394
+ {
395
+ Some ( sp)
396
+ } else {
397
+ None
398
+ }
378
399
}
379
400
ty:: Predicate :: WellFormed ( ..)
380
401
| ty:: Predicate :: ObjectSafe ( ..)
381
402
| ty:: Predicate :: TypeOutlives ( ..)
382
403
| ty:: Predicate :: RegionOutlives ( ..)
383
404
| ty:: Predicate :: ClosureKind ( ..)
384
405
| ty:: Predicate :: Subtype ( ..)
385
- | ty:: Predicate :: ConstEvaluatable ( ..) => false ,
406
+ | ty:: Predicate :: ConstEvaluatable ( ..) => None ,
386
407
}
387
408
} )
409
+ . collect ( )
388
410
}
389
411
390
412
fn trait_has_sized_self ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
0 commit comments