@@ -15,7 +15,7 @@ use hir::map::DefPathData;
15
15
use infer:: InferCtxt ;
16
16
use hir:: map as ast_map;
17
17
use traits:: { self , Reveal } ;
18
- use ty:: { self , Ty , AdtKind , TyCtxt , TypeAndMut , TypeFlags , TypeFoldable } ;
18
+ use ty:: { self , Ty , TyCtxt , TypeAndMut , TypeFlags , TypeFoldable } ;
19
19
use ty:: { Disr , ParameterEnvironment } ;
20
20
use ty:: fold:: TypeVisitor ;
21
21
use ty:: layout:: { Layout , LayoutError } ;
@@ -120,9 +120,8 @@ impl IntTypeExt for attr::IntType {
120
120
121
121
122
122
#[ derive( Copy , Clone ) ]
123
- pub enum CopyImplementationError {
124
- InfrigingField ( Name ) ,
125
- InfrigingVariant ( Name ) ,
123
+ pub enum CopyImplementationError < ' tcx > {
124
+ InfrigingField ( & ' tcx ty:: FieldDef ) ,
126
125
NotAnAdt ,
127
126
HasDestructor
128
127
}
@@ -145,37 +144,30 @@ pub enum Representability {
145
144
impl < ' tcx > ParameterEnvironment < ' tcx > {
146
145
pub fn can_type_implement_copy < ' a > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
147
146
self_type : Ty < ' tcx > , span : Span )
148
- -> Result < ( ) , CopyImplementationError > {
147
+ -> Result < ( ) , CopyImplementationError > {
149
148
// FIXME: (@jroesch) float this code up
150
- tcx. infer_ctxt ( None , Some ( self . clone ( ) ) , Reveal :: ExactMatch ) . enter ( |infcx| {
151
- let adt = match self_type. sty {
152
- ty:: TyAdt ( adt, substs) => match adt. adt_kind ( ) {
153
- AdtKind :: Struct | AdtKind :: Union => {
154
- for field in adt. all_fields ( ) {
155
- let field_ty = field. ty ( tcx, substs) ;
156
- if infcx. type_moves_by_default ( field_ty, span) {
157
- return Err ( CopyImplementationError :: InfrigingField (
158
- field. name ) )
159
- }
160
- }
161
- adt
162
- }
163
- AdtKind :: Enum => {
164
- for variant in & adt. variants {
165
- for field in & variant. fields {
166
- let field_ty = field. ty ( tcx, substs) ;
167
- if infcx. type_moves_by_default ( field_ty, span) {
168
- return Err ( CopyImplementationError :: InfrigingVariant (
169
- variant. name ) )
170
- }
171
- }
172
- }
173
- adt
174
- }
175
- } ,
149
+ tcx. infer_ctxt ( None , Some ( self . clone ( ) ) , Reveal :: NotSpecializable ) . enter ( |infcx| {
150
+ let ( adt, substs) = match self_type. sty {
151
+ ty:: TyAdt ( adt, substs) => ( adt, substs) ,
176
152
_ => return Err ( CopyImplementationError :: NotAnAdt )
177
153
} ;
178
154
155
+ let field_implements_copy = |field : & ty:: FieldDef | {
156
+ let cause = traits:: ObligationCause :: dummy ( ) ;
157
+ match traits:: fully_normalize ( & infcx, cause, & field. ty ( tcx, substs) ) {
158
+ Ok ( ty) => !infcx. type_moves_by_default ( ty, span) ,
159
+ Err ( ..) => false
160
+ }
161
+ } ;
162
+
163
+ for variant in & adt. variants {
164
+ for field in & variant. fields {
165
+ if !field_implements_copy ( field) {
166
+ return Err ( CopyImplementationError :: InfrigingField ( field) ) ;
167
+ }
168
+ }
169
+ }
170
+
179
171
if adt. has_dtor ( ) {
180
172
return Err ( CopyImplementationError :: HasDestructor ) ;
181
173
}
0 commit comments