@@ -136,7 +136,10 @@ impl Evaluator<'_> {
136136 not_supported ! ( "wrong generic arg kind for clone" ) ;
137137 } ;
138138 // 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+ ) {
140143 self . exec_clone ( def, args, self_ty. clone ( ) , locals, destination, span) ?;
141144 return Ok ( true ) ;
142145 }
@@ -167,32 +170,26 @@ impl Evaluator<'_> {
167170 return destination
168171 . write_from_interval ( self , Interval { addr, size : destination. size } ) ;
169172 }
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+ }
170185 TyKind :: Tuple ( _, subst) => {
171186 let [ arg] = args else {
172187 not_supported ! ( "wrong arg count for clone" ) ;
173188 } ;
174189 let addr = Address :: from_bytes ( arg. get ( self ) ?) ?;
175190 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) ?;
196193 }
197194 _ => {
198195 self . exec_fn_with_args (
@@ -209,6 +206,37 @@ impl Evaluator<'_> {
209206 Ok ( ( ) )
210207 }
211208
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+
212240 fn exec_alloc_fn (
213241 & mut self ,
214242 alloc_fn : & str ,
0 commit comments