-- in.cue --
#DeploymentManifest: #Manifest & {ref: kind: "deployment"}

#Manifest: {
	ref:         #ManifestRef
	description: #KumoriKinds[ref.kind]
}

#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
		}
	}
}

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

			role: configed.role
		}
	}
}

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

	out: {
		labstr: $p.label
	}
}

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

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

#ServiceManifest: #Manifest & {ref: kind: "service"}
-- out/evalalpha/stats --
Leaks:  85
Freed:  0
Reused: 0
Allocs: 85
Retain: 0

Unifications: 61
Conjuncts:    101
Disjuncts:    8

CloseIDElems: 27
NumCloseIDs: 17
-- out/evalalpha --
Errors:
#RelabelService.out.labstr: undefined field: label:
    ./in.cue:51:14

Result:
(_|_){
  // [eval]
  #DeploymentManifest: (#struct){
    ref: (#struct){
      kind: (string){ "deployment" }
    }
    description: ~(#KumoriKinds.deployment)
  }
  #Manifest: (#struct){
    ref: ~(#ManifestRef)
    description: (_|_){
      // [incomplete] #Manifest.description: unresolved disjunction "service" | "deployment" (type string):
      //     ./in.cue:5:15
    }
  }
  #ManifestRef: (#struct){
    kind: (string){ |((string){ "service" }, (string){ "deployment" }) }
  }
  #KindsNames: (string){ |((string){ "service" }, (string){ "deployment" }) }
  #KumoriKinds: (#struct){
    deployment: (#struct){
      service: ~(#ServiceManifest)
      hsize: (_|_){
        // [incomplete] #ServiceManifest.description: undefined field: service:
        //     ./in.cue:5:28
      }
    }
  }
  #DoDeploy: (#struct){
    _params: (#struct){
      manifest: ~(#DeploymentManifest)
    }
    deployment: (#struct){
      description: (#struct){
        let dep#1 = ~(#KumoriKinds.deployment)
        service: (#struct){
          description: (#struct){
            let configed#2 = (_|_){
              // [eval]
              labstr: (_|_){
                // [eval] #DoDeploy.deployment.description.service.description.configed.labstr: undefined field: label:
                //     ./in.cue:51:14
              }
            }
            role: (_|_){
              // [incomplete] #DoDeploy.deployment.description.service.description.role: undefined field: role:
              //     ./in.cue:40:19
            }
          }
        }
      }
    }
  }
  #Configure: (#struct){
    _params: (#struct){
      hsize: (#struct){
      }
    }
    service: (#struct){
      description: (#struct){
        let configed#2 = (_|_){
          // [eval]
          labstr: (_|_){
            // [eval] #Configure.service.description.configed.labstr: undefined field: label:
            //     ./in.cue:51:14
          }
        }
        role: (_|_){
          // [incomplete] #Configure.service.description.role: undefined field: role:
          //     ./in.cue:40:19
        }
      }
    }
  }
  #RelabelService: (_|_){
    // [eval]
    _params: (#struct){
      hsize: ~(#RoleSize)
    }
    out: (_|_){
      // [eval]
      labstr: (_|_){
        // [eval] #RelabelService.out.labstr: undefined field: label:
        //     ./in.cue:51:14
      }
    }
  }
  #RoleSize: (#struct){
    $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) }
  }
  #Deployment: (#struct){
    service: ~(#ServiceManifest)
    hsize: (_|_){
      // [incomplete] #ServiceManifest.description: undefined field: service:
      //     ./in.cue:5:28
    }
  }
  #ServiceManifest: (#struct){
    ref: (#struct){
      kind: (string){ "service" }
    }
    description: (_|_){
      // [incomplete] #ServiceManifest.description: undefined field: service:
      //     ./in.cue:5:28
    }
  }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -1,8 +1,4 @@
 Errors:
-#Configure.service.description.role: undefined field: role:
-    ./in.cue:40:19
-#DoDeploy.deployment.description.service.description.role: undefined field: role:
-    ./in.cue:40:19
 #RelabelService.out.labstr: undefined field: label:
     ./in.cue:51:14
 
@@ -13,24 +9,10 @@
     ref: (#struct){
       kind: (string){ "deployment" }
     }
