internal/core: move CloseID from Environment to Conjunct

Change-Id: If83db9714764e30c764c8947cfb3936beafd8bc5
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/7001
Reviewed-by: Marcel van Lohuizen <mpvl@golang.org>
Reviewed-by: CUE cueckoo <cueckoo@gmail.com>
diff --git a/cue/go.go b/cue/go.go
index 28399d9..1d6717c 100644
--- a/cue/go.go
+++ b/cue/go.go
@@ -38,7 +38,7 @@
 			expr = &adt.Bottom{Err: err}
 		}
 		n := &adt.Vertex{}
-		n.AddConjunct(adt.MakeConjunct(nil, expr))
+		n.AddConjunct(adt.MakeRootConjunct(nil, expr))
 		return Value{r.idx, n}
 
 		// return convertType(runtime.(*Runtime), x)
diff --git a/cue/instance.go b/cue/instance.go
index 5b954ea..7eb1958 100644
--- a/cue/instance.go
+++ b/cue/instance.go
@@ -75,7 +75,7 @@
 		st, ok := x.(*adt.Vertex)
 		if !ok {
 			st = &adt.Vertex{}
-			st.AddConjunct(adt.MakeConjunct(nil, x))
+			st.AddConjunct(adt.MakeRootConjunct(nil, x))
 		}
 		return v.ctx().index.addInst(&Instance{
 			root: st,
@@ -231,7 +231,7 @@
 
 	for _, i := range inst {
 		w := i.Value()
-		v.AddConjunct(adt.MakeConjunct(nil, w.v.ToDataAll()))
+		v.AddConjunct(adt.MakeRootConjunct(nil, w.v.ToDataAll()))
 	}
 	v.Finalize(ctx)
 
@@ -255,7 +255,7 @@
 
 	v, err := compile.Files(&compile.Config{Scope: inst.root}, r, p.Files...)
 
-	v.AddConjunct(adt.MakeConjunct(nil, inst.root))
+	v.AddConjunct(adt.MakeRootConjunct(nil, inst.root))
 
 	i := newInstance(idx, p, v)
 	if rErr != nil {
@@ -345,7 +345,7 @@
 	} else {
 		ctx := eval.NewContext(inst.index.Runtime, nil)
 		expr := convert.GoValueToExpr(ctx, true, x)
-		u.AddConjunct(adt.MakeConjunct(nil, expr))
+		u.AddConjunct(adt.MakeRootConjunct(nil, expr))
 		u.Finalize(ctx)
 	}
 	inst = inst.index.addInst(&Instance{
diff --git a/cue/types.go b/cue/types.go
index 2981a84..0848bbb 100644
--- a/cue/types.go
+++ b/cue/types.go
@@ -570,7 +570,7 @@
 		node.Parent = v.v.Parent
 	}
 	node.UpdateStatus(adt.Finalized)
-	node.AddConjunct(adt.MakeConjunct(nil, b))
+	node.AddConjunct(adt.MakeRootConjunct(nil, b))
 	return makeValue(v.idx, node)
 }
 
@@ -590,7 +590,7 @@
 		return newVertexRoot(ctx, n)
 	}
 	node := &adt.Vertex{}
-	node.AddConjunct(adt.MakeConjunct(nil, x))
+	node.AddConjunct(adt.MakeRootConjunct(nil, x))
 	return newVertexRoot(ctx, node)
 }
 
@@ -648,7 +648,7 @@
 		return Value{base.idx, v}
 	}
 	n := &adt.Vertex{Parent: base.v.Parent, Label: base.v.Label}
-	n.AddConjunct(adt.MakeConjunct(env, v))
+	n.AddConjunct(adt.MakeRootConjunct(env, v))
 	n = base.ctx().manifest(n)
 	return makeValue(base.idx, n)
 }
@@ -1556,7 +1556,7 @@
 	n, _ := value.(*adt.Vertex)
 	if n == nil {
 		n = &adt.Vertex{Label: v.v.Label, Parent: v.v.Parent}
-		n.AddConjunct(adt.MakeConjunct(nil, value))
+		n.AddConjunct(adt.MakeRootConjunct(nil, value))
 	} else {
 		n.Label = v.v.Label
 	}
@@ -1653,8 +1653,8 @@
 		return v
 	}
 	n := &adt.Vertex{Parent: v.v.Parent, Label: v.v.Label}
-	n.AddConjunct(adt.MakeConjunct(nil, v.v))
-	n.AddConjunct(adt.MakeConjunct(nil, w.v))
+	n.AddConjunct(adt.MakeRootConjunct(nil, v.v))
+	n.AddConjunct(adt.MakeRootConjunct(nil, w.v))
 
 	ctx := v.idx.newContext()
 	n.Finalize(ctx.opCtx)
@@ -1675,8 +1675,8 @@
 	}
 
 	n := &adt.Vertex{Parent: v.v.Parent, Label: v.v.Label}
-	n.AddConjunct(adt.MakeConjunct(nil, v.v))
-	n.AddConjunct(adt.MakeConjunct(nil, w.v))
+	n.AddConjunct(adt.MakeRootConjunct(nil, v.v))
+	n.AddConjunct(adt.MakeRootConjunct(nil, w.v))
 
 	e := eval.New(v.idx.Runtime)
 	ctx := e.NewContext(n)
@@ -2166,8 +2166,8 @@
 						Closed: v.v.Closed,
 					}
 					b := a
-					a.AddConjunct(adt.MakeConjunct(env, n.Val))
-					b.AddConjunct(adt.MakeConjunct(env, disjunct.Val))
+					a.AddConjunct(adt.MakeRootConjunct(env, n.Val))
+					b.AddConjunct(adt.MakeRootConjunct(env, disjunct.Val))
 
 					e := eval.New(v.idx.Runtime)
 					ctx := e.NewContext(nil)
@@ -2246,7 +2246,7 @@
 				n := &adt.Vertex{
 					Parent: v.v.Parent,
 					Label:  v.v.Label}
-				c := adt.MakeConjunct(envEmbed, x)
+				c := adt.MakeRootConjunct(envEmbed, x)
 				n.AddConjunct(c)
 				n.Finalize(ctx)
 				a = append(a, makeValue(v.idx, n))
@@ -2265,7 +2265,7 @@
 				Parent: v.v.Parent,
 				Label:  v.v.Label,
 			}
