// Issue #2146
//
// Ensure that let expressions are uniqued not only per Environment, but also
// per arc. This is relevant for disjunctions. Without it, an incorrect
// result may be cached for an arbitrary Environment.
-- in.cue --
p1: {
	#A: {
		x?: int
		y?: int

		let list = [x, y]
		all:  [for v in list if v != _|_ {v}]

		*{
			x?: _|_
			y:  1
		} | _
	}

	a: #A & { x: 3 }
	b: #A & a
}
p2: {
	#A: {
		x?: int
		y?: int

		let list = [x, y]
		all:  [for v in list if v != _|_ {v}]

		_ | *{
			x?: _|_
			y:  1
		}
	}

	a: #A & { x: 3, y: 2 }
	b: #A & a
}

-- out/evalalpha/stats --
Leaks:  139
Freed:  0
Reused: 0
Allocs: 139
Retain: 0

Unifications: 79
Conjuncts:    157
Disjuncts:    12

CloseIDElems: 120
NumCloseIDs: 42
-- diff/-out/evalalpha/stats<==>+out/eval/stats --
diff old new
--- old
+++ new
@@ -1,9 +1,12 @@
-Leaks:  18
-Freed:  171
-Reused: 163
-Allocs: 26
-Retain: 18
-
-Unifications: 173
-Conjuncts:    557
-Disjuncts:    189
+Leaks:  139
+Freed:  0
+Reused: 0
+Allocs: 139
+Retain: 0
+
+Unifications: 79
+Conjuncts:    157
+Disjuncts:    12
+
+CloseIDElems: 120
+NumCloseIDs: 42
-- out/eval/stats --
Leaks:  18
Freed:  171
Reused: 163
Allocs: 26
Retain: 18

Unifications: 173
Conjuncts:    557
Disjuncts:    189
-- out/evalalpha --
(struct){
  p1: (struct){
    #A: (#struct){ |(*(#struct){
        x?: (_|_){
          // [user] explicit error (_|_ literal) in source:
          //     ./in.cue:10:8
        }
        y: (int){ 1 }
        let list#1 = (#list){
          0: (_|_){
            // [incomplete] p1.#A.list.0: cannot reference optional field: x:
            //     ./in.cue:6:15
          }
          1: (int){ 1 }
        }
        all: (#list){
          0: (int){ 1 }
        }
      }, (#struct){
        x?: (int){ int }
        y?: (int){ int }
        let list#1 = (#list){
          0: (_|_){
            // [incomplete] p1.#A.list.0: cannot reference optional field: x:
            //     ./in.cue:6:15
          }
          1: (_|_){
            // [incomplete] p1.#A.list.1: cannot reference optional field: y:
            //     ./in.cue:6:18
          }
        }
        all: (#list){
        }
      }) }
    a: (#struct){
      x: (int){ 3 }
      y?: (int){ int }
      let list#1 = (#list){
        0: (int){ 3 }
        1: (_|_){
          // [incomplete] p1.a.list.1: cannot reference optional field: y:
          //     ./in.cue:6:18
        }
      }
      all: (#list){
        0: (int){ 3 }
      }
    }
    b: (#struct){
      x: (int){ 3 }
      y?: (int){ int }
      let list#1 = (#list){
        0: (int){ 3 }
        1: (_|_){
          // [incomplete] p1.b.list.1: cannot reference optional field: y:
          //     ./in.cue:6:18
        }
      }
      all: (#list){
        0: (int){ 3 }
      }
    }
  }
  p2: (struct){
    #A: (#struct){ |(*(#struct){
        x?: (_|_){
          // [user] explicit error (_|_ literal) in source:
          //     ./in.cue:27:8
        }
        y: (int){ 1 }
        let list#2 = (#list){
          0: (_|_){
            // [incomplete] p2.#A.list.0: cannot reference optional field: x:
            //     ./in.cue:23:15
          }
          1: (int){ 1 }
        }
        all: (#list){
          0: (int){ 1 }
        }
      }, (#struct){
        x?: (int){ int }
        y?: (int){ int }
        let list#2 = (#list){
          0: (_|_){
            // [incomplete] p2.#A.list.0: cannot reference optional field: x:
            //     ./in.cue:23:15
          }
          1: (_|_){
            // [incomplete] p2.#A.list.1: cannot reference optional field: y:
            //     ./in.cue:23:18
          }
        }
        all: (#list){
        }
      }) }
    a: (#struct){
      x: (int){ 3 }
      y: (int){ 2 }
      let list#2 = (#list){
        0: (int){ 3 }
        1: (int){ 2 }
      }
      all: (#list){
        0: (int){ 3 }
        1: (int){ 2 }
      }
    }
    b: (#struct){
      x: (int){ 3 }
      y: (int){ 2 }
      let list#2 = (#list){
        0: (int){ 3 }
        1: (int){ 2 }
      }
      all: (#list){
        0: (int){ 3 }
        1: (int){ 2 }
      }
    }
  }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -49,10 +49,13 @@
     b: (#struct){
       x: (int){ 3 }
       y?: (int){ int }
-      let list#1multi = [
-        〈1;x〉,
-        〈1;y〉,
-      ]
+      let list#1 = (#list){
+        0: (int){ 3 }
+        1: (_|_){
+          // [incomplete] p1.b.list.1: cannot reference optional field: y:
+          //     ./in.cue:6:18
+        }
+      }
       all: (#list){
         0: (int){ 3 }
       }
