20
20
use super :: elaborate_predicates;
21
21
22
22
use hir:: def_id:: DefId ;
23
+ use lint;
23
24
use traits;
24
25
use ty:: { self , Ty , TyCtxt , TypeFoldable } ;
25
26
use ty:: subst:: Substs ;
26
27
use ty:: util:: ExplicitSelf ;
27
28
use std:: borrow:: Cow ;
28
29
use syntax:: ast;
30
+ use syntax_pos:: Span ;
29
31
30
- #[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
32
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
31
33
pub enum ObjectSafetyViolation {
32
34
/// Self : Sized declared on the trait
33
35
SizedSelf ,
@@ -56,6 +58,9 @@ impl ObjectSafetyViolation {
56
58
ObjectSafetyViolation :: Method ( name, MethodViolationCode :: ReferencesSelf ) =>
57
59
format ! ( "method `{}` references the `Self` type \
58
60
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 ( ) ,
59
64
ObjectSafetyViolation :: Method ( name, MethodViolationCode :: Generic ) =>
60
65
format ! ( "method `{}` has generic type parameters" , name) . into ( ) ,
61
66
ObjectSafetyViolation :: Method ( name, MethodViolationCode :: NonStandardSelfType ) =>
@@ -75,6 +80,9 @@ pub enum MethodViolationCode {
75
80
/// e.g., `fn foo(&self, x: Self)` or `fn foo(&self) -> Self`
76
81
ReferencesSelf ,
77
82
83
+ /// e.g. `fn foo(&self) where Self: Clone`
84
+ WhereClauseReferencesSelf ( Span ) ,
85
+
78
86
/// e.g., `fn foo<A>()`
79
87
Generic ,
80
88
@@ -123,6 +131,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
123
131
. filter_map ( |item| {
124
132
self . object_safety_violation_for_method ( trait_def_id, & item)
125
133
. 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
+ }
126
150
} ) . collect ( ) ;
127
151
128
152
// Check the trait itself.
@@ -245,7 +269,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
245
269
return false ;
246
270
}
247
271
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
+ }
249
276
}
250
277
251
278
/// Returns `Some(_)` if this method cannot be called on a trait
@@ -288,6 +315,18 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
288
315
return Some ( MethodViolationCode :: Generic ) ;
289
316
}
290
317
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
+
291
330
None
292
331
}
293
332
0 commit comments