-- in.cue --
dynamicTop: {
	#D: {
		for k, v in {foo: 123} {(k): v}
	}
}

// Issue #1404
dynamicDepth1: {
	#D: {
		a: foo: 123
		b: {for k, v in a {(k): v}}
	}
}

allowed: {
	#D: {
		if true {
			d: int
		}
	}

	vErr: #D & {d: 5}
}

disallowed: {
	#D: {
		if false {
			d: int
		}
	}

	vErr: #D & {d: 5}
}

// Interpret comprehensions as embeddings.
// Issue #1956
comprehensionIsEmbed: {
	#A: size: int | *1
	#B: {
		kind: string

		// Should be identical to just #A. That is, #A is treated as open.
		if true {
			#A
		}
	}
	x: #B & {
		kind: "A"
	}
}

// This comprehension is inside a definition and should still disallow b.
noEraseDefinition: {
	#Foo: [if true {a: int}]
	a: { #Foo & [{ b: 2 }] } // Error
}

issue1956: {
	#Details: {
		size: int | *1
	}

	#Thing: {
		kind: "KindA" | "KindB"
		if kind == "KindA" {
			#Details
		}
	}

	x: #Thing & {
		kind: "KindA"
	}
}

// This triggers adding the same "closedInfo" twice, potentially causing
// a cyclic linked list in the todo list.
dedupTodo: {
	#sub: {
		c: _
		if c.n == "c" {
			X: test: c
		}
	}

	out: #sub // needs to be definition
	out: {
		c: n: "c" // Do not combine with &, as the original issue relies on this.
		c: n: string
	}
}

-- v3issues.cue --
issue3483: {
	#Schema: schemaField: int
	out1: out2: #Schema & {
		if false {
			schemaField: 3
		}
	}
}
issue3486: {
	#schema: {}

	if true {
		out: {
			#schema
			// This field should be allowed as #schema is embedded.
			extra: "foo"
		}
	}
}
-- out/eval/stats --
Leaks:  4
Freed:  78
Reused: 74
Allocs: 8
Retain: 3

Unifications: 68
Conjuncts:    118
Disjuncts:    81
-- out/evalalpha --
Errors:
disallowed.vErr.d: field not allowed:
    ./in.cue:28:4
    ./in.cue:32:14
noEraseDefinition.a.0.b: field not allowed:
    ./in.cue:55:17

Result:
(_|_){
  // [eval]
  dynamicTop: (struct){
    #D: (#struct){
      foo: (int){ 123 }
    }
  }
  dynamicDepth1: (struct){
    #D: (#struct){
      a: (#struct){
        foo: (int){ 123 }
      }
      b: (#struct){
        foo: (int){ 123 }
      }
    }
  }
  allowed: (struct){
    #D: (#struct){
      d: (int){ int }
    }
    vErr: (#struct){
      d: (int){ 5 }
    }
  }
  disallowed: (_|_){
    // [eval]
    #D: (#struct){
    }
    vErr: (_|_){
      // [eval]
      d: (_|_){
        // [eval] disallowed.vErr.d: field not allowed:
        //     ./in.cue:28:4
        //     ./in.cue:32:14
      }
    }
  }
  comprehensionIsEmbed: (struct){
    #A: (#struct){
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
    #B: (#struct){
      kind: (string){ string }
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
    x: (#struct){
      kind: (string){ "A" }
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
  }
  noEraseDefinition: (_|_){
    // [eval]
    #Foo: (#list){
      0: (#struct){
        a: (int){ int }
      }
    }
    a: (_|_){
      // [eval]
      0: (_|_){
        // [eval]
        b: (_|_){
          // [eval] noEraseDefinition.a.0.b: field not allowed:
          //     ./in.cue:55:17
        }
        a: (int){ int }
      }
    }
  }
  issue1956: (struct){
    #Details: (#struct){
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
    #Thing: (_|_){
      // [incomplete] issue1956.#Thing: unresolved disjunction "KindA" | "KindB" (type string):
      //     ./in.cue:65:6
      kind: (string){ |((string){ "KindA" }, (string){ "KindB" }) }
    }
    x: (#struct){
      kind: (string){ "KindA" }
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
  }
  dedupTodo: (struct){
    #sub: (_|_){
      // [incomplete] dedupTodo.#sub: c.n undefined as c is incomplete (type _):
      //     ./in.cue:80:6
      c: (_){ _ }
    }
    out: (#struct){
      c: (#struct){
        n: (string){ "c" }
      }
      X: (#struct){
        test: ~(dedupTodo.out.c)
      }
    }
  }
  issue3483: (struct){
    #Schema: (#struct){
      schemaField: (int){ int }
    }
    out1: (struct){
      out2: (#struct){
        schemaField: (int){ int }
      }
    }
  }
  issue3486: (struct){
    #schema: (#struct){
    }
    out: (#struct){
      extra: (string){ "foo" }
    }
  }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -1,19 +1,8 @@
 Errors:
 disallowed.vErr.d: field not allowed:
