-
Notifications
You must be signed in to change notification settings - Fork 68
Fix multiple object comprehension bugs #358
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
05ed13c
280b679
2b76aeb
64edef1
ee94db1
7a281cb
856c193
3239399
1c51f11
55bcb26
fd038d8
b74a493
fd3e9f4
cb5593e
bd4e1b2
f5e40c2
4867920
63cad73
7df617e
e06e7a7
5cd4ed8
0b2fce2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -841,42 +841,40 @@ class Evaluator( | |||||||||||||||||||
| def visitObjComp(e: ObjBody.ObjComp, sup: Val.Obj)(implicit scope: ValScope): Val.Obj = { | ||||||||||||||||||||
| val binds = e.preLocals ++ e.postLocals | ||||||||||||||||||||
| val compScope: ValScope = scope // .clearSuper | ||||||||||||||||||||
|
|
||||||||||||||||||||
| lazy val newSelf: Val.Obj = { | ||||||||||||||||||||
| val builder = new java.util.LinkedHashMap[String, Val.Obj.Member] | ||||||||||||||||||||
| for (s <- visitComp(e.first :: e.rest, Array(compScope))) { | ||||||||||||||||||||
| lazy val newScope: ValScope = s.extend(newBindings, newSelf, null) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| lazy val newBindings = visitBindings(binds, (self, sup) => newScope) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| visitExpr(e.key)(s) match { | ||||||||||||||||||||
| case Val.Str(_, k) => | ||||||||||||||||||||
| val prev_length = builder.size() | ||||||||||||||||||||
| builder.put( | ||||||||||||||||||||
| k, | ||||||||||||||||||||
| new Val.Obj.Member(e.plus, Visibility.Normal) { | ||||||||||||||||||||
| def invoke(self: Val.Obj, sup: Val.Obj, fs: FileScope, ev: EvalScope): Val = | ||||||||||||||||||||
| visitExpr(e.value)( | ||||||||||||||||||||
| s.extend(newBindings, self, null) | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| val builder = new java.util.LinkedHashMap[String, Val.Obj.Member] | ||||||||||||||||||||
| for (s <- visitComp(e.first :: e.rest, Array(compScope))) { | ||||||||||||||||||||
| visitExpr(e.key)(s) match { | ||||||||||||||||||||
| case Val.Str(_, k) => | ||||||||||||||||||||
| val prev_length = builder.size() | ||||||||||||||||||||
| builder.put( | ||||||||||||||||||||
| k, | ||||||||||||||||||||
| new Val.Obj.Member(e.plus, Visibility.Normal) { | ||||||||||||||||||||
| def invoke(self: Val.Obj, sup: Val.Obj, fs: FileScope, ev: EvalScope): Val = { | ||||||||||||||||||||
| lazy val newScope: ValScope = s.extend(newBindings, self, sup) | ||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are two changes here:
|
||||||||||||||||||||
| lazy val newBindings = visitBindings(binds, (self, sup) => newScope) | ||||||||||||||||||||
| visitExpr(e.value)( | ||||||||||||||||||||
| s.extend(newBindings, self, null) | ||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On closer look, I see that this is still passing
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||||||||||||
| ) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| if (prev_length == builder.size() && settings.noDuplicateKeysInComprehension) { | ||||||||||||||||||||
| Error.fail(s"Duplicate key ${k} in evaluated object comprehension.", e.pos); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| case Val.Null(_) => // do nothing | ||||||||||||||||||||
| case _ => | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
| val valueCache = if (sup == null) { | ||||||||||||||||||||
| Val.Obj.getEmptyValueCacheForObjWithoutSuper(builder.size()) | ||||||||||||||||||||
| } else { | ||||||||||||||||||||
| new java.util.HashMap[Any, Val]() | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| if (prev_length == builder.size() && settings.noDuplicateKeysInComprehension) { | ||||||||||||||||||||
| Error.fail(s"Duplicate key ${k} in evaluated object comprehension.", e.pos); | ||||||||||||||||||||
| } | ||||||||||||||||||||
| case Val.Null(_) => // do nothing | ||||||||||||||||||||
| case x => | ||||||||||||||||||||
| Error.fail( | ||||||||||||||||||||
| s"Field name must be string or null, not ${x.prettyName}", | ||||||||||||||||||||
| e.pos | ||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I copied this wording from sjsonnet/sjsonnet/src/sjsonnet/Evaluator.scala Lines 683 to 687 in 84ac320
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I factored this out in bd4e1b2 but, curiously, this appears to cause a test failure in the JDK 17 build: https://github.com/databricks/sjsonnet/actions/runs/14891478275/job/41824335648 : I think the problem is that we have code within the sjsonnet/sjsonnet/src/sjsonnet/Materializer.scala Lines 70 to 73 in 84ac320
I tried adding an This preexisting design seems very fragile. If we want to more fundamentally fix this and remove the core fragility, I think we probably need to allow the Given this, I'm going to back out of the error message DRY and will re-attempt it in a separate PR.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I think this might just be nondeterministically broken because the current reverted commit fails but its checkout tree is identical to a commit which passed two days ago.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that this is a test ordering issue: the current test for the stack overflow handling fails if it runs prior to other tests: it was implicitly relying on other tests to perform certain loading and initialization steps. We should fix this properly (e.g. by hardening the actual implementation, as this is a real bug), but as a temporary "unblock the test flakiness" hack I'm trying to force a particular loading step: 5cd4ed8
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||
| ) | ||||||||||||||||||||
| } | ||||||||||||||||||||
| new Val.Obj(e.pos, builder, false, null, sup, valueCache) | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| newSelf | ||||||||||||||||||||
| val valueCache = if (sup == null) { | ||||||||||||||||||||
| Val.Obj.getEmptyValueCacheForObjWithoutSuper(builder.size()) | ||||||||||||||||||||
| } else { | ||||||||||||||||||||
| new java.util.HashMap[Any, Val]() | ||||||||||||||||||||
| } | ||||||||||||||||||||
| new Val.Obj(e.pos, builder, false, null, sup, valueCache) | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| @tailrec | ||||||||||||||||||||
|
|
||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.