@@ -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 ,
@@ -473,6 +501,38 @@ impl Evaluator<'_> {
473501 self . write_memory_using_ref ( destination. addr , destination. size ) ?. fill ( 0 ) ;
474502 Ok ( ( ) )
475503 }
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+ }
476536 _ => not_supported ! ( "unknown external function {as_str}" ) ,
477537 }
478538 }
0 commit comments