-    ./in.cue:26:6
-    ./in.cue:27:3
-    ./in.cue:27:12
     ./in.cue:28:4
-    ./in.cue:32:8
     ./in.cue:32:14
-issue3486.out.extra: field not allowed:
-    ./v3issues.cue:10:11
-    ./v3issues.cue:12:2
-    ./v3issues.cue:14:4
-    ./v3issues.cue:16:4
 noEraseDefinition.a.0.b: field not allowed:
-    ./in.cue:54:17
-    ./in.cue:55:7
     ./in.cue:55:17
 
 Result:
@@ -50,11 +39,7 @@
       // [eval]
       d: (_|_){
         // [eval] disallowed.vErr.d: field not allowed:
-        //     ./in.cue:26:6
-        //     ./in.cue:27:3
-        //     ./in.cue:27:12
         //     ./in.cue:28:4
-        //     ./in.cue:32:8
         //     ./in.cue:32:14
       }
     }
@@ -83,13 +68,11 @@
       // [eval]
       0: (_|_){
         // [eval]
-        a: (int){ int }
         b: (_|_){
           // [eval] noEraseDefinition.a.0.b: field not allowed:
-          //     ./in.cue:54:17
-          //     ./in.cue:55:7
           //     ./in.cue:55:17
         }
+        a: (int){ int }
       }
     }
   }
@@ -114,13 +97,11 @@
       c: (_){ _ }
     }
     out: (#struct){
-      c: (struct){
+      c: (#struct){
         n: (string){ "c" }
       }
       X: (#struct){
-        test: (#struct){
-          n: (string){ "c" }
-        }
+        test: ~(dedupTodo.out.c)
       }
     }
   }
@@ -134,19 +115,11 @@
       }
     }
   }
-  issue3486: (_|_){
-    // [eval]
+  issue3486: (struct){
     #schema: (#struct){
     }
-    out: (_|_){
-      // [eval]
-      extra: (_|_){
-        // [eval] issue3486.out.extra: field not allowed:
-        //     ./v3issues.cue:10:11
-        //     ./v3issues.cue:12:2
-        //     ./v3issues.cue:14:4
-        //     ./v3issues.cue:16:4
-      }
+    out: (#struct){
+      extra: (string){ "foo" }
     }
   }
 }
-- diff/todo/p3 --
Missing error positions.
-- diff/explanation --
dedupTodo.out.c: the new evaluator correctly marks this as closed.
-- out/eval --
Errors:
disallowed.vErr.d: field not allowed:
    ./in.cue:26:6
    ./in.cue:27:3
    ./in.cue:27:12
    ./in.cue:28:4
    ./in.cue:32:8
    ./in.cue:32:14
issue3486.out.extra: field not allowed:
    ./v3issues.cue:10:11
    ./v3issues.cue:12:2
    ./v3issues.cue:14:4
    ./v3issues.cue:16:4
noEraseDefinition.a.0.b: field not allowed:
    ./in.cue:54:17
    ./in.cue:55:7
    ./in.cue:55:17

