@@ -45,7 +45,7 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
45
45
46
46
// Ensure that if ~T is cast to ~Trait, then T : Trait
47
47
push_cast_obligation ( fcx, cast_expr, object_trait, referent_ty) ;
48
- check_object_safety ( fcx. tcx ( ) , object_trait, source_expr. span ) ;
48
+ check_object_safety ( fcx. tcx ( ) , & object_trait. principal , source_expr. span ) ;
49
49
}
50
50
51
51
( & ty:: ty_rptr( referent_region, ty:: mt { ty : referent_ty,
@@ -69,7 +69,7 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
69
69
target_region,
70
70
referent_region) ;
71
71
72
- check_object_safety ( fcx. tcx ( ) , object_trait, source_expr. span ) ;
72
+ check_object_safety ( fcx. tcx ( ) , & object_trait. principal , source_expr. span ) ;
73
73
}
74
74
}
75
75
@@ -133,17 +133,32 @@ pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
133
133
// self by value, has no type parameters and does not use the `Self` type, except
134
134
// in self position.
135
135
pub fn check_object_safety < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
136
- object_trait : & ty:: TyTrait < ' tcx > ,
136
+ object_trait : & ty:: TraitRef < ' tcx > ,
137
+ span : Span ) {
138
+
139
+ let mut object = object_trait. clone ( ) ;
140
+ if object. substs . types . len ( SelfSpace ) == 0 {
141
+ object. substs . types . push ( SelfSpace , ty:: mk_err ( ) ) ;
142
+ }
143
+
144
+ let object = Rc :: new ( object) ;
145
+ for tr in traits:: supertraits ( tcx, object) {
146
+ check_object_safety_inner ( tcx, & * tr, span) ;
147
+ }
148
+ }
149
+
150
+ fn check_object_safety_inner < ' tcx > ( tcx : & ty:: ctxt < ' tcx > ,
151
+ object_trait : & ty:: TraitRef < ' tcx > ,
137
152
span : Span ) {
138
153
// Skip the fn_once lang item trait since only the compiler should call
139
154
// `call_once` which is the method which takes self by value. What could go
140
155
// wrong?
141
156
match tcx. lang_items . fn_once_trait ( ) {
142
- Some ( def_id) if def_id == object_trait. principal . def_id => return ,
157
+ Some ( def_id) if def_id == object_trait. def_id => return ,
143
158
_ => { }
144
159
}
145
160
146
- let trait_items = ty:: trait_items ( tcx, object_trait. principal . def_id ) ;
161
+ let trait_items = ty:: trait_items ( tcx, object_trait. def_id ) ;
147
162
148
163
let mut errors = Vec :: new ( ) ;
149
164
for item in trait_items. iter ( ) {
@@ -157,7 +172,7 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
157
172
158
173
let mut errors = errors. iter ( ) . flat_map ( |x| x. iter ( ) ) . peekable ( ) ;
159
174
if errors. peek ( ) . is_some ( ) {
160
- let trait_name = ty:: item_path_str ( tcx, object_trait. principal . def_id ) ;
175
+ let trait_name = ty:: item_path_str ( tcx, object_trait. def_id ) ;
161
176
span_err ! ( tcx. sess, span, E0038 ,
162
177
"cannot convert to a trait object because trait `{}` is not object-safe" ,
163
178
trait_name) ;
0 commit comments