@@ -32,7 +32,7 @@ pub enum ObjectSafetyViolation {
3232
3333 /// Supertrait reference references `Self` an in illegal location
3434 /// (e.g., `trait Foo : Bar<Self>`).
35- SupertraitSelf ,
35+ SupertraitSelf ( SmallVec < [ Span ; 1 ] > ) ,
3636
3737 /// Method has something illegal.
3838 Method ( ast:: Name , MethodViolationCode , Span ) ,
@@ -45,9 +45,13 @@ impl ObjectSafetyViolation {
4545 pub fn error_msg ( & self ) -> Cow < ' static , str > {
4646 match * self {
4747 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+ }
5155 }
5256 ObjectSafetyViolation :: Method ( name, MethodViolationCode :: StaticMethod ( _) , _) => {
5357 format ! ( "associated function `{}` has no `self` parameter" , name) . into ( )
@@ -87,7 +91,7 @@ impl ObjectSafetyViolation {
8791
8892 pub fn solution ( & self ) -> Option < ( String , Option < ( String , Span ) > ) > {
8993 Some ( match * self {
90- ObjectSafetyViolation :: SizedSelf ( _) | ObjectSafetyViolation :: SupertraitSelf => {
94+ ObjectSafetyViolation :: SizedSelf ( _) | ObjectSafetyViolation :: SupertraitSelf ( _ ) => {
9195 return None ;
9296 }
9397 ObjectSafetyViolation :: Method ( name, MethodViolationCode :: StaticMethod ( sugg) , _) => (
@@ -118,7 +122,8 @@ impl ObjectSafetyViolation {
118122 // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
119123 // diagnostics use a `note` instead of a `span_label`.
120124 match self {
121- ObjectSafetyViolation :: SizedSelf ( spans) => spans. clone ( ) ,
125+ ObjectSafetyViolation :: SupertraitSelf ( spans)
126+ | ObjectSafetyViolation :: SizedSelf ( spans) => spans. clone ( ) ,
122127 ObjectSafetyViolation :: AssocConst ( _, span)
123128 | ObjectSafetyViolation :: Method ( _, _, span)
124129 if * span != DUMMY_SP =>
@@ -162,8 +167,9 @@ pub fn astconv_object_safety_violations(
162167) -> Vec < ObjectSafetyViolation > {
163168 debug_assert ! ( tcx. generics_of( trait_def_id) . has_self) ;
164169 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) )
167173 . collect ( ) ;
168174
169175 debug ! ( "astconv_object_safety_violations(trait_def_id={:?}) = {:?}" , trait_def_id, violations) ;
@@ -266,8 +272,9 @@ fn object_safety_violations_for_trait(
266272 let spans = get_sized_bounds ( tcx, trait_def_id) ;
267273 violations. push ( ObjectSafetyViolation :: SizedSelf ( spans) ) ;
268274 }
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) ) ;
271278 }
272279
273280 violations. extend (
@@ -337,7 +344,11 @@ fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]>
337344 . unwrap_or_else ( SmallVec :: new)
338345}
339346
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 ] > {
341352 let trait_ref = ty:: Binder :: dummy ( ty:: TraitRef :: identity ( tcx, trait_def_id) ) ;
342353 let predicates = if supertraits_only {
343354 tcx. super_predicates_of ( trait_def_id)
@@ -349,12 +360,16 @@ fn predicates_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId, supertraits_o
349360 predicates
350361 . predicates
351362 . 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 ) | {
354365 match predicate {
355366 ty:: Predicate :: Trait ( ref data, _) => {
356367 // 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+ }
358373 }
359374 ty:: Predicate :: Projection ( ref data) => {
360375 // 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
369384 //
370385 // This is ALT2 in issue #56288, see that for discussion of the
371386 // possible alternatives.
372- data. skip_binder ( )
387+ if data
388+ . skip_binder ( )
373389 . projection_ty
374390 . trait_ref ( tcx)
375391 . input_types ( )
376392 . skip ( 1 )
377393 . any ( has_self_ty)
394+ {
395+ Some ( sp)
396+ } else {
397+ None
398+ }
378399 }
379400 ty:: Predicate :: WellFormed ( ..)
380401 | ty:: Predicate :: ObjectSafe ( ..)
381402 | ty:: Predicate :: TypeOutlives ( ..)
382403 | ty:: Predicate :: RegionOutlives ( ..)
383404 | ty:: Predicate :: ClosureKind ( ..)
384405 | ty:: Predicate :: Subtype ( ..)
385- | ty:: Predicate :: ConstEvaluatable ( ..) => false ,
406+ | ty:: Predicate :: ConstEvaluatable ( ..) => None ,
386407 }
387408 } )
409+ . collect ( )
388410}
389411
390412fn trait_has_sized_self ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> bool {
0 commit comments