git.delta.rocks / jrsonnet / refs/commits / c02b270b3da5

difftreelog

refactor no need to use CacheUnbound if there is no locals at all

omxrzoskYaroslav Bolyukin2026-03-23parent: #a47ce2d.patch.diff
in: master

1 file changed

modifiedcrates/jrsonnet-evaluator/src/evaluate/mod.rsdiffbeforeafterboth
282 Ok(())282 Ok(())
283}283}
284
285#[derive(Trace, Clone)]
286struct DirectUnbound(Context);
287impl Unbound for DirectUnbound {
288 type Bound = Context;
289 fn bind(&self, sup_this: SupThis) -> Result<Context> {
290 Ok(self
291 .0
292 .clone()
293 .extend_bindings_sup_this(FxHashMap::new(), sup_this))
294 }
295}
284296
285#[allow(clippy::too_many_lines)]297#[allow(clippy::too_many_lines)]
286pub fn evaluate_member_list_object(298pub fn evaluate_member_list_object(
287 super_obj: Option<ObjValue>,299 super_obj: Option<ObjValue>,
288 ctx: Context,300 ctx: Context,
289 members: &ObjMembers,301 members: &ObjMembers,
290) -> Result<ObjValue> {302) -> Result<ObjValue> {
303 #[derive(Trace)]
304 struct ObjectAssert<B: Trace> {
305 uctx: B,
306 asserts: Rc<Vec<AssertStmt>>,
307 }
308 impl<B: Unbound<Bound = Context>> ObjectAssertion for ObjectAssert<B> {
309 fn run(&self, sup_this: SupThis) -> Result<()> {
310 let ctx = self.uctx.bind(sup_this)?;
311 for assert in &*self.asserts {
312 evaluate_assert(ctx.clone(), assert)?;
313 }
314 Ok(())
315 }
316 }
317
291 let mut builder = ObjValueBuilder::new();318 let mut builder = ObjValueBuilder::new();
292 if let Some(super_obj) = super_obj {319 if let Some(super_obj) = super_obj {
293 builder.with_super(super_obj);320 builder.with_super(super_obj);
294 }321 }
295322
296 let locals = members.locals.clone();323 if members.locals.is_empty() {
297324 // We can use the same context for all field evaluation, it doesn't depends on locals, only on this/super
298 // We have single context for all fields, so we can cache binds
299 let uctx = CachedUnbound::new(evaluate_object_locals(ctx.clone(), locals));325 let uctx = DirectUnbound(ctx.clone());
300
301 for field in &members.fields {326 for field in &members.fields {
302 evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), field)?;327 evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), field)?;
303 }328 }
304
305 if !members.asserts.is_empty() {329 if !members.asserts.is_empty() {
306 #[derive(Trace)]330 builder.assert(ObjectAssert {
307 struct ObjectAssert<B: Trace> {331 uctx,
332 asserts: members.asserts.clone(),
333 });
334 }
335 } else {
336 let locals = members.locals.clone();
337 // We have single context for all fields, so we can cache them together
308 uctx: B,338 let uctx = CachedUnbound::new(evaluate_object_locals(ctx.clone(), locals));
309 asserts: Rc<Vec<AssertStmt>>,
310 }
311 impl<B: Unbound<Bound = Context>> ObjectAssertion for ObjectAssert<B> {339 for field in &members.fields {
312 fn run(&self, sup_this: SupThis) -> Result<()> {340 evaluate_field_member(&mut builder, ctx.clone(), uctx.clone(), field)?;
313 let ctx = self.uctx.bind(sup_this)?;
314 for assert in &*self.asserts {
315 evaluate_assert(ctx.clone(), assert)?;
316 }
317 Ok(())
318 }
319 }341 }
342 if !members.asserts.is_empty() {
320 builder.assert(ObjectAssert {343 builder.assert(ObjectAssert {
321 uctx,344 uctx,
322 asserts: members.asserts.clone(),345 asserts: members.asserts.clone(),
323 });346 });
347 }
324 }348 }
325349
326 Ok(builder.build())350 Ok(builder.build())