git.delta.rocks / jrsonnet / refs/commits / 166fbe9afc2a

difftreelog

fix exp-destruct

wkqlwykpYaroslav Bolyukin2026-04-25parent: #a3646b3.patch.diff
in: master

7 files changed

modifiedcrates/jrsonnet-evaluator/src/analyze.rsdiffbeforeafterboth
--- 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)],
modifiedcrates/jrsonnet-evaluator/src/evaluate/compspec.rsdiffbeforeafterboth
--- 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,
modifiedcrates/jrsonnet-evaluator/src/evaluate/destructure.rsdiffbeforeafterboth
12#[allow(dead_code, reason = "not dead in exp-destruct")]12#[allow(dead_code, reason = "not dead in exp-destruct")]
13fn destruct_array(13fn destruct_array(
14 start: &[LDestruct],14 start: &[LDestruct],
15 rest: Option<LDestructRest>,15 rest: Option<&LDestructRest>,
16 end: &[LDestruct],16 end: &[LDestruct],
1717
18 value: Thunk<Val>,18 value: Thunk<Val>,
56 if let Some(crate::analyze::LDestructRest::Keep(id)) = rest {56 if let Some(crate::analyze::LDestructRest::Keep(id)) = rest {
57 let full = full.clone();57 let full = full.clone();
58 builder.bind(58 builder.bind(
59 id,59 *id,
60 Thunk!(move || {60 Thunk!(move || {
61 let full = full.evaluate()?;61 let full = full.evaluate()?;
62 let to = full.len() - end_len;62 let to = full.len() - end_len;
88#[allow(dead_code, reason = "not dead in exp-destruct")]88#[allow(dead_code, reason = "not dead in exp-destruct")]
89fn destruct_object(89fn destruct_object(
90 fields: &[LDestructField],90 fields: &[LDestructField],
91 rest: Option<LDestructRest>,91 rest: Option<&LDestructRest>,
9292
93 value: Thunk<Val>,93 value: Thunk<Val>,
94 fctx: Pending<Context>,94 fctx: Pending<Context>,
127 if let Some(crate::analyze::LDestructRest::Keep(id)) = rest {127 if let Some(crate::analyze::LDestructRest::Keep(id)) = rest {
128 let full = full.clone();128 let full = full.clone();
129 builder.bind(129 builder.bind(
130 id,130 *id,
131 Thunk!(move || {131 Thunk!(move || {
132 let full = full.evaluate()?;132 let full = full.evaluate()?;
133 let mut out = ObjValueBuilder::new();133 let mut out = ObjValueBuilder::new();
178 #[cfg(feature = "exp-destruct")]178 #[cfg(feature = "exp-destruct")]
179 LDestruct::Skip => {}179 LDestruct::Skip => {}
180 #[cfg(feature = "exp-destruct")]180 #[cfg(feature = "exp-destruct")]
181 LDestruct::Array { start, rest, end } => destruct_array(start, rest, end, value, fctx, builder),181 LDestruct::Array { start, rest, end } => {
182 destruct_array(start, rest.as_ref(), end, value, fctx, builder)
183 }
182 #[cfg(feature = "exp-destruct")]184 #[cfg(feature = "exp-destruct")]
183 LDestruct::Object { fields, rest } => destruct_object(fields, rest, value, fctx, builder),185 LDestruct::Object { fields, rest } => {
186 destruct_object(fields, rest.as_ref(), value, fctx, builder)
187 }
184 }188 }
185}189}
186190
modifiedcrates/jrsonnet-evaluator/src/snapshots/jrsonnet_evaluator__analyze__tests__snapshots@redeclared_local.jsonnet.snapdiffbeforeafterboth
--- 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 ---
modifiedcrates/jrsonnet-ir-parser/src/lib.rsdiffbeforeafterboth
--- 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)?;
modifiedcrates/jrsonnet-ir/src/expr.rsdiffbeforeafterboth
--- 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<IStr>),
 	#[cfg(feature = "exp-destruct")]
@@ -233,7 +233,7 @@
 	#[cfg(feature = "exp-destruct")]
 	Object {
 		#[allow(clippy::type_complexity)]
-		fields: Vec<(IStr, Option<Destruct>, Option<Rc<Spanned<Expr>>>)>,
+		fields: Vec<(IStr, Option<Destruct>, Option<Spanned<Expr>>)>,
 		rest: Option<DestructRest>,
 	},
 }
modifiedcrates/jrsonnet-peg-parser/src/lib.rsdiffbeforeafterboth
--- 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(<expr(s)>, s) {v})? {(name, into, default.map(Rc::new))})**comma()
+				fields:(name:id() into:(_ ":" _ into:destruct(s) {into})? default:(_ "=" _ v:spanned(<expr(s)>, s) {v})? {(name, into, default)})**comma()
 				rest:(
 					comma() rest:destruct_rest()? {rest}
 					/ comma()? {None}