# evalv3 panics with nil pointer dereference on a reduced real-world CUE file
# involving `let` bindings and mutual references between definitions, whereas
# evalv2 handles it correctly.
# https://cuelang.org/issue/3527
-- in.cue --
package p

_taxPayer: self: {}

let sam = {taxPayer: _taxPayer}
assert: {
	invoke: sam
	invoke: _
	res: subject & {in: invoke}
}

subject: {
	in: #ReturnData
	_computed: (#computeF1040 & {"in": in})
}
#computeF1040: in:      #ReturnData
#ReturnData: taxPayer?: #TaxPayer
#TaxPayer: self?:       _

@test(eq, {
	_taxPayer$p: {self: {}}
	assert: {
		invoke: {taxPayer: {self: {}}}
		res: {
			in: {taxPayer: {self: {}}}
			_computed$p: {in: {taxPayer: {self: {}}}}
		}
	}
	subject: {
		in: {taxPayer?: {self?: _}}
		_computed$p: {in: {taxPayer?: {self?: _}}}
	}
	#computeF1040: {in: {taxPayer?: {self?: _}}}
	#ReturnData: {taxPayer?: {self?: _}}
	#TaxPayer: {self?: _}
})
-- out/eval/stats --
Leaks:  0
Freed:  26
Reused: 11
Allocs: 15
Retain: 0

Unifications: 26
Conjuncts:    55
Disjuncts:    0

NumCloseIDs: 15
-- out/evalalpha --
(struct){
  _taxPayer(:p): (struct){
    self: (struct){
    }
  }
  let sam#1 = (struct){
    taxPayer: ~(_taxPayer(:p))
  }
  assert: (struct){
    invoke: (struct){
      taxPayer: ~(_taxPayer(:p))
    }
    res: (struct){
      in: (#struct){
        taxPayer: (#struct){
          self: (#struct){
          }
        }
      }
      _computed(:p): (#struct){
        in: (#struct){
          taxPayer: (#struct){
            self: (#struct){
            }
          }
        }
      }
    }
  }
  subject: (struct){
    in: ~(#ReturnData)
    _computed(:p): (#struct){
      in: ~(#ReturnData)
    }
  }
  #computeF1040: (#struct){
    in: ~(#ReturnData)
  }
  #ReturnData: (#struct){
    taxPayer?: ~(#TaxPayer)
  }
  #TaxPayer: (#struct){
    self?: (_){ _ }
  }
}
-- diff/-out/evalalpha<==>+out/eval --
diff old new
--- old
+++ new
@@ -4,22 +4,16 @@
     }
   }
   let sam#1 = (struct){
-    taxPayer: (struct){
-      self: (struct){
-      }
-    }
+    taxPayer: ~(_taxPayer(:p))
   }
   assert: (struct){
     invoke: (struct){
-      taxPayer: (struct){
-        self: (struct){
-        }
-      }
+      taxPayer: ~(_taxPayer(:p))
     }
     res: (struct){
       in: (#struct){
         taxPayer: (#struct){
-          self: (struct){
+          self: (#struct){
           }
         }
       }
@@ -26,7 +20,7 @@
       _computed(:p): (#struct){
         in: (#struct){
           taxPayer: (#struct){
-            self: (struct){
+            self: (#struct){
             }
           }
         }
@@ -34,30 +28,16 @@
     }
   }
   subject: (struct){
-    in: (#struct){
-      taxPayer?: (#struct){
-        self?: (_){ _ }
-      }
-    }
+    in: ~(#ReturnData)
     _computed(:p): (#struct){
-      in: (#struct){
-        taxPayer?: (#struct){
-          self?: (_){ _ }
-        }
-      }
+      in: ~(#ReturnData)
     }
   }
   #computeF1040: (#struct){
-    in: (#struct){
-      taxPayer?: (#struct){
-        self?: (_){ _ }
-      }
-    }
+    in: ~(#ReturnData)
   }
   #ReturnData: (#struct){
-    taxPayer?: (#struct){
-      self?: (_){ _ }
-    }
+    taxPayer?: ~(#TaxPayer)
   }
   #TaxPayer: (#struct){
     self?: (_){ _ }
-- out/eval --
(struct){
  _taxPayer(:p): (struct){
    self: (struct){
    }
  }
  let sam#1 = (struct){
    taxPayer: (struct){
      self: (struct){
      }
    }
  }
  assert: (struct){
    invoke: (struct){
      taxPayer: (struct){
        self: (struct){
        }
      }
    }
    res: (struct){
      in: (#struct){
        taxPayer: (#struct){
          self: (struct){
          }
        }
      }
      _computed(:p): (#struct){
        in: (#struct){
          taxPayer: (#struct){
            self: (struct){
            }
          }
        }
      }
    }
  }
  subject: (struct){
    in: (#struct){
      taxPayer?: (#struct){
        self?: (_){ _ }
      }
    }
    _computed(:p): (#struct){
      in: (#struct){
        taxPayer?: (#struct){
          self?: (_){ _ }
        }
      }
    }
  }
  #computeF1040: (#struct){
    in: (#struct){
      taxPayer?: (#struct){
        self?: (_){ _ }
      }
    }
  }
  #ReturnData: (#struct){
    taxPayer?: (#struct){
      self?: (_){ _ }
    }
  }
  #TaxPayer: (#struct){
    self?: (_){ _ }
  }
}