@@ -106,10 +109,10 @@
     b: (#struct){
       x: (int){ 3 }
       y: (int){ 2 }
-      let list#2multi = [
-        〈1;x〉,
-        〈1;y〉,
-      ]
+      let list#2 = (#list){
+        0: (int){ 3 }
+        1: (int){ 2 }
+      }
       all: (#list){
         0: (int){ 3 }
         1: (int){ 2 }
-- out/eval --
(struct){
  p1: (struct){
    #A: (#struct){ |(*(#struct){
        x?: (_|_){
          // [user] explicit error (_|_ literal) in source:
          //     ./in.cue:10:8
        }
        y: (int){ 1 }
        let list#1 = (#list){
          0: (_|_){
            // [incomplete] p1.#A.list.0: cannot reference optional field: x:
            //     ./in.cue:6:15
          }
          1: (int){ 1 }
        }
        all: (#list){
          0: (int){ 1 }
        }
      }, (#struct){
        x?: (int){ int }
        y?: (int){ int }
        let list#1 = (#list){
          0: (_|_){
            // [incomplete] p1.#A.list.0: cannot reference optional field: x:
            //     ./in.cue:6:15
          }
          1: (_|_){
            // [incomplete] p1.#A.list.1: cannot reference optional field: y:
            //     ./in.cue:6:18
          }
        }
        all: (#list){
        }
      }) }
    a: (#struct){
      x: (int){ 3 }
      y?: (int){ int }
      let list#1 = (#list){
        0: (int){ 3 }
        1: (_|_){
          // [incomplete] p1.a.list.1: cannot reference optional field: y:
          //     ./in.cue:6:18
        }
      }
      all: (#list){
        0: (int){ 3 }
      }
    }
    b: (#struct){
      x: (int){ 3 }
      y?: (int){ int }
      let list#1multi = [
        〈1;x〉,
        〈1;y〉,
      ]
      all: (#list){
        0: (int){ 3 }
      }
    }
  }
  p2: (struct){
    #A: (#struct){ |(*(#struct){
        x?: (_|_){
          // [user] explicit error (_|_ literal) in source:
          //     ./in.cue:27:8
        }
        y: (int){ 1 }
        let list#2 = (#list){
          0: (_|_){
            // [incomplete] p2.#A.list.0: cannot reference optional field: x:
            //     ./in.cue:23:15
          }
          1: (int){ 1 }
        }
        all: (#list){
          0: (int){ 1 }
        }
      }, (#struct){
        x?: (int){ int }
        y?: (int){ int }
        let list#2 = (#list){
          0: (_|_){
            // [incomplete] p2.#A.list.0: cannot reference optional field: x:
            //     ./in.cue:23:15
          }
          1: (_|_){
            // [incomplete] p2.#A.list.1: cannot reference optional field: y:
            //     ./in.cue:23:18
          }
        }
        all: (#list){
        }
      }) }
    a: (#struct){
      x: (int){ 3 }
      y: (int){ 2 }
      let list#2 = (#list){
        0: (int){ 3 }
        1: (int){ 2 }
      }
      all: (#list){
        0: (int){ 3 }
        1: (int){ 2 }
      }
    }
    b: (#struct){
      x: (int){ 3 }
      y: (int){ 2 }
      let list#2multi = [
        〈1;x〉,
        〈1;y〉,
      ]
      all: (#list){
        0: (int){ 3 }
        1: (int){ 2 }
      }
    }
  }
}
-- out/compile --
--- in.cue
{
  p1: {
    #A: {
      x?: int
      y?: int
      let list#1 = [
        〈1;x〉,
        〈1;y〉,
      ]
      all: [
        for _, v in 〈1;let list#1〉 if (〈0;v〉 != _|_(explicit error (_|_ literal) in source)) {
          〈1;v〉
        },
      ]
      (*{
        x?: _|_(explicit error (_|_ literal) in source)
        y: 1
      }|_)
    }
    a: (〈0;#A〉 & {
      x: 3
    })
    b: (〈0;#A〉 & 〈0;a〉)
  }
  p2: {
    #A: {
      x?: int
      y?: int
      let list#2 = [
        〈1;x〉,
        〈1;y〉,
      ]
      all: [
        for _, v in 〈1;let list#2〉 if (〈0;v〉 != _|_(explicit error (_|_ literal) in source)) {
          〈1;v〉
        },
      ]
      (_|*{
        x?: _|_(explicit error (_|_ literal) in source)
        y: 1
      })
    }
    a: (〈0;#A〉 & {
      x: 3
      y: 2
    })
    b: (〈0;#A〉 & 〈0;a〉)
  }
}