-			c := adt.MakeConjunct(env, &adt.StructLit{
+			c := adt.MakeRootConjunct(env, &adt.StructLit{
 				Decls: fields,
 			})
 			n.AddConjunct(c)
diff --git a/internal/core/adt/composite.go b/internal/core/adt/composite.go
index 999d4d8..3cbbbd1 100644
--- a/internal/core/adt/composite.go
+++ b/internal/core/adt/composite.go
@@ -91,10 +91,6 @@
 	// TODO(perf): make the following public fields a shareable struct as it
 	// mostly is going to be the same for child nodes.
 
-	// CloseID is a unique number that tracks a group of conjuncts that need
-	// belong to a single originating definition.
-	CloseID uint32
-
 	// Cyclic indicates a structural cycle was detected for this conjunct or one
 	// of its ancestors.
 	Cyclic bool
@@ -129,6 +125,8 @@
 	cache map[Expr]Value
 }
 
+type ID int32
+
 // evalCached is used to look up let expressions. Caching let expressions
 // prevents a possible combinatorial explosion.
 func (e *Environment) evalCached(c *OpContext, x Expr) Value {
@@ -337,7 +335,7 @@
 			status: Finalized,
 			Value:  x,
 		}
-		n.AddConjunct(MakeConjunct(nil, v))
+		n.AddConjunct(MakeRootConjunct(nil, v))
 		return n
 	}
 }
@@ -557,13 +555,25 @@
 type Conjunct struct {
 	Env *Environment
 	x   Node
+
+	// CloseID is a unique number that tracks a group of conjuncts that need
+	// belong to a single originating definition.
+	CloseID ID
+}
+
+func (c *Conjunct) ID() ID {
+	return c.CloseID
 }
 
 // TODO(perf): replace with composite literal if this helps performance.
 
-// MakeConjunct creates a conjunct from the given environment and node.
+// MakeRootConjunct creates a conjunct from the given environment and node.
 // It panics if x cannot be used as an expression.
-func MakeConjunct(env *Environment, x Node) Conjunct {
+func MakeRootConjunct(env *Environment, x Node) Conjunct {
+	return MakeConjunct(env, x, 0)
+}
+
+func MakeConjunct(env *Environment, x Node, id ID) Conjunct {
 	if env == nil {
 		// TODO: better is to pass one.
 		env = &Environment{}
@@ -573,7 +583,7 @@
 	default:
 		panic(fmt.Sprintf("invalid Node type %T", x))
 	}
-	return Conjunct{env, x}
+	return Conjunct{env, x, id}
 }
 
 func (c *Conjunct) Source() ast.Node {
diff --git a/internal/core/adt/context.go b/internal/core/adt/context.go
index 9a36cc1..7cb2aa0 100644
--- a/internal/core/adt/context.go
+++ b/internal/core/adt/context.go
@@ -160,9 +160,6 @@
 	sub := *c
 	node.Parent = c.e.Vertex
 	sub.e = &Environment{Up: c.e, Vertex: node}
-	if c.e != nil {
-		sub.e.CloseID = c.e.CloseID
-	}
 	return &sub
 }
 
@@ -290,9 +287,7 @@
 	if src != nil {
 		c.src = src
 	}
-	if env != nil {
-		c.e = env
-	}
+	c.e = env
 
 	return saved
 }
diff --git a/internal/core/adt/default.go b/internal/core/adt/default.go
index 2dd1ff7..fc922bd 100644
--- a/internal/core/adt/default.go
+++ b/internal/core/adt/default.go
@@ -69,7 +69,7 @@
 		for _, c := range v.Conjuncts {
 			// TODO: preserve field information.
 			expr, _ := stripNonDefaults(c.Expr())
-			w.Conjuncts = append(w.Conjuncts, MakeConjunct(c.Env, expr))
+			w.Conjuncts = append(w.Conjuncts, MakeRootConjunct(c.Env, expr))
 		}
 		return w
 
diff --git a/internal/core/adt/expr.go b/internal/core/adt/expr.go
index 8fbdcec..4b53894 100644
--- a/internal/core/adt/expr.go
+++ b/internal/core/adt/expr.go
@@ -40,7 +40,7 @@
 
 func (x *StructLit) evaluate(c *OpContext) Value {
 	e := c.Env(0)
-	v := &Vertex{Conjuncts: []Conjunct{{e, x}}}
+	v := &Vertex{Conjuncts: []Conjunct{{e, x, 0}}}
 	c.Unifier.Unify(c, v, Finalized) // TODO: also partial okay?
 	return v
 }
@@ -168,7 +168,7 @@
 
 func (x *ListLit) evaluate(c *OpContext) Value {
 	e := c.Env(0)
-	v := &Vertex{Conjuncts: []Conjunct{{e, x}}}
+	v := &Vertex{Conjuncts: []Conjunct{{e, x, 0}}}
 	c.Unifier.Unify(c, v, Finalized) // TODO: also partial okay?
 	return v
 }
@@ -547,7 +547,7 @@
 	e := c.Env(x.UpCount)
 	label := e.Vertex.Label
 	// Anonymous arc.
