# Tests that errors in definitions with complex reference chains are reported
# correctly, specifically undefined field errors via let bindings. Issue #837.
-- in.cue --
#DeploymentManifest: #Manifest & {ref: kind: "deployment"}

#Manifest: {
	ref:         #ManifestRef
	description: #KumoriKinds[ref.kind] @test(err, code=incomplete,
		contains="unresolved disjunction %v (type %s)",
		args=["service" | "deployment", string], pos=[0:15])
}

#ManifestRef: kind: #KindsNames

#KindsNames: "service" | "deployment"

#KumoriKinds: deployment: #Deployment
#KumoriKinds: [string]: {...}

#DoDeploy: {
	_params: manifest: #DeploymentManifest
	deployment: {
		description: {
			let dep = _params.manifest.description
			service: (#Configure & {
				_params: hsize: dep.hsize
			}).service
			@test(err, at=service.description.role, code=incomplete,
				contains="undefined field: %s", args=[role], pos=[24:19])
		}
	}
}

#Configure: {
	$p=_params: {
		hsize: [string]: #RoleSize
	}
	service: {
		description: {
			let configed = (#RelabelService & {
				_params: {
					hsize: $p.hsize
				}
				role: "admin"
			}).out

			role: configed.role @test(err, code=incomplete,
				contains="undefined field: %s", args=[role], pos=[0:19])
		}
	}
}

#RelabelService: {
	$p=_params: {
		hsize: #RoleSize
	}

	out: {
		labstr: $p.label @test(err, code=eval,
			contains="undefined field: %s", args=[label], pos=[0:14])

	}
} @test(err, code=eval)

#RoleSize: {
	$_instances: >=0 | *1
}

#Deployment: {
	service: #ServiceManifest
	hsize: [service.description.#roles]: #RoleSize
}

#ServiceManifest: #Manifest & {ref: kind: "service"}
@test(err, at=#ServiceManifest.description, code=incomplete,
	contains="undefined field: %s", args=[service], pos=[-67:28])

-- out/errors.txt --
[incomplete] #Manifest.description: unresolved disjunction "service" | "deployment" (type string):
    ./in.cue:5:15
[incomplete] #ServiceManifest.description: undefined field: service:
    ./in.cue:5:28
[incomplete] #DoDeploy.deployment.description.service.description.role: undefined field: role:
    ./in.cue:44:19
[incomplete] #Configure.service.description.role: undefined field: role:
    ./in.cue:44:19
[eval] #RelabelService.out.labstr: undefined field: label:
    ./in.cue:56:14
[incomplete] #ServiceManifest.description: undefined field: service:
    ./in.cue:5:28
[incomplete] #ServiceManifest.description: undefined field: service:
    ./in.cue:5:28
-- out/todo.txt --
v2 additionally reports errors for #Configure.service.description.role and
#DoDeploy.deployment.description.service.description.role (both "undefined field: role"),
while v3 only reports #RelabelService.out.labstr: undefined field: label.
v3 uses structure sharing (~) for several fields, showing them as shared references
rather than expanded inline values.
-- out/eval/stats --
Leaks:  14
Freed:  67
Reused: 49
Allocs: 32
Retain: 0

Unifications: 57
Conjuncts:    97
Disjuncts:    8

NumCloseIDs: 17
