@@ -15,7 +15,7 @@ use hir::map::DefPathData;
1515use infer:: InferCtxt ;
1616use hir:: map as ast_map;
1717use traits:: { self , Reveal } ;
18- use ty:: { self , Ty , AdtKind , TyCtxt , TypeAndMut , TypeFlags , TypeFoldable } ;
18+ use ty:: { self , Ty , TyCtxt , TypeAndMut , TypeFlags , TypeFoldable } ;
1919use ty:: { Disr , ParameterEnvironment } ;
2020use ty:: fold:: TypeVisitor ;
2121use ty:: layout:: { Layout , LayoutError } ;
@@ -120,9 +120,8 @@ impl IntTypeExt for attr::IntType {
120120
121121
122122#[ derive( Copy , Clone ) ]
123- pub enum CopyImplementationError {
124- InfrigingField ( Name ) ,
125- InfrigingVariant ( Name ) ,
123+ pub enum CopyImplementationError < ' tcx > {
124+ InfrigingField ( & ' tcx ty:: FieldDef ) ,
126125 NotAnAdt ,
127126 HasDestructor
128127}
@@ -145,37 +144,30 @@ pub enum Representability {
145144impl < ' tcx > ParameterEnvironment < ' tcx > {
146145 pub fn can_type_implement_copy < ' a > ( & self , tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
147146 self_type : Ty < ' tcx > , span : Span )
148- -> Result < ( ) , CopyImplementationError > {
147+ -> Result < ( ) , CopyImplementationError > {
149148 // 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) ,
176152 _ => return Err ( CopyImplementationError :: NotAnAdt )
177153 } ;
178154
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+
179171 if adt. has_dtor ( ) {
180172 return Err ( CopyImplementationError :: HasDestructor ) ;
181173 }
0 commit comments