-    description: (#struct){
-      service: (#struct){
-        ref: (#struct){
-          kind: (string){ "service" }
-        }
-        description: (_|_){
-          // [incomplete] #DeploymentManifest.description.service.description: undefined field: service:
-          //     ./in.cue:5:28
-        }
-      }
-      hsize: (#struct){
-      }
-    }
+    description: ~(#KumoriKinds.deployment)
   }
   #Manifest: (#struct){
-    ref: (#struct){
-      kind: (string){ |((string){ "service" }, (string){ "deployment" }) }
-    }
+    ref: ~(#ManifestRef)
     description: (_|_){
       // [incomplete] #Manifest.description: unresolved disjunction "service" | "deployment" (type string):
       //     ./in.cue:5:15
@@ -42,62 +24,22 @@
   #KindsNames: (string){ |((string){ "service" }, (string){ "deployment" }) }
   #KumoriKinds: (#struct){
     deployment: (#struct){
-      service: (#struct){
-        ref: (#struct){
-          kind: (string){ "service" }
-        }
-        description: (_|_){
-          // [incomplete] #KumoriKinds.deployment.service.description: undefined field: service:
-          //     ./in.cue:5:28
-        }
-      }
-      hsize: (#struct){
-      }
-    }
-  }
-  #DoDeploy: (_|_){
-    // [eval]
-    _params: (#struct){
-      manifest: (#struct){
-        ref: (#struct){
-          kind: (string){ "deployment" }
-        }
-        description: (#struct){
-          service: (#struct){
-            ref: (#struct){
-              kind: (string){ "service" }
-            }
-            description: (_|_){
-              // [incomplete] #DoDeploy._params.manifest.description.service.description: undefined field: service:
-              //     ./in.cue:5:28
-            }
-          }
-          hsize: (#struct){
-          }
-        }
-      }
-    }
-    deployment: (_|_){
-      // [eval]
-      description: (_|_){
-        // [eval]
-        let dep#1 = (#struct){
-          service: (#struct){
-            ref: (#struct){
-              kind: (string){ "service" }
-            }
-            description: (_|_){
-              // [incomplete] #DoDeploy.deployment.description.dep.service.description: undefined field: service:
-              //     ./in.cue:5:28
-            }
-          }
-          hsize: (#struct){
-          }
-        }
-        service: (_|_){
-          // [eval]
-          description: (_|_){
-            // [eval]
+      service: ~(#ServiceManifest)
+      hsize: (_|_){
+        // [incomplete] #ServiceManifest.description: undefined field: service:
+        //     ./in.cue:5:28
+      }
+    }
+  }
+  #DoDeploy: (#struct){
+    _params: (#struct){
+      manifest: ~(#DeploymentManifest)
+    }
+    deployment: (#struct){
+      description: (#struct){
+        let dep#1 = ~(#KumoriKinds.deployment)
+        service: (#struct){
+          description: (#struct){
             let configed#2 = (_|_){
               // [eval]
               labstr: (_|_){
@@ -106,7 +48,7 @@
               }
             }
             role: (_|_){
-              // [eval] #DoDeploy.deployment.description.service.description.role: undefined field: role:
+              // [incomplete] #DoDeploy.deployment.description.service.description.role: undefined field: role:
               //     ./in.cue:40:19
             }
           }
@@ -114,16 +56,13 @@
       }
     }
   }
-  #Configure: (_|_){
-    // [eval]
-    _params: (#struct){
-      hsize: (#struct){
-      }
-    }
-    service: (_|_){
-      // [eval]
-      description: (_|_){
-        // [eval]
+  #Configure: (#struct){
+    _params: (#struct){
+      hsize: (#struct){
+      }
+    }
+    service: (#struct){
+      description: (#struct){
         let configed#2 = (_|_){
           // [eval]
           labstr: (_|_){
@@ -132,7 +71,7 @@
           }
         }
         role: (_|_){
-          // [eval] #Configure.service.description.role: undefined field: role:
+          // [incomplete] #Configure.service.description.role: undefined field: role:
           //     ./in.cue:40:19
         }
       }
@@ -141,9 +80,7 @@
   #RelabelService: (_|_){
     // [eval]
     _params: (#struct){
-      hsize: (#struct){
-        $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) }
-      }
+      hsize: ~(#RoleSize)
     }
     out: (_|_){
       // [eval]
@@ -157,16 +94,10 @@
     $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) }
   }
   #Deployment: (#struct){
-    service: (#struct){
-      ref: (#struct){
-        kind: (string){ "service" }
-      }
-      description: (_|_){
-        // [incomplete] #Deployment.service.description: undefined field: service:
-        //     ./in.cue:5:28
-      }
-    }
-    hsize: (#struct){
+    service: ~(#ServiceManifest)
+    hsize: (_|_){
+      // [incomplete] #ServiceManifest.description: undefined field: service:
+      //     ./in.cue:5:28
     }
   }
   #ServiceManifest: (#struct){
-- diff/-out/evalalpha/stats<==>+out/eval/stats --
diff old new
--- old
+++ new
@@ -1,9 +1,12 @@
-Leaks:  16
-Freed:  117
-Reused: 108
-Allocs: 25
-Retain: 53
-
-Unifications: 107
-Conjuncts:    243
-Disjuncts:    170
+Leaks:  85
+Freed:  0
+Reused: 0
+Allocs: 85
+Retain: 0
+
+Unifications: 61
+Conjuncts:    101
+Disjuncts:    8
+
+CloseIDElems: 27
+NumCloseIDs: 17
-- out/eval/stats --
Leaks:  16
Freed:  117
Reused: 108
Allocs: 25
Retain: 53

Unifications: 107
Conjuncts:    243
Disjuncts:    170
-- out/eval --
Errors:
#Configure.service.description.role: undefined field: role:
    ./in.cue:40:19
#DoDeploy.deployment.description.service.description.role: undefined field: role:
    ./in.cue:40:19
#RelabelService.out.labstr: undefined field: label:
    ./in.cue:51:14

Result:
(_|_){
  // [eval]
  #DeploymentManifest: (#struct){
    ref: (#struct){
      kind: (string){ "deployment" }
    }
    description: (#struct){
      service: (#struct){
        ref: (#struct){
          kind: (string){ "service" }
        }
        description: (_|_){
          // [incomplete] #DeploymentManifest.description.service.description: undefined field: service:
          //     ./in.cue:5:28
        }
      }
      hsize: (#struct){
      }
    }
  }
  #Manifest: (#struct){
    ref: (#struct){
      kind: (string){ |((string){ "service" }, (string){ "deployment" }) }
    }
    description: (_|_){
      // [incomplete] #Manifest.description: unresolved disjunction "service" | "deployment" (type string):
      //     ./in.cue:5:15
    }
  }
  #ManifestRef: (#struct){
    kind: (string){ |((string){ "service" }, (string){ "deployment" }) }
  }
  #KindsNames: (string){ |((string){ "service" }, (string){ "deployment" }) }
  #KumoriKinds: (#struct){
    deployment: (#struct){
      service: (#struct){
        ref: (#struct){
          kind: (string){ "service" }
        }
        description: (_|_){
          // [incomplete] #KumoriKinds.deployment.service.description: undefined field: service:
          //     ./in.cue:5:28
        }
      }
      hsize: (#struct){
      }
    }
  }
  #DoDeploy: (_|_){
    // [eval]
    _params: (#struct){
      manifest: (#struct){
        ref: (#struct){
          kind: (string){ "deployment" }
        }
        description: (#struct){
          service: (#struct){
            ref: (#struct){
              kind: (string){ "service" }
            }
            description: (_|_){
              // [incomplete] #DoDeploy._params.manifest.description.service.description: undefined field: service:
              //     ./in.cue:5:28
            }
          }
          hsize: (#struct){
          }
        }
      }
    }
    deployment: (_|_){
      // [eval]
      description: (_|_){
        // [eval]
        let dep#1 = (#struct){
          service: (#struct){
            ref: (#struct){
              kind: (string){ "service" }
            }
            description: (_|_){
              // [incomplete] #DoDeploy.deployment.description.dep.service.description: undefined field: service:
              //     ./in.cue:5:28
            }
          }
          hsize: (#struct){
          }
        }
        service: (_|_){
          // [eval]
          description: (_|_){
            // [eval]
            let configed#2 = (_|_){
              // [eval]
              labstr: (_|_){
                // [eval] #DoDeploy.deployment.description.service.description.configed.labstr: undefined field: label:
                //     ./in.cue:51:14
              }
            }
            role: (_|_){
              // [eval] #DoDeploy.deployment.description.service.description.role: undefined field: role:
              //     ./in.cue:40:19
            }
          }
        }
      }
    }
  }
  #Configure: (_|_){
    // [eval]
    _params: (#struct){
      hsize: (#struct){
      }
    }
    service: (_|_){
      // [eval]
      description: (_|_){
        // [eval]
        let configed#2 = (_|_){
          // [eval]
          labstr: (_|_){
            // [eval] #Configure.service.description.configed.labstr: undefined field: label:
            //     ./in.cue:51:14
          }
        }
        role: (_|_){
          // [eval] #Configure.service.description.role: undefined field: role:
          //     ./in.cue:40:19
        }
      }
    }
  }
  #RelabelService: (_|_){
    // [eval]
    _params: (#struct){
      hsize: (#struct){
        $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) }
      }
    }
    out: (_|_){
      // [eval]
      labstr: (_|_){
        // [eval] #RelabelService.out.labstr: undefined field: label:
        //     ./in.cue:51:14
      }
    }
  }
  #RoleSize: (#struct){
    $_instances: (number){ |(*(int){ 1 }, (number){ >=0 }) }
  }
  #Deployment: (#struct){
    service: (#struct){
      ref: (#struct){
        kind: (string){ "service" }
      }
      description: (_|_){
        // [incomplete] #Deployment.service.description: undefined field: service:
        //     ./in.cue:5:28
      }
    }
    hsize: (#struct){
    }
  }
  #ServiceManifest: (#struct){
    ref: (#struct){
      kind: (string){ "service" }
    }
    description: (_|_){
      // [incomplete] #ServiceManifest.description: undefined field: service:
      //     ./in.cue:5:28
    }
  }
}
-- diff/todo/p2 --
Some incorrect error messages. The newly introduced error messages for hsize
seem to be correct, though.
Error paths seem wrong as a result of structure sharing.
Error path now selects into let. This is probably okay, and
to some extent is clearer.
-- out/compile --
--- in.cue
{
  #DeploymentManifest: (〈0;#Manifest〉 & {
    ref: {
      kind: "deployment"
    }
  })
  #Manifest: {
    ref: 〈1;#ManifestRef〉
    description: 〈1;#KumoriKinds〉[〈0;ref〉.kind]
  }
  #ManifestRef: {
    kind: 〈1;#KindsNames〉
  }
  #KindsNames: ("service"|"deployment")
  #KumoriKinds: {
    deployment: 〈1;#Deployment〉
  }
  #KumoriKinds: {
    [string]: {
      ...
    }
  }
  #DoDeploy: {
    _params: {
      manifest: 〈2;#DeploymentManifest〉
    }
    deployment: {
      description: {
        let dep#1 = 〈2;_params〉.manifest.description
        service: (〈3;#Configure〉 & {
          _params: {
            hsize: 〈2;let dep#1〉.hsize
          }
        }).service
      }
    }
  }
  #Configure: {
    _params: {
      hsize: {
        [string]: 〈3;#RoleSize〉
      }
    }
    service: {
      description: {
        let configed#2 = (〈3;#RelabelService〉 & {
          _params: {
            hsize: 〈4;_params〉.hsize
          }
          role: "admin"
        }).out
        role: 〈0;let configed#2〉.role
      }
    }
  }
  #RelabelService: {
    _params: {
      hsize: 〈2;#RoleSize〉
    }
    out: {
      labstr: 〈1;_params〉.label
    }
  }
  #RoleSize: {
    $_instances: (>=0|*1)
  }
  #Deployment: {
    service: 〈1;#ServiceManifest〉
    hsize: {
      [〈1;service〉.description.#roles]: 〈2;#RoleSize〉
    }
  }
  #ServiceManifest: (〈0;#Manifest〉 & {
    ref: {
      kind: "service"
    }
  })
}
