2020use super :: elaborate_predicates;
2121
2222use hir:: def_id:: DefId ;
23+ use lint;
2324use traits;
2425use ty:: { self , Ty , TyCtxt , TypeFoldable } ;
2526use ty:: subst:: Substs ;
2627use ty:: util:: ExplicitSelf ;
2728use std:: borrow:: Cow ;
2829use syntax:: ast;
30+ use syntax_pos:: Span ;
2931
30- #[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
32+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
3133pub enum ObjectSafetyViolation {
3234 /// Self : Sized declared on the trait
3335 SizedSelf ,
@@ -56,6 +58,9 @@ impl ObjectSafetyViolation {
5658 ObjectSafetyViolation :: Method ( name, MethodViolationCode :: ReferencesSelf ) =>
5759 format ! ( "method `{}` references the `Self` type \
5860 in its arguments or return type", name) . into ( ) ,
61+ ObjectSafetyViolation :: Method ( name,
62+ MethodViolationCode :: WhereClauseReferencesSelf ( _) ) =>
63+ format ! ( "method `{}` references the `Self` type in where clauses" , name) . into ( ) ,
5964 ObjectSafetyViolation :: Method ( name, MethodViolationCode :: Generic ) =>
6065 format ! ( "method `{}` has generic type parameters" , name) . into ( ) ,
6166 ObjectSafetyViolation :: Method ( name, MethodViolationCode :: NonStandardSelfType ) =>
@@ -75,6 +80,9 @@ pub enum MethodViolationCode {
7580 /// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self`
7681 ReferencesSelf ,
7782
83+ /// e.g. `fn foo(&self) where Self: Clone`
84+ WhereClauseReferencesSelf ( Span ) ,
85+
7886 /// e.g., `fn foo<A>()`
7987 Generic ,
8088
@@ -123,6 +131,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
123131 . filter_map ( |item| {
124132 self . object_safety_violation_for_method ( trait_def_id, & item)
125133 . map ( |code| ObjectSafetyViolation :: Method ( item. name , code) )
134+ } ) . filter ( |violation| {
135+ if let ObjectSafetyViolation :: Method ( _,
136+ MethodViolationCode :: WhereClauseReferencesSelf ( span) ) = violation {
137+ // Using`CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
138+ // It's also hard to get a use site span, so we use the method definition span.
139+ self . lint_node_note (
140+ lint:: builtin:: WHERE_CLAUSES_OBJECT_SAFETY ,
141+ ast:: CRATE_NODE_ID ,
142+ * span,
143+ & format ! ( "the trait `{}` cannot be made into an object" ,
144+ self . item_path_str( trait_def_id) ) ,
145+ & violation. error_msg ( ) ) ;
146+ false
147+ } else {
148+ true
149+ }
126150 } ) . collect ( ) ;
127151
128152 // Check the trait itself.
@@ -245,7 +269,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
245269 return false ;
246270 }
247271
248- self . virtual_call_violation_for_method ( trait_def_id, method) . is_none ( )
272+ match self . virtual_call_violation_for_method ( trait_def_id, method) {
273+ None | Some ( MethodViolationCode :: WhereClauseReferencesSelf ( _) ) => true ,
274+ Some ( _) => false ,
275+ }
249276 }
250277
251278 /// Returns `Some(_)` if this method cannot be called on a trait
@@ -288,6 +315,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
288315 return Some ( MethodViolationCode :: Generic ) ;
289316 }
290317
318+ if self . predicates_of ( method. def_id ) . predicates . into_iter ( )
319+ // A trait object can't claim to live more than the concrete type,
320+ // so outlives predicates will always hold.
321+ . filter ( |p| p. to_opt_type_outlives ( ) . is_none ( ) )
322+ . collect :: < Vec < _ > > ( )
323+ // Do a shallow visit so that `contains_illegal_self_type_reference`
324+ // may apply it's custom visiting.
325+ . visit_tys_shallow ( |t| self . contains_illegal_self_type_reference ( trait_def_id, t) ) {
326+ let span = self . def_span ( method. def_id ) ;
327+ return Some ( MethodViolationCode :: WhereClauseReferencesSelf ( span) ) ;
328+ }
329+
291330 None
292331 }
293332
0 commit comments