@@ -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 ,
@@ -473,6 +501,38 @@ impl Evaluator<'_> {
473
501
self . write_memory_using_ref ( destination. addr , destination. size ) ?. fill ( 0 ) ;
474
502
Ok ( ( ) )
475
503
}
504
+ "getenv" => {
505
+ let [ name] = args else {
506
+ return Err ( MirEvalError :: TypeError ( "libc::write args are not provided" ) ) ;
507
+ } ;
508
+ let mut name_buf = vec ! [ ] ;
509
+ let name = {
510
+ let mut index = Address :: from_bytes ( name. get ( self ) ?) ?;
511
+ loop {
512
+ let byte = self . read_memory ( index, 1 ) ?[ 0 ] ;
513
+ index = index. offset ( 1 ) ;
514
+ if byte == 0 {
515
+ break ;
516
+ }
517
+ name_buf. push ( byte) ;
518
+ }
519
+ String :: from_utf8_lossy ( & name_buf)
520
+ } ;
521
+ let value = self . db . crate_graph ( ) [ self . crate_id ] . env . get ( & name) ;
522
+ match value {
523
+ None => {
524
+ // Write null as fail
525
+ self . write_memory_using_ref ( destination. addr , destination. size ) ?. fill ( 0 ) ;
526
+ }
527
+ Some ( mut value) => {
528
+ value. push ( '\0' ) ;
529
+ let addr = self . heap_allocate ( value. len ( ) , 1 ) ?;
530
+ self . write_memory ( addr, value. as_bytes ( ) ) ?;
531
+ self . write_memory ( destination. addr , & addr. to_bytes ( ) ) ?;
532
+ }
533
+ }
534
+ Ok ( ( ) )
535
+ }
476
536
_ => not_supported ! ( "unknown external function {as_str}" ) ,
477
537
}
478
538
}
0 commit comments