From 166fbe9afc2a68350653cd96e2ef68d29d47c739 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Sat, 25 Apr 2026 21:17:53 +0000 Subject: [PATCH] fix: exp-destruct --- --- a/crates/jrsonnet-evaluator/src/analyze.rs +++ b/crates/jrsonnet-evaluator/src/analyze.rs @@ -425,7 +425,7 @@ /// h = 1 => referenced += [], closures += 0, destructs += 1 /// And the result is /// - /// ``` + /// ```rust,ignore /// Closures { /// referenced: vec![d, e, f, a, b, c, h] /// spec_shapes: vec![(3, 3), (4, 3), (0, 1)], --- a/crates/jrsonnet-evaluator/src/evaluate/compspec.rs +++ b/crates/jrsonnet-evaluator/src/evaluate/compspec.rs @@ -195,7 +195,7 @@ ) -> Result<()> { if idx >= specs.len() { collector.reserve(guaranteed_reserve); - return collector.collect(ctx.clone()); + return collector.collect(ctx); } match &specs[idx] { LCompSpec::If(cond) => { @@ -239,18 +239,20 @@ )?; } } + // TODO: Should not be eager? CoW won't work here #[cfg(feature = "exp-destruct")] _ => { for (i, item) in arr.iter().enumerate() { let item_val = item?; let mut inner_builder = ContextBuilder::extend(ctx.clone(), 1); + let fctx = Pending::new(); destructure::destruct( destruct, Thunk::evaluated(item_val), - None, + fctx.clone(), &mut inner_builder, ); - let inner_ctx = inner_builder.build(); + let inner_ctx = inner_builder.build().into_future(fctx); evaluate_compspecs_eager( inner_ctx, specs, --- a/crates/jrsonnet-evaluator/src/evaluate/destructure.rs +++ b/crates/jrsonnet-evaluator/src/evaluate/destructure.rs @@ -12,7 +12,7 @@ #[allow(dead_code, reason = "not dead in exp-destruct")] fn destruct_array( start: &[LDestruct], - rest: Option, + rest: Option<&LDestructRest>, end: &[LDestruct], value: Thunk, @@ -56,7 +56,7 @@ if let Some(crate::analyze::LDestructRest::Keep(id)) = rest { let full = full.clone(); builder.bind( - id, + *id, Thunk!(move || { let full = full.evaluate()?; let to = full.len() - end_len; @@ -88,7 +88,7 @@ #[allow(dead_code, reason = "not dead in exp-destruct")] fn destruct_object( fields: &[LDestructField], - rest: Option, + rest: Option<&LDestructRest>, value: Thunk, fctx: Pending, @@ -127,7 +127,7 @@ if let Some(crate::analyze::LDestructRest::Keep(id)) = rest { let full = full.clone(); builder.bind( - id, + *id, Thunk!(move || { let full = full.evaluate()?; let mut out = ObjValueBuilder::new(); @@ -178,9 +178,13 @@ #[cfg(feature = "exp-destruct")] LDestruct::Skip => {} #[cfg(feature = "exp-destruct")] - LDestruct::Array { start, rest, end } => destruct_array(start, rest, end, value, fctx, builder), + LDestruct::Array { start, rest, end } => { + destruct_array(start, rest.as_ref(), end, value, fctx, builder) + } #[cfg(feature = "exp-destruct")] - LDestruct::Object { fields, rest } => destruct_object(fields, rest, value, fctx, builder), + LDestruct::Object { fields, rest } => { + destruct_object(fields, rest.as_ref(), value, fctx, builder) + } } } --- a/crates/jrsonnet-evaluator/src/snapshots/jrsonnet_evaluator__analyze__tests__snapshots@redeclared_local.jsonnet.snap +++ b/crates/jrsonnet-evaluator/src/snapshots/jrsonnet_evaluator__analyze__tests__snapshots@redeclared_local.jsonnet.snap @@ -1,7 +1,7 @@ --- source: crates/jrsonnet-evaluator/src/analyze.rs expression: rendered -input_file: crates/jrsonnet-evaluator/src/analyze_tests/redeclared_local.jsonnet +input_file: crates/jrsonnet-evaluator/src/analysis_tests/redeclared_local.jsonnet --- --- source --- local x = 1, x = 2; x @@ -10,7 +10,7 @@ local_dependent_depth: 0 errored: true --- diagnostics --- - · ╭── variable redeclared: x + · ╭── local is already defined in the current frame: x 1 │ local x = 1, x = 2; x 2 │ --- lir --- --- a/crates/jrsonnet-ir-parser/src/lib.rs +++ b/crates/jrsonnet-ir-parser/src/lib.rs @@ -381,7 +381,7 @@ None }; let default = if p.try_eat(T![=]) { - Some(Rc::new(spanned(p, expr)?)) + Some(spanned(p, expr)?) } else { None }; @@ -466,8 +466,10 @@ if !p.at(SyntaxKind::IDENT) { let d = destruct(p)?; p.eat(T![=])?; - let value = Rc::new(expr(p)?); - return Ok(BindSpec::Field { into: d, value }); + return Ok(BindSpec::Field { + into: d, + value: expr(p)?, + }); } } let name_spanned = spanned(p, ident)?; --- a/crates/jrsonnet-ir/src/expr.rs +++ b/crates/jrsonnet-ir/src/expr.rs @@ -211,7 +211,7 @@ } } -#[derive(Debug, Clone, PartialEq, Eq, Acyclic)] +#[derive(Debug, PartialEq, Eq, Acyclic)] pub enum DestructRest { /// ...rest Keep(IStr), @@ -219,7 +219,7 @@ Drop, } -#[derive(Debug, Clone, PartialEq, Acyclic)] +#[derive(Debug, PartialEq, Acyclic)] pub enum Destruct { Full(Spanned), #[cfg(feature = "exp-destruct")] @@ -233,7 +233,7 @@ #[cfg(feature = "exp-destruct")] Object { #[allow(clippy::type_complexity)] - fields: Vec<(IStr, Option, Option>>)>, + fields: Vec<(IStr, Option, Option>)>, rest: Option, }, } --- a/crates/jrsonnet-peg-parser/src/lib.rs +++ b/crates/jrsonnet-peg-parser/src/lib.rs @@ -1,5 +1,3 @@ -use std::rc::Rc; - use jrsonnet_gcmodule::Acyclic; use jrsonnet_ir::{ ArgsDesc, AssertExpr, AssertStmt, BinaryOp, BindSpec, CompSpec, Destruct, DestructRest, Expr, @@ -110,7 +108,7 @@ } pub rule destruct_object(s: &ParserSettings) -> Destruct = "{" _ - fields:(name:id() into:(_ ":" _ into:destruct(s) {into})? default:(_ "=" _ v:spanned(, s) {v})? {(name, into, default.map(Rc::new))})**comma() + fields:(name:id() into:(_ ":" _ into:destruct(s) {into})? default:(_ "=" _ v:spanned(, s) {v})? {(name, into, default)})**comma() rest:( comma() rest:destruct_rest()? {rest} / comma()? {None} -- gitstuff