// This files tests that values are properly "frozen" in case of mutual
// references. Non-structural cyclic references are okay, as long a property
// that is dependended upon in the cycle is not changed after the fact,
// that is, a value may not become more specific after it is used.
-- in.cue --
freezing: t1: ok: {
	#a: x: "a"
	len(#a) // 1
	@test(eq, {1, #a: {x: "a"}})
}

-- comprehension.cue --
// This should be an incomplete error, as z is inserted in x, over which the
// comprehension loops. Adding a field z to x would fix this.
// This test would fail in the old evaluator, depending on ordering.
comprehension: t1: _
comprehension: t1: ok:{
	@test(permute, count=)

	x: y: {}
	// order of comprehensions matter in old evaluator.
	for _ in x {
		if true { x: z: a: {} }
	}
	if true {
		if true { x: z: a: {} }
	}
	@test(eq, {x: {y: {}, z: {a: {}}}})
}

comprehension: t2: err: {
	a: {
		x: 1
		for k, v in a {
			(k+"q"): v // This increases the set of fields in a.
		}
		@test(err, code=eval, contains="adding field %v not allowed as field set was already referenced", args=[xq], pos=[3:13])
	}
}

comprehension: t3: err: {
	// mutual dependencies not okay in this case, as the set of fields grows.
	a: x: 1
	b: y: 1
	a: {
		for k, v in b {
			(k+"q"): v
		}
		@test(err, code=eval,
			suberr=(code=eval, contains="adding field %v not allowed as field set was already referenced", args=[yq], pos=[2:13]),
			suberr=(code=eval, contains="adding field %v not allowed as field set was already referenced", args=[xq], pos=[2:13]))
	}
	b: {
		for k, v in a {
			(k): v
		}
		@test(eq, {y: 1, x: 1})
	}
}

comprehension: t4: ok: {
	// It is okay to make x more specific as long as no fields are added.
	x: y: {}
	for _ in x {
		if true { x: y: a: {} }
	}
	@test(eq, {x: {y: {a: {}}}})
}

comprehension: moreSpecific: ok: {
	a: {
		x: int
		for k, v in a {
			(k): 1
		}
		@test(eq, {x: 1})
	}
}

comprehension: moreSpecific: err: {
	a: {
		x: {y: 1}
		// len(v) should free the size of x.
		for k, v in a if len(v) > 0 {
			(k): {z: 1}
		}
		@test(err, code=eval, path=x,
			contains="adding field %v not allowed as field set was already referenced", args=[z], pos=[4:9])
	}
}
-- issue3178.cue --
// evalv3 regression: exporting via the Go API produced an error that evalv2
// did not, for a case involving chained comprehensions.
// https://cuelang.org/issue/3178
issue3178: {
	// This should pass. Reasoning:
	// - second comprehension runs
	// - in order to satisfy, first comprehension must run
	// - first comprehension runs and completes
	input: [ "Value" ]
	output: {...}
	for name in input {
			output: "\(name)": true
	}
	for name, v in output {
	}
	@test(eq, {input: ["Value"], output: {Value: true}})
}
-- out/errors.txt --
[eval] comprehension.t2.err.a: adding field xq not allowed as field set was already referenced:
    ./comprehension.cue:23:13
[eval] comprehension.t3.err.a: adding field xq not allowed as field set was already referenced:
    ./comprehension.cue:35:13
comprehension.t3.err.a: adding field yq not allowed as field set was already referenced:
    ./comprehension.cue:35:13
[eval] comprehension.moreSpecific.err.a.x: adding field z not allowed as field set was already referenced:
    ./comprehension.cue:73:9
-- out/eval/stats --
Leaks:  4
Freed:  42
Reused: 28
Allocs: 18
Retain: 0

Unifications: 46
Conjuncts:    87
Disjuncts:    0

NumCloseIDs: 24
