# Self-referential expressions broken by a concrete value should resolve,
# regardless of which builtin sits between the field and its self-reference.
# Earlier evaluators rejected some such cycles with bogus errors like
# "cannot add field N: was already used" or "cycle error", even though
# similar cases with other builtins resolved fine.
# https://cuelang.org/issue/2627
-- in.cue --
import (
	"list"
	"math"
	"encoding/json"
)

mutualArith: {
	x: y + 1
	y: x - 1
	x: 5
	@test(eq, {x: 5, y: 4})
}

selfArith: {
	x: x + 1 - 1
	x: 5
	@test(eq, {x: 5})
}

selfMathRound: {
	x: math.Round(x)
	x: 5
	@test(eq, {x: 5})
}

selfListFlattenN: {
	x: list.FlattenN(x, -1)
	x: [1, 2, 3]
	@test(eq, {x: [1, 2, 3]})
}

selfJSONMarshalUnmarshalScalar: {
	x: json.Marshal(json.Unmarshal(x))
	x: "5"
	@test(eq, {x: "5"})
}

selfJSONMarshalUnmarshalObject: {
	x: json.Marshal(json.Unmarshal(x))
	x: #"{"a":5}"#
	@test(eq, {x: #"{"a":5}"#})
}

selfJSONUnmarshalMarshal: {
	x: json.Unmarshal(json.Marshal(x))
	x: a: 5
	@test(eq, {x: {a: 5}})
}

mutualJSON: {
	x: json.Unmarshal(y)
	y: json.Marshal(x)
	y: #"{"a":5}"#
	x: a: 5
	@test(eq, {x: {a: 5}, y: #"{"a":5}"#})
}

toJSON: {
	x: a: 5
	y: json.Marshal(x)
	x: json.Unmarshal(y)
	@test(eq:todo, {x: {a: 5}, y: #"{"a":5}"#})
}

fromJSON: {
	x: json.Unmarshal(y)
	y: json.Marshal(x)
	y: #"{"a":5}"#
	@test(eq, {x: {a: 5}, y: #"{"a":5}"#})
}
-- out/errors.txt --
[incomplete] toJSON.x: error in call to encoding/json.Unmarshal: non-concrete value _:
    ./in.cue:61:5
-- out/eval/stats --
Leaks:  0
Freed:  40
Reused: 24
Allocs: 16
Retain: 0

Unifications: 37
Conjuncts:    53
Disjuncts:    0

NumCloseIDs: 4