-	return &Vertex{Parent: nil, Label: label, Conjuncts: []Conjunct{{e, x.X}}}
+	return &Vertex{Parent: nil, Label: label, Conjuncts: []Conjunct{{e, x.X, 0}}}
 }
 
 func (x *LetReference) evaluate(c *OpContext) Value {
@@ -822,7 +822,7 @@
 	env := c.Env(0)
 	if x.Op == AndOp {
 		// Anonymous Arc
-		v := Vertex{Conjuncts: []Conjunct{{env, x}}}
+		v := Vertex{Conjuncts: []Conjunct{{env, x, 0}}}
 		return c.Unifier.Evaluate(c, &v)
 	}
 
@@ -1094,7 +1094,7 @@
 
 func (x *DisjunctionExpr) evaluate(c *OpContext) Value {
 	e := c.Env(0)
-	v := &Vertex{Conjuncts: []Conjunct{{e, x}}}
+	v := &Vertex{Conjuncts: []Conjunct{{e, x, 0}}}
 	c.Unifier.Unify(c, v, Finalized) // TODO: also partial okay?
 	// TODO: if the disjunction result originated from a literal value, we may
 	// consider the result closed to create more permanent errors.
@@ -1178,7 +1178,7 @@
 		if x.Key != 0 {
 			v := &Vertex{Label: x.Key}
 			key := a.Label.ToValue(c)
-			v.AddConjunct(MakeConjunct(c.Env(0), key))
+			v.AddConjunct(MakeRootConjunct(c.Env(0), key))
 			v.SetValue(c, Finalized, key)
 			n.Arcs = append(n.Arcs, v)
 		}
@@ -1234,7 +1234,7 @@
 
 func (x *LetClause) yield(c *OpContext, f YieldFunc) {
 	n := &Vertex{Arcs: []*Vertex{
-		{Label: x.Label, Conjuncts: []Conjunct{{c.Env(0), x.Expr}}},
+		{Label: x.Label, Conjuncts: []Conjunct{{c.Env(0), x.Expr, 0}}},
 	}}
 	x.Dst.yield(c.spawn(n), f)
 }
diff --git a/internal/core/compile/builtin.go b/internal/core/compile/builtin.go
index 8934019..75972dc 100644
--- a/internal/core/compile/builtin.go
+++ b/internal/core/compile/builtin.go
@@ -128,7 +128,7 @@
 		}
 		v := &adt.Vertex{}
 		// TODO: make a Disjunction.
-		v.AddConjunct(adt.MakeConjunct(nil,
+		v.AddConjunct(adt.MakeRootConjunct(nil,
 			&adt.DisjunctionExpr{Values: d, HasDefaults: false},
 		))
 		c.Unify(c, v, adt.Finalized)
diff --git a/internal/core/compile/compile.go b/internal/core/compile/compile.go
index dbb556a..eab01fd 100644
--- a/internal/core/compile/compile.go
+++ b/internal/core/compile/compile.go
@@ -241,7 +241,7 @@
 		c.pushScope(nil, 0, file) // File scope
 		v := &adt.StructLit{Src: file}
 		c.addDecls(v, file.Decls)
-		res.Conjuncts = append(res.Conjuncts, adt.MakeConjunct(nil, v))
+		res.Conjuncts = append(res.Conjuncts, adt.MakeRootConjunct(nil, v))
 		c.popScope()
 	}
 
@@ -278,7 +278,7 @@
 		// env = e
 	}
 
-	return adt.MakeConjunct(env, expr)
+	return adt.MakeRootConjunct(env, expr)
 }
 
 // resolve assumes that all existing resolutions are legal. Validation should
diff --git a/internal/core/convert/go.go b/internal/core/convert/go.go
index 067321d..2a4173b 100644
--- a/internal/core/convert/go.go
+++ b/internal/core/convert/go.go
@@ -63,7 +63,7 @@
 		return v
 	}
 	obj := &adt.Vertex{}
-	obj.AddConjunct(adt.MakeConjunct(nil, e))
+	obj.AddConjunct(adt.MakeRootConjunct(nil, e))
 	return obj
 }
 
@@ -400,7 +400,7 @@
 		case reflect.Struct:
 			obj := &adt.StructLit{Src: src}
 			v := &adt.Vertex{}
-			v.AddConjunct(adt.MakeConjunct(nil, obj))
+			v.AddConjunct(adt.MakeRootConjunct(nil, obj))
 			v.SetValue(ctx, adt.Finalized, &adt.StructMarker{})
 
 			t := value.Type()
@@ -441,7 +441,7 @@
 					arc.Label = f
 				} else {
 					arc = &adt.Vertex{Label: f, Value: sub}
-					arc.AddConjunct(adt.MakeConjunct(nil, sub))
+					arc.AddConjunct(adt.MakeRootConjunct(nil, sub))
 				}
 				v.Arcs = append(v.Arcs, arc)
 			}
@@ -451,7 +451,7 @@
 		case reflect.Map:
 			obj := &adt.StructLit{Src: src}
 			v := &adt.Vertex{Value: &adt.StructMarker{}}
-			v.AddConjunct(adt.MakeConjunct(nil, obj))
+			v.AddConjunct(adt.MakeRootConjunct(nil, obj))
 			v.SetValue(ctx, adt.Finalized, &adt.StructMarker{})
 
 			t := value.Type()
@@ -492,7 +492,7 @@
 						arc.Label = f
 					} else {
 						arc = &adt.Vertex{Label: f, Value: sub}
-						arc.AddConjunct(adt.MakeConjunct(nil, sub))
+						arc.AddConjunct(adt.MakeRootConjunct(nil, sub))
 					}
 					v.Arcs = append(v.Arcs, arc)
 				}
diff --git a/internal/core/eval/closed.go b/internal/core/eval/closed.go
index 56a0d7f..175b08d 100644
--- a/internal/core/eval/closed.go
+++ b/internal/core/eval/closed.go
@@ -143,7 +143,7 @@
 // any value.
 type CloseDef struct {
 	Src   adt.Node // for error reporting
-	ID    uint32
+	ID    adt.ID
 	IsAnd bool
 	List  []*CloseDef
 }
@@ -161,7 +161,7 @@
 // a CloseDef tree based on replacement information gathered during evaluation
 // of this flat list.
 //
