@@ -309,17 +309,41 @@ impl<'a> Builder<'a> {
309
309
//
310
310
// We set "bar" (index 0) to return bytes, and "baz" (index 1) to return an
311
311
// integer.
312
+ //
313
+ // If one of the arguments is dependant on a closure, the parameters initial
314
+ // type is assigned here and it's recomputed from the compiled closure.
312
315
for ( index, input_var) in input. variables . clone ( ) . into_iter ( ) . enumerate ( ) {
313
316
let call_ident = & variables[ index] ;
314
317
let type_def = target. type_info ( state) . result ;
315
318
316
- let ( type_def, value) = match input_var. kind {
319
+ let mut var_kind = input_var. kind ;
320
+ if let VariableKind :: Closure ( vk) = var_kind {
321
+ var_kind = vk. into ( ) ;
322
+ }
323
+
324
+ let ( type_def, value) = match var_kind {
325
+ // A closure variable kind is not possible here but we need to
326
+ // satisfy all variants with a match arm.
327
+ VariableKind :: Closure ( _) => {
328
+ panic ! ( "got unexpected variable kind" )
329
+ }
330
+
331
+ // The variable kind is expected to be equal to the kind of a
332
+ // specified parameter of the closure.
333
+ VariableKind :: Parameter ( keyword) => {
334
+ let expr = list
335
+ . arguments
336
+ . get ( keyword)
337
+ . expect ( "parameter should exist" ) ;
338
+ ( expr. type_info ( state) . result , expr. resolve_constant ( state) )
339
+ }
340
+
317
341
// The variable kind is expected to be exactly
318
342
// the kind provided by the closure definition.
319
343
VariableKind :: Exact ( kind) => ( kind. into ( ) , None ) ,
320
344
321
345
// The variable kind is expected to be equal to
322
- // the ind of the target of the closure.
346
+ // the kind of the target of the closure.
323
347
VariableKind :: Target => (
324
348
target. type_info ( state) . result ,
325
349
target. resolve_constant ( state) ,
@@ -505,7 +529,36 @@ impl<'a> Builder<'a> {
505
529
// TODO: This assumes the closure will run exactly once, which is incorrect.
506
530
// see: https://github.com/vectordotdev/vector/issues/13782
507
531
508
- let block = closure_block. expect ( "closure must contain block" ) ;
532
+ let ( block_span, ( block, mut block_type_def) ) =
533
+ closure_block. expect ( "closure must contain block" ) . take ( ) ;
534
+
535
+ let mut closure_dependent_variables = input
536
+ . variables
537
+ . iter ( )
538
+ . enumerate ( )
539
+ . filter_map ( |( index, input_var) | match input_var. kind {
540
+ VariableKind :: Closure ( _) => Some ( & variables[ index] ) ,
541
+ _ => None ,
542
+ } )
543
+ . peekable ( ) ;
544
+
545
+ // If any of the arugments are dependant on the closure, union the initial type with the
546
+ // returned type of the closure and then recompute the closures type.
547
+ if closure_dependent_variables. peek ( ) . is_some ( ) {
548
+ let block_kind = block_type_def
549
+ . kind ( )
550
+ . union ( block_type_def. returns ( ) . clone ( ) ) ;
551
+
552
+ closure_dependent_variables. for_each ( |ident| {
553
+ let details = state
554
+ . local
555
+ . variable_mut ( ident)
556
+ . expect ( "state must contain a closure dependant argument" ) ;
557
+ details. type_def = details. type_def . kind ( ) . union ( block_kind. clone ( ) ) . into ( ) ;
558
+ } ) ;
559
+
560
+ block_type_def = block. apply_type_info ( state) ;
561
+ }
509
562
510
563
// At this point, we've compiled the block, so we can remove the
511
564
// closure variables from the compiler's local environment.
@@ -518,8 +571,6 @@ impl<'a> Builder<'a> {
518
571
}
519
572
} ) ;
520
573
521
- let ( block_span, ( block, block_type_def) ) = block. take ( ) ;
522
-
523
574
let closure_fallible = block_type_def. is_fallible ( ) ;
524
575
525
576
// Check the type definition of the resulting block.This needs to match
0 commit comments