@@ -18,15 +18,16 @@ use rustc_hir::def_id::DefId;
1818use rustc_session:: lint:: builtin:: WHERE_CLAUSES_OBJECT_SAFETY ;
1919use rustc_span:: symbol:: Symbol ;
2020use rustc_span:: { Span , DUMMY_SP } ;
21+ use smallvec:: SmallVec ;
2122use syntax:: ast;
2223
2324use std:: borrow:: Cow ;
2425use std:: iter:: { self } ;
2526
26- #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
27+ #[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
2728pub enum ObjectSafetyViolation {
2829 /// `Self: Sized` declared on the trait.
29- SizedSelf ( Span ) ,
30+ SizedSelf ( SmallVec < [ Span ; 1 ] > ) ,
3031
3132 /// Supertrait reference references `Self` an in illegal location
3233 /// (e.g., `trait Foo : Bar<Self>`).
@@ -75,18 +76,18 @@ impl ObjectSafetyViolation {
7576 }
7677 }
7778
78- pub fn span ( & self ) -> Option < Span > {
79+ pub fn spans ( & self ) -> SmallVec < [ Span ; 1 ] > {
7980 // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so
8081 // diagnostics use a `note` instead of a `span_label`.
81- match * self {
82+ match self {
83+ ObjectSafetyViolation :: SizedSelf ( spans) => spans. clone ( ) ,
8284 ObjectSafetyViolation :: AssocConst ( _, span)
83- | ObjectSafetyViolation :: SizedSelf ( span)
8485 | ObjectSafetyViolation :: Method ( _, _, span)
85- if span != DUMMY_SP =>
86+ if * span != DUMMY_SP =>
8687 {
87- Some ( span)
88+ vec ! [ * span] . into ( )
8889 }
89- _ => None ,
90+ _ => vec ! [ ] . into ( ) ,
9091 }
9192 }
9293}
@@ -189,10 +190,14 @@ fn object_safety_violations_for_trait(
189190 tcx. def_path_str( trait_def_id)
190191 ) ,
191192 ) ;
192- match violation. span ( ) {
193- Some ( span) => err. span_label ( span, violation. error_msg ( ) ) ,
194- None => err. note ( & violation. error_msg ( ) ) ,
195- } ;
193+ let spans = violation. spans ( ) ;
194+ if spans. is_empty ( ) {
195+ err. note ( & violation. error_msg ( ) ) ;
196+ } else {
197+ for span in spans {
198+ err. span_label ( span, violation. error_msg ( ) ) ;
199+ }
200+ }
196201 err. emit ( ) ;
197202 false
198203 } else {
@@ -203,8 +208,9 @@ fn object_safety_violations_for_trait(
203208
204209 // Check the trait itself.
205210 if trait_has_sized_self ( tcx, trait_def_id) {
206- let span = get_sized_bound ( tcx, trait_def_id) ;
207- violations. push ( ObjectSafetyViolation :: SizedSelf ( span) ) ;
211+ // We don't want to include the requirement from `Sized` itself to be `Sized` in the list.
212+ let spans = get_sized_bounds ( tcx, trait_def_id) ;
213+ violations. push ( ObjectSafetyViolation :: SizedSelf ( spans) ) ;
208214 }
209215 if predicates_reference_self ( tcx, trait_def_id, false ) {
210216 violations. push ( ObjectSafetyViolation :: SupertraitSelf ) ;
@@ -224,25 +230,26 @@ fn object_safety_violations_for_trait(
224230 violations
225231}
226232
227- fn get_sized_bound ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> Span {
233+ fn get_sized_bounds ( tcx : TyCtxt < ' _ > , trait_def_id : DefId ) -> SmallVec < [ Span ; 1 ] > {
228234 tcx. hir ( )
229235 . get_if_local ( trait_def_id)
230236 . and_then ( |node| match node {
231- hir:: Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Trait ( .., bounds, _) , .. } ) => bounds
232- . iter ( )
233- . filter_map ( |b| match b {
234- hir:: GenericBound :: Trait ( trait_ref, hir:: TraitBoundModifier :: None )
235- if Some ( trait_ref. trait_ref . trait_def_id ( ) )
236- == tcx. lang_items ( ) . sized_trait ( ) =>
237- {
238- Some ( trait_ref. span )
239- }
240- _ => None ,
241- } )
242- . next ( ) ,
237+ hir:: Node :: Item ( hir:: Item { kind : hir:: ItemKind :: Trait ( .., bounds, _) , .. } ) => Some (
238+ bounds
239+ . iter ( )
240+ . filter_map ( |b| match b {
241+ hir:: GenericBound :: Trait ( trait_ref, hir:: TraitBoundModifier :: None )
242+ if trait_has_sized_self ( tcx, trait_ref. trait_ref . trait_def_id ( ) ) =>
243+ {
244+ Some ( trait_ref. span )
245+ }
246+ _ => None ,
247+ } )
248+ . collect :: < SmallVec < [ Span ; 1 ] > > ( ) ,
249+ ) ,
243250 _ => None ,
244251 } )
245- . unwrap_or ( DUMMY_SP )
252+ . unwrap_or_else ( SmallVec :: new )
246253}
247254
248255fn predicates_reference_self ( tcx : TyCtxt < ' _ > , trait_def_id : DefId , supertraits_only : bool ) -> bool {
0 commit comments