Result:
(_|_){
  // [eval]
  dynamicTop: (struct){
    #D: (#struct){
      foo: (int){ 123 }
    }
  }
  dynamicDepth1: (struct){
    #D: (#struct){
      a: (#struct){
        foo: (int){ 123 }
      }
      b: (#struct){
        foo: (int){ 123 }
      }
    }
  }
  allowed: (struct){
    #D: (#struct){
      d: (int){ int }
    }
    vErr: (#struct){
      d: (int){ 5 }
    }
  }
  disallowed: (_|_){
    // [eval]
    #D: (#struct){
    }
    vErr: (_|_){
      // [eval]
      d: (_|_){
        // [eval] disallowed.vErr.d: field not allowed:
        //     ./in.cue:26:6
        //     ./in.cue:27:3
        //     ./in.cue:27:12
        //     ./in.cue:28:4
        //     ./in.cue:32:8
        //     ./in.cue:32:14
      }
    }
  }
  comprehensionIsEmbed: (struct){
    #A: (#struct){
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
    #B: (#struct){
      kind: (string){ string }
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
    x: (#struct){
      kind: (string){ "A" }
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
  }
  noEraseDefinition: (_|_){
    // [eval]
    #Foo: (#list){
      0: (#struct){
        a: (int){ int }
      }
    }
    a: (_|_){
      // [eval]
      0: (_|_){
        // [eval]
        a: (int){ int }
        b: (_|_){
          // [eval] noEraseDefinition.a.0.b: field not allowed:
          //     ./in.cue:54:17
          //     ./in.cue:55:7
          //     ./in.cue:55:17
        }
      }
    }
  }
  issue1956: (struct){
    #Details: (#struct){
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
    #Thing: (_|_){
      // [incomplete] issue1956.#Thing: unresolved disjunction "KindA" | "KindB" (type string):
      //     ./in.cue:65:6
      kind: (string){ |((string){ "KindA" }, (string){ "KindB" }) }
    }
    x: (#struct){
      kind: (string){ "KindA" }
      size: (int){ |(*(int){ 1 }, (int){ int }) }
    }
  }
  dedupTodo: (struct){
    #sub: (_|_){
      // [incomplete] dedupTodo.#sub: c.n undefined as c is incomplete (type _):
      //     ./in.cue:80:6
      c: (_){ _ }
    }
    out: (#struct){
      c: (struct){
        n: (string){ "c" }
      }
      X: (#struct){
        test: (#struct){
          n: (string){ "c" }
        }
      }
    }
  }
  issue3483: (struct){
    #Schema: (#struct){
      schemaField: (int){ int }
    }
    out1: (struct){
      out2: (#struct){
        schemaField: (int){ int }
      }
    }
  }
  issue3486: (_|_){
    // [eval]
    #schema: (#struct){
    }
    out: (_|_){
      // [eval]
      extra: (_|_){
        // [eval] issue3486.out.extra: field not allowed:
        //     ./v3issues.cue:10:11
        //     ./v3issues.cue:12:2
        //     ./v3issues.cue:14:4
        //     ./v3issues.cue:16:4
      }
    }
  }
}
-- out/compile --
--- in.cue
{
  dynamicTop: {
    #D: {
      for k, v in {
        foo: 123
      } {
        〈1;k〉: 〈1;v〉
      }
    }
  }
  dynamicDepth1: {
    #D: {
      a: {
        foo: 123
      }
      b: {
        for k, v in 〈1;a〉 {
          〈1;k〉: 〈1;v〉
        }
      }
    }
  }
  allowed: {
    #D: {
      if true {
        d: int
      }
    }
    vErr: (〈0;#D〉 & {
      d: 5
    })
  }
  disallowed: {
    #D: {
      if false {
        d: int
      }
    }
    vErr: (〈0;#D〉 & {
      d: 5
    })
  }
  comprehensionIsEmbed: {
    #A: {
      size: (int|*1)
    }
    #B: {
      kind: string
      if true {
        〈2;#A〉
      }
    }
    x: (〈0;#B〉 & {
      kind: "A"
    })
  }
  noEraseDefinition: {
    #Foo: [
      if true {
        a: int
      },
    ]
    a: {
      (〈1;#Foo〉 & [
        {
          b: 2
        },
      ])
    }
  }
  issue1956: {
    #Details: {
      size: (int|*1)
    }
    #Thing: {
      kind: ("KindA"|"KindB")
      if (〈0;kind〉 == "KindA") {
        〈2;#Details〉
      }
    }
    x: (〈0;#Thing〉 & {
      kind: "KindA"
    })
  }
  dedupTodo: {
    #sub: {
      c: _
      if (〈0;c〉.n == "c") {
        X: {
          test: 〈2;c〉
        }
      }
    }
    out: 〈0;#sub〉
    out: {
      c: {
        n: "c"
      }
      c: {
        n: string
      }
    }
  }
}
--- v3issues.cue
{
  issue3483: {
    #Schema: {
      schemaField: int
    }
    out1: {
      out2: (〈1;#Schema〉 & {
        if false {
          schemaField: 3
        }
      })
    }
  }
  issue3486: {
    #schema: {}
    if true {
      out: {
        〈2;#schema〉
        extra: "foo"
      }
    }
  }
}
