@@ -136,7 +136,10 @@ impl Evaluator<'_> {
136
136
not_supported ! ( "wrong generic arg kind for clone" ) ;
137
137
} ;
138
138
// Clone has special impls for tuples and function pointers
139
- if matches ! ( self_ty. kind( Interner ) , TyKind :: Function ( _) | TyKind :: Tuple ( ..) ) {
139
+ if matches ! (
140
+ self_ty. kind( Interner ) ,
141
+ TyKind :: Function ( _) | TyKind :: Tuple ( ..) | TyKind :: Closure ( ..)
142
+ ) {
140
143
self . exec_clone ( def, args, self_ty. clone ( ) , locals, destination, span) ?;
141
144
return Ok ( true ) ;
142
145
}
@@ -167,32 +170,26 @@ impl Evaluator<'_> {
167
170
return destination
168
171
. write_from_interval ( self , Interval { addr, size : destination. size } ) ;
169
172
}
173
+ TyKind :: Closure ( id, subst) => {
174
+ let [ arg] = args else {
175
+ not_supported ! ( "wrong arg count for clone" ) ;
176
+ } ;
177
+ let addr = Address :: from_bytes ( arg. get ( self ) ?) ?;
178
+ let ( closure_owner, _) = self . db . lookup_intern_closure ( ( * id) . into ( ) ) ;
179
+ let infer = self . db . infer ( closure_owner) ;
180
+ let ( captures, _) = infer. closure_info ( id) ;
181
+ let layout = self . layout ( & self_ty) ?;
182
+ let ty_iter = captures. iter ( ) . map ( |c| c. ty ( subst) ) ;
183
+ self . exec_clone_for_fields ( ty_iter, layout, addr, def, locals, destination, span) ?;
184
+ }
170
185
TyKind :: Tuple ( _, subst) => {
171
186
let [ arg] = args else {
172
187
not_supported ! ( "wrong arg count for clone" ) ;
173
188
} ;
174
189
let addr = Address :: from_bytes ( arg. get ( self ) ?) ?;
175
190
let layout = self . layout ( & self_ty) ?;
176
- for ( i, ty) in subst. iter ( Interner ) . enumerate ( ) {
177
- let ty = ty. assert_ty_ref ( Interner ) ;
178
- let size = self . layout ( ty) ?. size . bytes_usize ( ) ;
179
- let tmp = self . heap_allocate ( self . ptr_size ( ) , self . ptr_size ( ) ) ?;
180
- let arg = IntervalAndTy {
181
- interval : Interval { addr : tmp, size : self . ptr_size ( ) } ,
182
- ty : TyKind :: Ref ( Mutability :: Not , static_lifetime ( ) , ty. clone ( ) )
183
- . intern ( Interner ) ,
184
- } ;
185
- let offset = layout. fields . offset ( i) . bytes_usize ( ) ;
186
- self . write_memory ( tmp, & addr. offset ( offset) . to_bytes ( ) ) ?;
187
- self . exec_clone (
188
- def,
189
- & [ arg] ,
190
- ty. clone ( ) ,
191
- locals,
192
- destination. slice ( offset..offset + size) ,
193
- span,
194
- ) ?;
195
- }
191
+ let ty_iter = subst. iter ( Interner ) . map ( |ga| ga. assert_ty_ref ( Interner ) . clone ( ) ) ;
192
+ self . exec_clone_for_fields ( ty_iter, layout, addr, def, locals, destination, span) ?;
196
193
}
197
194
_ => {
198
195
self . exec_fn_with_args (
@@ -209,6 +206,37 @@ impl Evaluator<'_> {
209
206
Ok ( ( ) )
210
207
}
211
208
209
+ fn exec_clone_for_fields (
210
+ & mut self ,
211
+ ty_iter : impl Iterator < Item = Ty > ,
212
+ layout : Arc < Layout > ,
213
+ addr : Address ,
214
+ def : FunctionId ,
215
+ locals : & Locals ,
216
+ destination : Interval ,
217
+ span : MirSpan ,
218
+ ) -> Result < ( ) > {
219
+ for ( i, ty) in ty_iter. enumerate ( ) {
220
+ let size = self . layout ( & ty) ?. size . bytes_usize ( ) ;
221
+ let tmp = self . heap_allocate ( self . ptr_size ( ) , self . ptr_size ( ) ) ?;
222
+ let arg = IntervalAndTy {
223
+ interval : Interval { addr : tmp, size : self . ptr_size ( ) } ,
224
+ ty : TyKind :: Ref ( Mutability :: Not , static_lifetime ( ) , ty. clone ( ) ) . intern ( Interner ) ,
225
+ } ;
226
+ let offset = layout. fields . offset ( i) . bytes_usize ( ) ;
227
+ self . write_memory ( tmp, & addr. offset ( offset) . to_bytes ( ) ) ?;
228
+ self . exec_clone (
229
+ def,
230
+ & [ arg] ,
231
+ ty,
232
+ locals,
233
+ destination. slice ( offset..offset + size) ,
234
+ span,
235
+ ) ?;
236
+ }
237
+ Ok ( ( ) )
238
+ }
239
+
212
240
fn exec_alloc_fn (
213
241
& mut self ,
214
242
alloc_fn : & str ,
0 commit comments