--- a/crates/jrsonnet-evaluator/src/evaluate/destructure.rs +++ b/crates/jrsonnet-evaluator/src/evaluate/destructure.rs @@ -107,6 +107,11 @@ } #[cfg(feature = "exp-destruct")] Destruct::Object { fields, rest } => { + use crate::ObjValueBuilder; + use jrsonnet_ir::DestructRest; + use rustc_hash::FxHashSet; + + let captured_fields: FxHashSet<_> = fields.iter().map(|f| f.0.clone()).collect(); let field_names: Vec<_> = fields .iter() .map(|f| (f.0.clone(), f.2.is_some())) @@ -131,6 +136,27 @@ Ok(obj) }); + match rest { + Some(DestructRest::Keep(v)) => { + let full = full.clone(); + destruct( + &Destruct::Full(v.clone()), + Thunk!(move || { + let full = full.evaluate()?; + let mut builder = ObjValueBuilder::new(); + builder + .reserve_cores(1) + .extend_with_core(full.as_standalone()); + builder.with_fields_omitted(captured_fields); + Ok(Val::Obj(builder.build())) + }), + fctx.clone(), + new_bindings, + )?; + } + Some(DestructRest::Drop) | None => {} + } + for (field, d, default) in fields { let default = default.clone().map(|e| (fctx.clone(), e)); let value = { --- a/crates/jrsonnet-evaluator/src/obj/mod.rs +++ b/crates/jrsonnet-evaluator/src/obj/mod.rs @@ -158,6 +158,7 @@ pub type EnumFieldsHandler<'a> = dyn FnMut(SuperDepth, FieldIndex, IStr, EnumFields) -> ControlFlow<()> + 'a; +#[derive(Debug)] pub enum EnumFields { Normal(Visibility), Omit(Skip), @@ -289,7 +290,7 @@ } #[derive(Trace, Debug)] -struct StandaloneSuperCore { +pub(crate) struct StandaloneSuperCore { sup: CoreIdx, this: ObjValue, } @@ -791,6 +792,14 @@ key, }) } + pub(crate) fn as_standalone(&self) -> StandaloneSuperCore { + StandaloneSuperCore { + sup: CoreIdx { + idx: self.0.cores.len(), + }, + this: self.clone(), + } + } pub fn ptr_eq(a: &Self, b: &Self) -> bool { Cc::ptr_eq(&a.0, &b.0) }