-func updateClosed(c *CloseDef, replace map[uint32]*CloseDef) *CloseDef { // used in eval.go
+func updateClosed(c *CloseDef, replace map[adt.ID]*CloseDef) *CloseDef { // used in eval.go
 	// Insert an entry for CloseID 0 if we are about to replace it. By default
 	// 0, which is the majority case, is omitted.
 	if c != nil && replace[0] != nil && !containsClosed(c, 0) {
@@ -190,7 +190,7 @@
 	return c
 }
 
-func updateClosedRec(c *CloseDef, replace map[uint32]*CloseDef) *CloseDef {
+func updateClosedRec(c *CloseDef, replace map[adt.ID]*CloseDef) *CloseDef {
 	if c == nil {
 		return nil
 	}
@@ -239,18 +239,13 @@
 
 // UpdateReplace is called after evaluating a conjunct at the top of the arc
 // to update the replacement information with the gathered CloseDef info.
-func (n *nodeContext) updateReplace(env *adt.Environment) { // used in eval.go
+func (n *nodeContext) updateReplace(id adt.ID) { // used in eval.go
 	if n.newClose == nil {
 		return
 	}
 
 	if n.replace == nil {
-		n.replace = make(map[uint32]*CloseDef)
-	}
-
-	id := uint32(0)
-	if env != nil {
-		id = env.CloseID
+		n.replace = make(map[adt.ID]*CloseDef)
 	}
 
 	n.replace[id] = updateClose(n.replace[id], n.newClose)
@@ -310,7 +305,7 @@
 	}
 }
 
-func (n *nodeContext) addOr(parentID uint32, c *CloseDef) { // used in eval.go
+func (n *nodeContext) addOr(parentID adt.ID, c *CloseDef) { // used in eval.go
 	switch {
 	case n.newClose == nil:
 		d := &CloseDef{ID: parentID, List: []*CloseDef{{ID: parentID}}}
@@ -337,6 +332,7 @@
 	// more clever and only generate this when it is a user error.
 	filter := f.IsString() || f == adt.InvalidLabel
 	if filter && !n.verifyArcRecursive(ctx, n.tree, f) {
+		collectPositions(ctx, n.tree)
 		label := f.SelectorString(ctx)
 		return ctx.NewErrf("field `%s` not allowed", label)
 	}
@@ -365,9 +361,9 @@
 
 // verifyDefinition reports whether f is a valid member for any of the fieldSets
 // with the same closeID.
-func (n *acceptor) verifyDefinition(ctx *adt.OpContext, closeID uint32, f adt.Feature) (ok bool) {
+func (n *acceptor) verifyDefinition(ctx *adt.OpContext, closeID adt.ID, f adt.Feature) (ok bool) {
 	for _, o := range n.fields {
-		if o.env.CloseID != closeID {
+		if o.id != closeID {
 			continue
 		}
 
@@ -387,7 +383,6 @@
 			}
 		}
 	}
-	collectPositions(ctx, n.tree)
 	for _, o := range n.fields {
 		if o.pos != nil {
 			ctx.AddPosition(o.pos)
@@ -407,7 +402,7 @@
 
 // containsClosed reports whether c contains any CloseDef with ID x,
 // recursively.
-func containsClosed(c *CloseDef, x uint32) bool {
+func containsClosed(c *CloseDef, x adt.ID) bool {
 	if c.ID == x && !c.IsAnd {
 		return true
 	}
diff --git a/internal/core/eval/closed_test.go b/internal/core/eval/closed_test.go
index c0ed278..45511f6 100644
--- a/internal/core/eval/closed_test.go
+++ b/internal/core/eval/closed_test.go
@@ -17,6 +17,7 @@
 import (
 	"testing"
 
+	"cuelang.org/go/internal/core/adt"
 	"github.com/google/go-cmp/cmp"
 )
 
@@ -24,12 +25,12 @@
 	testCases := []struct {
 		desc    string
 		close   *CloseDef
-		replace map[uint32]*CloseDef
+		replace map[adt.ID]*CloseDef
 		want    *CloseDef
 	}{{
 		desc:  "introduce new",
 		close: nil,
-		replace: map[uint32]*CloseDef{
+		replace: map[adt.ID]*CloseDef{
 			0: {ID: 2, IsAnd: false, List: nil},
 		},
 		want: &CloseDef{
@@ -40,7 +41,7 @@
 		close: &CloseDef{
 			ID: 1,
 		},
-		replace: map[uint32]*CloseDef{
+		replace: map[adt.ID]*CloseDef{
 			0: {ID: 2, IsAnd: false, List: nil},
 			1: nil, // keep 1
 		},
@@ -53,7 +54,7 @@
 		close: &CloseDef{
 			ID: 1,
 		},
-		replace: map[uint32]*CloseDef{
+		replace: map[adt.ID]*CloseDef{
 			1: {ID: 1, IsAnd: true, List: []*CloseDef{{ID: 2}, {ID: 3}}},
 		},
 		want: &CloseDef{
@@ -66,7 +67,7 @@
 		close: &CloseDef{
 			ID: 1,
 		},
-		replace: map[uint32]*CloseDef{
+		replace: map[adt.ID]*CloseDef{
 			0: nil,
 		},
 		want: nil,
@@ -80,7 +81,7 @@
 				{ID: 3},
 			},
 		},
-		replace: map[uint32]*CloseDef{2: nil},
+		replace: map[adt.ID]*CloseDef{2: nil},
 		want:    &CloseDef{ID: 2},
 	}, {
 		desc: "eliminateAllEmbeddings",
@@ -91,7 +92,7 @@
 				{ID: 3},
 			},
 		},
-		replace: map[uint32]*CloseDef{0: {ID: 4}, 4: nil},
+		replace: map[adt.ID]*CloseDef{0: {ID: 4}, 4: nil},
 		want:    &CloseDef{ID: 4},
 	}, {
 		// Do not eliminate an embedding that has a replacement.
@@ -103,7 +104,7 @@
 				{ID: 3},
 			},
 		},
-		replace: map[uint32]*CloseDef{
+		replace: map[adt.ID]*CloseDef{
 			2: nil,
 			3: {ID: 3, IsAnd: true, List: []*CloseDef{{ID: 4}, {ID: 5}}},
 		},
@@ -134,7 +135,7 @@
 				{ID: 0},
 			},
 		},
-		replace: map[uint32]*CloseDef{0: {ID: 3}},
+		replace: map[adt.ID]*CloseDef{0: {ID: 3}},
 		want:    &CloseDef{ID: 3},
 	}, {
 		// Select b within a
@@ -156,7 +157,7 @@
 				{ID: 0},
 			},
 		},
-		replace: map[uint32]*CloseDef{
+		replace: map[adt.ID]*CloseDef{
 			0: {IsAnd: true, List: []*CloseDef{{ID: 3}, {ID: 4}}},
 		},
 		want: &CloseDef{
diff --git a/internal/core/eval/disjunct.go b/internal/core/eval/disjunct.go
index 27c479d..6028093 100644
--- a/internal/core/eval/disjunct.go
+++ b/internal/core/eval/disjunct.go
@@ -87,7 +87,7 @@
 	env         *adt.Environment
 	values      []disjunct
 	numDefaults int
-	cloneID     uint32
+	cloneID     adt.ID
 	isEmbed     bool
 }
 
@@ -96,7 +96,7 @@
 	isDefault bool
 }
 
-func (n *nodeContext) addDisjunction(env *adt.Environment, x *adt.DisjunctionExpr, cloneID uint32, isEmbed bool) {
+func (n *nodeContext) addDisjunction(env *adt.Environment, x *adt.DisjunctionExpr, cloneID adt.ID, isEmbed bool) {
 	a := []disjunct{}
 
 	numDefaults := 0
@@ -116,7 +116,7 @@
 		envDisjunct{env, a, numDefaults, cloneID, isEmbed})
 }
 
-func (n *nodeContext) addDisjunctionValue(env *adt.Environment, x *adt.Disjunction, cloneID uint32, isEmbed bool) {
+func (n *nodeContext) addDisjunctionValue(env *adt.Environment, x *adt.Disjunction, cloneID adt.ID, isEmbed bool) {
 	a := []disjunct{}
 
 	for i, v := range x.Values {
@@ -297,8 +297,8 @@
 	k := n.stack[p]
 	v := d.values[k]
 	n.isFinal = n.isFinal && k == len(d.values)-1
-	c := adt.MakeConjunct(d.env, v.expr)
-	n.addExprConjunct(c, d.cloneID, d.isEmbed)
+	c := adt.MakeConjunct(d.env, v.expr, d.cloneID)
+	n.addExprConjunct(c, d.isEmbed)
 
 	for n.expandOne() {
 	}
diff --git a/internal/core/eval/eval.go b/internal/core/eval/eval.go
index 647d4b8..bc5a477 100644
--- a/internal/core/eval/eval.go
+++ b/internal/core/eval/eval.go
@@ -112,12 +112,12 @@
 type Evaluator struct {
 	r       adt.Runtime
 	index   adt.StringIndexer
-	closeID uint32
+	closeID adt.ID
 
 	stats Stats
 }
 
-func (e *Evaluator) nextID() uint32 {
+func (e *Evaluator) nextID() adt.ID {
 	e.closeID++
 	return e.closeID
 }
@@ -363,16 +363,10 @@
 			isFinal: true,
 		}
 
-		closeID := uint32(0)
-
 		for _, x := range v.Conjuncts {
-			closeID := closeID
 			// TODO: needed for reentrancy. Investigate usefulness for cycle
 			// detection.
-			if x.Env != nil && x.Env.CloseID != 0 {
-				closeID = x.Env.CloseID
-			}
-			n.addExprConjunct(x, closeID, true)
+			n.addExprConjunct(x, true)
 		}
 
 		if i == 0 {
@@ -577,20 +571,20 @@
 
 	replace := n.replace
 	if replace == nil {
-		replace = map[uint32]*CloseDef{}
+		replace = map[adt.ID]*CloseDef{}
 	}
 
 	// Mark any used CloseID to keep, if not already replaced.
 	for _, x := range n.optionals {
-		if _, ok := replace[x.env.CloseID]; !ok {
-			replace[x.env.CloseID] = nil
+		if _, ok := replace[x.id]; !ok {
+			replace[x.id] = nil
 		}
 	}
 	for _, a := range n.node.Arcs {
 		for _, c := range a.Conjuncts {
 			if c.Env != nil {
-				if _, ok := replace[c.Env.CloseID]; !ok {
-					replace[c.Env.CloseID] = nil
+				if _, ok := replace[c.ID()]; !ok {
+					replace[c.ID()] = nil
 				}
 			}
 		}
@@ -753,8 +747,8 @@
 	aStruct   adt.Expr
 	hasTop    bool
 	newClose  *CloseDef
-	// closeID   uint32 // from parent, or if not exist, new if introducing a def.
-	replace map[uint32]*CloseDef
+	// closeID   adt.ID // from parent, or if not exist, new if introducing a def.
+	replace map[adt.ID]*CloseDef
 
 	// Expression conjuncts
 	lists  []envList
@@ -891,18 +885,19 @@
 
 type conjunct struct {
 	adt.Conjunct
-	closeID uint32
-	top     bool
+	top bool
 }
 
 type envDynamic struct {
 	env   *adt.Environment
 	field *adt.DynamicField
+	id    adt.ID
 }
 
 type envYield struct {
 	env   *adt.Environment
 	yield adt.Yielder
+	id    adt.ID
 }
 
 type envList struct {
@@ -910,6 +905,7 @@
 	list    *adt.ListLit
 	n       int64 // recorded length after evaluator
 	elipsis *adt.Ellipsis
+	id      adt.ID
 }
 
 func (n *nodeContext) addBottom(b *adt.Bottom) {
@@ -927,52 +923,51 @@
 // addExprConjuncts will attempt to evaluate an adt.Expr and insert the value
 // into the nodeContext if successful or queue it for later evaluation if it is
 // incomplete or is not value.
-func (n *nodeContext) addExprConjunct(v adt.Conjunct, def uint32, top bool) {
+func (n *nodeContext) addExprConjunct(v adt.Conjunct, top bool) {
 	env := v.Env
-	if env != nil && env.CloseID != def {
-		e := *env
-		e.CloseID = def
-		env = &e
-	}
+	id := v.CloseID
+
 	switch x := v.Expr().(type) {
 	case adt.Value:
-		n.addValueConjunct(env, x)
+		n.addValueConjunct(env, x, id)
 
 	case *adt.BinaryExpr:
 		if x.Op == adt.AndOp {
-			n.addExprConjunct(adt.MakeConjunct(env, x.X), def, false)
-			n.addExprConjunct(adt.MakeConjunct(env, x.Y), def, false)
+			n.addExprConjunct(adt.MakeConjunct(env, x.X, id), false)
+			n.addExprConjunct(adt.MakeConjunct(env, x.Y, id), false)
 		} else {
-			n.evalExpr(v, def, top)
+			n.evalExpr(v, top)
 		}
 
 	case *adt.StructLit:
-		n.addStruct(env, x, def, top)
+		n.addStruct(env, x, id, top)
 
 	case *adt.ListLit:
-		n.lists = append(n.lists, envList{env: env, list: x})
+		n.lists = append(n.lists, envList{env: env, list: x, id: id})
 
 	case *adt.DisjunctionExpr:
 		if n.disjunctions != nil {
 			_ = n.disjunctions
 		}
-		n.addDisjunction(env, x, def, top)
+		n.addDisjunction(env, x, id, top)
 
 	default:
 		// Must be Resolver or Evaluator.
-		n.evalExpr(v, def, top)
+		n.evalExpr(v, top)
 	}
 
 	if top {
-		n.updateReplace(v.Env)
+		n.updateReplace(v.CloseID)
 	}
 }
 
 // evalExpr is only called by addExprConjunct.
-func (n *nodeContext) evalExpr(v adt.Conjunct, closeID uint32, top bool) {
+func (n *nodeContext) evalExpr(v adt.Conjunct, top bool) {
 	// Require an Environment.
 	ctx := n.ctx
 
+	closeID := v.CloseID
+
 	// TODO: see if we can do without these counters.
 	for _, d := range v.Env.Deref {
 		d.EvalCount++
@@ -1002,7 +997,7 @@
 			}
 		}
 		if arc == nil {
-			n.exprs = append(n.exprs, conjunct{v, closeID, top})
+			n.exprs = append(n.exprs, conjunct{v, top})
 			break
 		}
 
@@ -1074,8 +1069,10 @@
 			id := n.eval.nextID()
 			n.insertClosed(arc, id, cyclic, arc)
 		} else {
-			for _, a := range arc.Conjuncts {
-				n.addExprConjunct(updateCyclic(a, cyclic, arc), closeID, top)
+			for _, c := range arc.Conjuncts {
+				c = updateCyclic(c, cyclic, arc)
+				c.CloseID = closeID
+				n.addExprConjunct(c, top)
 			}
 		}
 
@@ -1084,7 +1081,7 @@
 		// Could be unify?
 		val, complete := ctx.Evaluate(v.Env, v.Expr())
 		if !complete {
-			n.exprs = append(n.exprs, conjunct{v, closeID, top})
+			n.exprs = append(n.exprs, conjunct{v, top})
 			break
 		}
 
@@ -1094,14 +1091,15 @@
 			b, ok := v.Value.(*adt.Bottom)
 			if ok && b.IsIncomplete() && len(v.Conjuncts) > 0 {
 				for _, c := range v.Conjuncts {
-					n.addExprConjunct(c, closeID, top)
+					c.CloseID = closeID
+					n.addExprConjunct(c, top)
 				}
 				break
 			}
 		}
 
 		// TODO: insert in vertex as well
-		n.addValueConjunct(v.Env, val)
+		n.addValueConjunct(v.Env, val, closeID)
 
 	default:
 		panic(fmt.Sprintf("unknown expression of type %T", x))
@@ -1138,17 +1136,19 @@
 		env.Deref = append(env.Deref, deref)
 		env.Cycles = append(env.Cycles, deref)
 	}
-	return adt.MakeConjunct(env, c.Expr())
+	return adt.MakeConjunct(env, c.Expr(), c.CloseID)
 }
 
-func (n *nodeContext) insertClosed(arc *adt.Vertex, id uint32, cyclic bool, deref *adt.Vertex) {
+func (n *nodeContext) insertClosed(arc *adt.Vertex, id adt.ID, cyclic bool, deref *adt.Vertex) {
 	n.needClose = true
 
 	current := n.newClose
 	n.newClose = nil
 
-	for _, a := range arc.Conjuncts {
-		n.addExprConjunct(updateCyclic(a, cyclic, deref), id, false)
+	for _, c := range arc.Conjuncts {
+		c = updateCyclic(c, cyclic, deref)
+		c.CloseID = id
+		n.addExprConjunct(c, false)
 	}
 
 	current, n.newClose = n.newClose, current
@@ -1159,7 +1159,7 @@
 	n.addAnd(current)
 }
 
-func (n *nodeContext) addValueConjunct(env *adt.Environment, v adt.Value) {
+func (n *nodeContext) addValueConjunct(env *adt.Environment, v adt.Value, id adt.ID) {
 	n.updateCyclicStatus(env)
 
 	if x, ok := v.(*adt.Vertex); ok {
@@ -1181,11 +1181,13 @@
 		if !x.IsData() && len(x.Conjuncts) > 0 {
 			cyclic := env != nil && env.Cyclic
 			if needClose {
-				n.insertClosed(x, env.CloseID, cyclic, nil)
+				n.insertClosed(x, id, cyclic, nil)
 				return
 			}
 			for _, c := range x.Conjuncts {
-				n.addExprConjunct(updateCyclic(c, cyclic, nil), 0, false) // TODO: Pass from eval
+				c = updateCyclic(c, cyclic, nil)
+				c.CloseID = id
+				n.addExprConjunct(c, false) // TODO: Pass from eval
 			}
 			return
 		}
@@ -1206,17 +1208,17 @@
 					n.aStruct = x
 				}
 				// TODO, insert here as
-				n.insertField(a.Label, adt.MakeConjunct(nil, a))
+				n.insertField(a.Label, adt.MakeConjunct(nil, a, id))
 				// sub, _ := n.node.GetArc(a.Label)
 				// sub.Add(a)
 			}
 
 		default:
-			n.addValueConjunct(env, v)
+			n.addValueConjunct(env, v, id)
 
 			for _, a := range x.Arcs {
 				// TODO(errors): report error when this is a regular field.
-				n.insertField(a.Label, adt.MakeConjunct(nil, a))
+				n.insertField(a.Label, adt.MakeConjunct(nil, a, id))
 				// sub, _ := n.node.GetArc(a.Label)
 				// sub.Add(a)
 			}
@@ -1239,17 +1241,17 @@
 
 	switch x := v.(type) {
 	case *adt.Disjunction:
-		n.addDisjunctionValue(env, x, 0, true)
+		n.addDisjunctionValue(env, x, id, true)
 
 	case *adt.Conjunction:
 		for _, x := range x.Values {
-			n.addValueConjunct(env, x)
+			n.addValueConjunct(env, x, id)
 		}
 
 	case *adt.Top:
 		n.hasTop = true
 		// TODO: Is this correct. Needed for elipsis, but not sure for others.
-		n.optionals = append(n.optionals, fieldSet{env: env, isOpen: true})
+		n.optionals = append(n.optionals, fieldSet{env: env, id: id, isOpen: true})
 
 	case *adt.BasicType:
 		// handled above
@@ -1259,7 +1261,7 @@
 		case adt.LessThanOp, adt.LessEqualOp:
 			if y := n.upperBound; y != nil {
 				n.upperBound = nil
-				n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y))
+				n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y), id)
 				return
 			}
 			n.upperBound = x
@@ -1267,7 +1269,7 @@
 		case adt.GreaterThanOp, adt.GreaterEqualOp:
 			if y := n.lowerBound; y != nil {
 				n.lowerBound = nil
-				n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y))
+				n.addValueConjunct(env, adt.SimplifyBounds(ctx, n.kind, x, y), id)
 				return
 			}
 			n.lowerBound = x
@@ -1303,7 +1305,7 @@
 		if u := adt.SimplifyBounds(ctx, n.kind, n.lowerBound, n.upperBound); u != nil {
 			n.lowerBound = nil
 			n.upperBound = nil
-			n.addValueConjunct(env, u)
+			n.addValueConjunct(env, u, id)
 		}
 	}
 }
@@ -1318,7 +1320,7 @@
 func (n *nodeContext) addStruct(
 	env *adt.Environment,
 	s *adt.StructLit,
-	newDef uint32,
+	closeID adt.ID,
 	top bool) {
 
 	n.updateCyclicStatus(env) // to handle empty structs.
@@ -1326,12 +1328,6 @@
 	ctx := n.ctx
 	n.node.AddStructs(s)
 
-	// Inherit closeID from environment, unless this is a new definition.
-	closeID := newDef
-	if closeID == 0 && env != nil {
-		closeID = env.CloseID
-	}
-
 	// NOTE: This is a crucial point in the code:
 	// Unification derferencing happens here. The child nodes are set to
 	// an Environment linked to the current node. Together with the De Bruijn
@@ -1345,9 +1341,8 @@
 	// 	}
 	// }
 	childEnv := &adt.Environment{
-		Up:      env,
-		Vertex:  n.node,
-		CloseID: closeID,
+		Up:     env,
+		Vertex: n.node,
 	}
 	if env != nil {
 		childEnv.Cyclic = env.Cyclic
@@ -1357,7 +1352,7 @@
 	var hasOther, hasBulk adt.Node
 	hasEmbed := false
 
-	opt := fieldSet{pos: s, env: childEnv}
+	opt := fieldSet{pos: s, env: childEnv, id: closeID}
 
 	for _, d := range s.Decls {
 		switch x := d.(type) {
@@ -1374,16 +1369,16 @@
 		case *adt.DynamicField:
 			n.aStruct = s
 			hasOther = x
-			n.dynamicFields = append(n.dynamicFields, envDynamic{childEnv, x})
+			n.dynamicFields = append(n.dynamicFields, envDynamic{childEnv, x, closeID})
 			opt.AddDynamic(ctx, childEnv, x)
 
 		case *adt.ForClause:
 			hasOther = x
-			n.forClauses = append(n.forClauses, envYield{childEnv, x})
+			n.forClauses = append(n.forClauses, envYield{childEnv, x, closeID})
 
 		case adt.Yielder:
 			hasOther = x
-			n.ifClauses = append(n.ifClauses, envYield{childEnv, x})
+			n.ifClauses = append(n.ifClauses, envYield{childEnv, x, closeID})
 
 		case adt.Expr:
 			hasEmbed = true
@@ -1395,7 +1390,7 @@
 			n.newClose = nil
 
 			hasOther = x
-			n.addExprConjunct(adt.MakeConjunct(childEnv, x), id, false)
+			n.addExprConjunct(adt.MakeConjunct(childEnv, x, id), false)
 
 			current, n.newClose = n.newClose, current
 
@@ -1443,7 +1438,7 @@
 			if x.Label.IsString() {
 				n.aStruct = s
 			}
-			n.insertField(x.Label, adt.MakeConjunct(childEnv, x))
+			n.insertField(x.Label, adt.MakeConjunct(childEnv, x, closeID))
 		}
 	}
 }
@@ -1502,7 +1497,7 @@
 	exprs := n.exprs
 	n.exprs = n.exprs[:0]
 	for _, x := range exprs {
-		n.addExprConjunct(x.Conjunct, x.closeID, x.top)
+		n.addExprConjunct(x.Conjunct, x.top)
 
 		// collect and and or
 	}
@@ -1530,11 +1525,11 @@
 			continue
 		}
 		if b, _ := v.(*adt.Bottom); b != nil {
-			n.addValueConjunct(nil, b)
+			n.addValueConjunct(nil, b, d.id)
 			continue
 		}
 		f = ctx.Label(v)
-		n.insertField(f, adt.MakeConjunct(d.env, d.field))
+		n.insertField(f, adt.MakeConjunct(d.env, d.field, d.id))
 	}
 
 	progress = k < len(n.dynamicFields)
@@ -1575,7 +1570,7 @@
 		}
 
 		for _, st := range sa {
-			n.addStruct(st.env, st.s, 0, true)
+			n.addStruct(st.env, st.s, d.id, true)
 		}
 	}
 
@@ -1639,7 +1634,7 @@
 
 		for _, a := range elems {
 			if a.Conjuncts == nil {
-				n.insertField(a.Label, adt.MakeConjunct(nil, a.Value))
+				n.insertField(a.Label, adt.MakeConjunct(nil, a.Value, 0))
 				continue
 			}
 			for _, c := range a.Conjuncts {
@@ -1663,7 +1658,7 @@
 					label, err := adt.MakeLabel(x.Source(), index, adt.IntLabel)
 					n.addErr(err)
 					index++
-					n.insertField(label, adt.MakeConjunct(e, st))
+					n.insertField(label, adt.MakeConjunct(e, st, l.id))
 				})
 				hasComprehension = true
 				if err != nil && !err.IsIncomplete() {
@@ -1681,7 +1676,7 @@
 				label, err := adt.MakeLabel(x.Source(), index, adt.IntLabel)
 				n.addErr(err)
 				index++ // TODO: don't use insertField.
-				n.insertField(label, adt.MakeConjunct(l.env, x))
+				n.insertField(label, adt.MakeConjunct(l.env, x, l.id))
 			}
 
 			// Terminate early n case of runaway comprehension.
@@ -1734,7 +1729,7 @@
 			continue
 		}
 
-		f := fieldSet{pos: l.list, env: l.env}
+		f := fieldSet{pos: l.list, env: l.env, id: l.id}
 		f.AddEllipsis(c, l.elipsis)
 
 		n.optionals = append(n.optionals, f)
diff --git a/internal/core/eval/optionals.go b/internal/core/eval/optionals.go
index 0426c18..947dd19 100644
--- a/internal/core/eval/optionals.go
+++ b/internal/core/eval/optionals.go
@@ -23,11 +23,13 @@
 // fieldSet represents the fields for a single struct literal, along
 // the constraints of fields that may be added.
 type fieldSet struct {
-	pos adt.Node
+	next *fieldSet
+	pos  adt.Node
 
 	// TODO: look at consecutive identical environments to figure out
 	// what belongs to same definition?
 	env *adt.Environment
+	id  adt.ID
 
 	// field marks the optional conjuncts of all explicit fields.
 	// Required fields are marked as empty
@@ -104,7 +106,7 @@
 	}
 	if p < len(o.fields) {
 		for _, e := range o.fields[p].optional {
-			arc.AddConjunct(adt.MakeConjunct(env, e))
+			arc.AddConjunct(adt.MakeConjunct(env, e, o.id))
 		}
 		return
 	}
@@ -122,7 +124,7 @@
 		if f.check.Match(c, arc.Label) {
 			matched = true
 			if f.expr != nil {
-				arc.AddConjunct(adt.MakeConjunct(&bulkEnv, f.expr))
+				arc.AddConjunct(adt.MakeConjunct(&bulkEnv, f.expr, o.id))
 			}
 		}
 	}
@@ -132,7 +134,7 @@
 
 	// match others
 	for _, x := range o.additional {
-		arc.AddConjunct(adt.MakeConjunct(env, x))
+		arc.AddConjunct(adt.MakeConjunct(env, x, o.id))
 	}
 }
 
@@ -242,13 +244,13 @@
 	v := adt.Vertex{}
 	v.AddConjunct(adt.Conjunct(m))
 	label := f.ToValue(c)
-	v.AddConjunct(adt.MakeConjunct(m.Env, label))
+	v.AddConjunct(adt.MakeRootConjunct(m.Env, label))
 	v.Finalize(c)
 	b, _ := v.Value.(*adt.Bottom)
 	return b == nil
 }
 
 func (o *fieldSet) newPatternMatcher(ctx *adt.OpContext, x adt.Value) fieldMatcher {
-	c := adt.MakeConjunct(o.env, x)
+	c := adt.MakeRootConjunct(o.env, x)
 	return patternMatcher(c)
 }
diff --git a/internal/core/export/export.go b/internal/core/export/export.go
index 51f2209..733c202 100644
--- a/internal/core/export/export.go
+++ b/internal/core/export/export.go
@@ -291,7 +291,7 @@
 
 func (e *exporter) setDocs(x adt.Node) {
 	f := e.stack[len(e.stack)-1]
-	f.docSources = []adt.Conjunct{adt.MakeConjunct(nil, x)}
+	f.docSources = []adt.Conjunct{adt.MakeRootConjunct(nil, x)}
 	e.stack[len(e.stack)-1] = f
 }
 
diff --git a/internal/core/export/expr.go b/internal/core/export/expr.go
index 3edc5f5..7f130f5 100644
--- a/internal/core/export/expr.go
+++ b/internal/core/export/expr.go
@@ -65,7 +65,7 @@
 		return e.mergeValues(adt.InvalidLabel, x, a, x.Conjuncts...)
 
 	case *adt.StructLit:
-		c := adt.MakeConjunct(nil, x)
+		c := adt.MakeRootConjunct(nil, x)
 		return e.mergeValues(adt.InvalidLabel, nil, []conjunct{{c: c, up: 0}}, c)
 
 	case adt.Value:
@@ -204,7 +204,7 @@
 func (c *conjuncts) addConjunct(f adt.Feature, env *adt.Environment, n adt.Node) {
 
 	x := c.fields[f]
-	v := adt.MakeConjunct(env, n)
+	v := adt.MakeRootConjunct(env, n)
 	x.conjuncts = append(x.conjuncts, conjunct{
 		c:  v,
 		up: c.top().upCount,
@@ -282,7 +282,7 @@
 		switch x.(type) {
 		case *adt.StructMarker, *adt.Top:
 		default:
-			e.values.AddConjunct(adt.MakeConjunct(env, x)) // GOBBLE TOP
+			e.values.AddConjunct(adt.MakeRootConjunct(env, x)) // GOBBLE TOP
 		}
 
 	case *adt.BinaryExpr:
@@ -291,14 +291,14 @@
 			e.addExpr(env, x.X)
 			e.addExpr(env, x.Y)
 		case isSelfContained(x):
-			e.values.AddConjunct(adt.MakeConjunct(env, x))
+			e.values.AddConjunct(adt.MakeRootConjunct(env, x))
 		default:
 			e.exprs = append(e.exprs, e.expr(x))
 		}
 
 	default:
 		if isSelfContained(x) {
-			e.values.AddConjunct(adt.MakeConjunct(env, x))
+			e.values.AddConjunct(adt.MakeRootConjunct(env, x))
 		} else {
 			e.exprs = append(e.exprs, e.expr(x))
 		}
diff --git a/internal/core/subsume/structural.go b/internal/core/subsume/structural.go
index 16e7a0e..bc581cb 100644
--- a/internal/core/subsume/structural.go
+++ b/internal/core/subsume/structural.go
@@ -42,7 +42,7 @@
 }
 
 func (s *subsumer) c(env *adt.Environment, x adt.Expr) adt.Conjunct {
-	return adt.MakeConjunct(env, x)
+	return adt.MakeRootConjunct(env, x)
 }
 
 func isBottomConjunct(c adt.Conjunct) bool {
@@ -247,12 +247,12 @@
 		case *adt.Field:
 			e := c.fields[x.Label]
 			e.required = true
-			e.conjuncts = append(e.conjuncts, adt.MakeConjunct(env, x))
+			e.conjuncts = append(e.conjuncts, adt.MakeRootConjunct(env, x))
 			c.fields[x.Label] = e
 
 		case *adt.OptionalField:
 			e := c.fields[x.Label]
-			e.conjuncts = append(e.conjuncts, adt.MakeConjunct(env, x))
+			e.conjuncts = append(e.conjuncts, adt.MakeRootConjunct(env, x))
 			c.fields[x.Label] = e
 			c.hasOptional = true
 
diff --git a/pkg/internal/builtin.go b/pkg/internal/builtin.go
index 167bbec..ac69222 100644
--- a/pkg/internal/builtin.go
+++ b/pkg/internal/builtin.go
@@ -64,7 +64,7 @@
 	pkgLabel := ctx.StringLabel(pkgName)
 	st := &adt.StructLit{}
 	if len(p.Native) > 0 {
-		obj.AddConjunct(adt.MakeConjunct(nil, st))
+		obj.AddConjunct(adt.MakeRootConjunct(nil, st))
 	}
 	for _, b := range p.Native {
 		b.Pkg = pkgLabel