# Tests that recursive secret/nested-map structures (#secrets) unify correctly
# without exponential conjunct expansion. Performance regression originally
# caused quadratic growth when #secrets disjunctions were repeatedly applied.
# https://cuelang.org/issue/1684

// TODO: significantly reduce the number of counts in this evaluation.
-- in.cue --
#Secret: {
	$secret: id: string
}
#secrets: #Secret | {[string]: #secrets}

out: #secrets & {
	FOO: $secret: id: "100"
	ONE: TWO: THREE: $secret: id: "123"
}

#Secret: {
	$secret: _id: string
}
#secrets: #Secret | {[string]: #secrets}

out: #secrets & {
	FOO: $secret: _id: "100"
	ONE: TWO: THREE: $secret: _id: "123"
} @test(eq, {
	FOO: $secret:             {id: "100", _id: "100"}
	ONE: TWO: THREE: $secret: {id: "123", _id: "123"}
})

-- perf.cue --
nestedCross: closed: {
	#D: {id: string} | {[string]: #D}
	#D: {id: string} | {[string]: #D}
	#D: {id: string} | {[string]: #D}
} @test(eq, {#D: {id: string} | {}})

nestedCross: open: {
	D: {id: string} | {[string]: D}
	D: {id: string} | {[string]: D}
	D: {id: string} | {[string]: D}
} @test(eq, {D: {id: string} | {}})

// TODO(perf): support this case.  This is currently exponential, although the
// tight bound on the detection of structural cycles mitigates the situation.
//
// An additional improvement would be to stop processing disjunctions if we see
// there are more than two solutions.
nestedClosed: passing: {
	D: {id: {}} | {[string]: D}
	D: {id: {}} | {[string]: D}
	D: {id: {}} | {[string]: D}
} @test(eq, {D: {id: {}} | {}})
-- out/eval/stats --
Leaks:  13889
Freed:  10906
Reused: 10802
Allocs: 13993
Retain: 0

Unifications: 3175
Conjuncts:    22523
Disjuncts:    6402

NumCloseIDs: 4099

ConjunctInfos:       7472
MaxConjunctInfos:    4
MaxReqSets:          12
MaxRedirect:         6
-- out/todo.txt --
New algorithm is better at trimming recursive disjunctions.
Note that the old closedness implementation of V3 was able to reduce this to
445 unification ops. This could be due to the fact that the old closedness could
in some cases eliminate earlier than with a flat structure. So this may not be
attainable with the current implementation.
TODO(perf): investigate nonetheless.
