// Good program ==========
var v_0: {p_0: {p_0: string}} = {p_0: {p_0: "foo"}};
var v_1: {p_0: string, p_1: {p_0: {p_0: string}}} = {p_0: "foo", p_1: v_0};
v_1.p_0 = "foo";
f0(v_1);
var v_2: ({p_0: string}) => void = f0;
v_0.p_0 = v_1;
v_2(v_1);
var v_3: {p_0: string, p_1: {p_0: {p_0: string}}} = {p_0: "foo", p_1: v_0};
v_1.p_1 = v_0;
f2(v_1);
var v_4: {p_0: string, p_1: {p_0: {p_0: string}}} = v_1;
v_0.p_0 = {p_0: "foo"};
v_2(v_4);
assert_type(v_0, {p_0: {p_0: "foo"}});
assert_type(v_1, {p_0: "foo", p_1: {p_0: {p_0: "foo"}}});
assert_type(v_3, {p_0: "foo", p_1: {p_0: {p_0: "foo"}}});
assert_type(v_4, {p_0: "foo", p_1: {p_0: {p_0: "foo"}}});
function f0(param_0: {p_0: string}): void {
  assert_type(param_0, {p_0: "foo"});
  param_0.p_0 = "foo";
}
function f1(param_0: {p_0: string}): void {
  assert_type(param_0, {p_0: "foo"});
  param_0.p_0 = "foo";
}
function f2(param_0: {p_0: string, p_1: {p_0: {p_0: string}}}): void {
  assert_type(param_0, {p_0: "foo", p_1: {p_0: {p_0: "foo"}}});
  param_0.p_1 = v_1.p_1;
}
function f3(param_0: {p_0: string}): void {
  assert_type(param_0, {p_0: "foo"});
  param_0.p_0 = "foo";
}

/*
Env:
void
string | {p_0: string}
{p_0: "foo", p_1: v_0} : {p_0: string, p_1: {p_0: {p_0: string}}}
{p_0: string}
{p_0: {p_0: string}}
v_2(v_4) : void
v_1.p_1 : {p_0: {p_0: string}}
number
v_4 : {p_0: string, p_1: {p_0: {p_0: string}}}
{p_0: void}
{p_0: f2(v_1)} : {p_0: void}
({p_0: {p_0: string}} | number) | {p_0: string, p_1: {p_0: {p_0: string}}}
"foo" : string
{p_0: {p_0: string}} | number
{p_0: v_1.p_1, p_1: "foo"} : {p_0: {p_0: {p_0: string}}, p_1: string}
{p_0: {p_0: {p_0: string}}, p_1: string}
v_2 : ({p_0: string}) => void
f0(v_1) : void
v_2(v_1) : void
v_3.p_1 : {p_0: {p_0: string}}
{p_0: string, p_1: {p_0: {p_0: string}}}
string | number
{p_0: {p_0: "foo"}} : {p_0: {p_0: string}}
v_3.p_0 : string
({p_0: string}) => void
1.1 : number
string | string
{p_0: "foo"} : {p_0: string}
v_0.p_0 : {p_0: string}
f2(v_1) : void
({p_0: string, p_1: {p_0: {p_0: string}}}) => void
f2 : ({p_0: string, p_1: {p_0: {p_0: string}}}) => void
v_1 : {p_0: string, p_1: {p_0: {p_0: string}}}
f0 : ({p_0: string}) => void
f1 : ({p_0: string}) => void
v_0 : {p_0: {p_0: string}}
f3 : ({p_0: string}) => void
v_3 : {p_0: string, p_1: {p_0: {p_0: string}}}
string
*/



// Good program ==========
var v_5: {p_0: number, p_1: number} = {p_0: 1.1, p_1: 1.1};
v_5.p_0 = 1.1;
f4({p_0: 1.1, p_1: 1.1});
var v_6: {p_0: {p_0: void}} = {p_0: {p_0: f4({p_0: 1.1, p_1: 1.1})}};
v_5.p_1 = v_5.p_0;
f5({p_0: 1.1, p_1: 1.1});
var v_7: {p_0: {p_0: void}} = {p_0: {p_0: f4({p_0: 1.1, p_1: 1.1})}};
v_5.p_1 = 1.1;
f4({p_0: 1.1, p_1: 1.1});
var v_8: {p_0: {p_0: void}} = v_7;
v_5.p_0 = 1.1;
f4(v_5);
var v_9: {p_0: {p_0: void}} = {p_0: {p_0: f4({p_0: 1.1, p_1: 1.1})}};
v_5.p_0 = v_5.p_1;
f7({p_0: 1.1, p_1: 1.1});
assert_type(v_5, {p_0: 1.1, p_1: 1.1});
assert_type(v_6, {p_0: {p_0: null}});
assert_type(v_7, {p_0: {p_0: null}});
assert_type(v_8, {p_0: {p_0: null}});
assert_type(v_9, {p_0: {p_0: null}});
function f4(param_0: {p_0: number, p_1: number}): void {
  assert_type(param_0, {p_0: 1.1, p_1: 1.1});
  param_0.p_1 = 1.1;
}
function f5(param_0: {p_0: number, p_1: number}): void {
  assert_type(param_0, {p_0: 1.1, p_1: 1.1});
  param_0.p_0 = v_5.p_0;
}
function f6(param_0: {p_0: number, p_1: number}): void {
  assert_type(param_0, {p_0: 1.1, p_1: 1.1});
  param_0.p_1 = 1.1;
}
function f7(param_0: {p_0: number, p_1: number}): void {
  assert_type(param_0, {p_0: 1.1, p_1: 1.1});
  param_0.p_1 = v_5.p_1;
}
function f8(param_0: {p_0: number, p_1: number}): void {
  assert_type(param_0, {p_0: 1.1, p_1: 1.1});
  param_0.p_1 = v_5.p_0;
}

/*
Env:
{p_0: void}
v_9.p_0 : {p_0: void}
({p_0: number, p_1: number}) => void
f6 : ({p_0: number, p_1: number}) => void
number
f7({p_0: 1.1, p_1: 1.1}) : void
{p_0: number, p_1: number}
f5({p_0: 1.1, p_1: 1.1}) : void
v_8 : {p_0: {p_0: void}}
{p_0: {p_0: number}}
{p_0: {p_0: 1.1}} : {p_0: {p_0: number}}
void | {p_0: {p_0: void}}
1.1 : number
v_5.p_1 : number
v_9 : {p_0: {p_0: void}}
{p_0: {p_0: {p_0: number, p_1: number}, p_1: number}}
{p_0: {p_0: v_5, p_1: v_5.p_1}} : {p_0: {p_0: {p_0: number, p_1: number}, p_1: number}}
{p_0: {p_0: void}} | {p_0: {p_0: void}}
"foo" : string
(number | string) | number
{p_0: number, p_1: number} | (({p_0: number, p_1: number}) => void)
v_5.p_0 : number
{p_0: {p_0: void}}
f4(v_5) : void
f4 : ({p_0: number, p_1: number}) => void
f8 : ({p_0: number, p_1: number}) => void
v_5 : {p_0: number, p_1: number}
f7 : ({p_0: number, p_1: number}) => void
f4({p_0: 1.1, p_1: 1.1}) : void
f5 : ({p_0: number, p_1: number}) => void
v_7 : {p_0: {p_0: void}}
{p_0: {p_0: f4({p_0: 1.1, p_1: 1.1})}} : {p_0: {p_0: void}}
v_6 : {p_0: {p_0: void}}
string
{p_0: 1.1, p_1: 1.1} : {p_0: number, p_1: number}
number | string
void
*/
