Skip to content

Commit 2adf5e9

Browse files
committed
internal/core/adt: ensure emptyNode is inert
Currently, emptyNode is sometimes passed to operations that request its nodeContext. Because it was not marked as finalized, this would cause a nodeContext to be created. This nodeContext would then be initialized for a certain version. We now set the global to be "finalized" and add tests to verify this. Fixes #3985 Signed-off-by: Marcel van Lohuizen <[email protected]> Change-Id: I73313f1ea0af4c7d2032f1166556908871e1beb5 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1217744 Unity-Result: CUE porcuepine <[email protected]> Reviewed-by: Daniel Martí <[email protected]> Reviewed-by: Roger Peppe <[email protected]> TryBot-Result: CUEcueckoo <[email protected]>
1 parent b8a14de commit 2adf5e9

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

cue/testdata/benchmarks/issue2176.txtar

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,13 @@ output: {
5858
"2": (datastream & {marker: length: 14}).marker.position
5959
}
6060
-- out/evalalpha/stats --
61-
Leaks: 449
61+
Leaks: 448
6262
Freed: 0
6363
Reused: 0
64-
Allocs: 449
64+
Allocs: 448
6565
Retain: 0
6666

67-
Unifications: 377
67+
Unifications: 376
6868
Conjuncts: 1333
6969
Disjuncts: 8
7070

@@ -87,13 +87,13 @@ diff old new
8787
-
8888
-CloseIDElems: 0
8989
-NumCloseIDs: 12
90-
+Leaks: 449
90+
+Leaks: 448
9191
+Freed: 0
9292
+Reused: 0
93-
+Allocs: 449
93+
+Allocs: 448
9494
+Retain: 0
9595
+
96-
+Unifications: 377
96+
+Unifications: 376
9797
+Conjuncts: 1333
9898
+Disjuncts: 8
9999
+

internal/core/adt/adt_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2025 CUE Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package adt
16+
17+
import (
18+
"testing"
19+
)
20+
21+
// TestEmptyNodeInert checks that getting a node for an empty struct does not
22+
// cause a nodeContext to be created.
23+
func TestEmptyNodeInert(t *testing.T) {
24+
// We run the evaluator twice with different versions of the evaluator. Each
25+
// results in the use of emptyNode. Ensure that the it does not get
26+
// assigned a nodeContext.
27+
28+
ctx := &OpContext{}
29+
30+
s := emptyNode.getBareState(ctx)
31+
if s != nil {
32+
t.Fatal("expected nil state for empty struct")
33+
}
34+
}

internal/core/adt/context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1091,7 +1091,7 @@ func (c *OpContext) typeErrorAs(v Value, k Kind, as interface{}) {
10911091
}
10921092
}
10931093

1094-
var emptyNode = &Vertex{}
1094+
var emptyNode = &Vertex{status: finalized}
10951095

10961096
func pos(x Node) token.Pos {
10971097
if x.Source() == nil {

internal/core/adt/eval_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,15 @@ func runEvalTest(t *cuetxtar.Test, version internal.EvaluatorVersion, flags cued
195195
return
196196
}
197197

198+
func TestIssue3985(t *testing.T) {
199+
// We run the evaluator twice with different versions of the evaluator. Each
200+
// results in the use of emptyNode. Ensure that the it does not get
201+
// assigned a nodeContext.
202+
cuecontext.New(cuecontext.EvaluatorVersion(cuecontext.EvalV3)).CompileString(`a!: _, b: [for c in a if a != _|_ {}]`)
203+
204+
cuecontext.New(cuecontext.EvaluatorVersion(cuecontext.EvalV2)).CompileString(`matchN(0, [_|_]) & []`)
205+
}
206+
198207
// TestX is for debugging. Do not delete.
199208
func TestX(t *testing.T) {
200209
adt.DebugDeps = true

0 commit comments

Comments
 (0)