-- in.cue --
a: close({
	a: b: int
})

b: a & {x: int}    // err
c: a & {a: c: int} // okay (non-recursive close)

inDisjunctions: {
	x: [string]: #Def
	#Def: [string]: {
		a: b: true
		let X = a
		close({uint: a: b: X.b}) | close({string: a: b: true})
	}
	x: socket: string: {}
	x: syslog: x.socket
	x: syslog: xxx: {}
}

// issue642: Tests that close() with merged struct patterns (concrete fields and
// bulk optional) correctly allows subfields. https://cuelang.org/issue/642
issue642: {
	test: close({
		a: _
		b: x: _
	} & {
		[string]: y: _
	})

	test: a: x: _
	test: b: x: _
}

// Issue 642
withSubfields: {
	test: close({
		a: _
		b: x:        _
		[string]: y: _
	})

	test: a: x: _
	test: b: x: _
}

// issue3572: Tests that close({...}) allows additional fields when unified
// with an open struct. https://cuelang.org/issue/3572
issue3572: {
	t1: close({...}) & {a: 5}

	e: close({...}) // TODO: @test(allows=expr)

	t2: e & {a: 5}
}

// issue3580: Tests that close() does not panic when a field inside the closed
// struct references another field of the same struct. https://cuelang.org/issue/3580
issue3580: {
	x: close({
		a: _
		b: x.a
	})
}
-- embed.cue --
nestedEmbedded: base: {
	close({foo?: close({foo?: _})})
	foo: allowed: 5
}
nestedEmbedded: t1: {
	{close({foo?: close({foo?: _})})}
	foo: allowed: 5
}
nestedEmbedded: t2: {
	{{close({foo?: close({foo?: _})})}}
	foo: allowed: 5
}
unified: base: {
	x: close({foo?: close({foo?: _})})
	x: foo: disallowed: 5
}
unified: t1: {
	x: {close({foo?: close({foo?: _})})}
	x: foo: disallowed: 5
}
unified: t2: {
	x: {{close({foo?: close({foo?: _})})}}
	x: foo: disallowed: 5
}
nestedWithSelfReference: t1: {
	_schema: close({
		foo?: _schema
	})
	// TODO(inline): make work for hidden fields.
	// @test(err, at=_schema.foo, code=structural_cycle)
	// @test(shareID=S, at=x.foo.foo)

	x: {_schema}
	x: foo: disallowed: 5
}
nestedWithSelfReference: t2: {
	_schema: close({
		foo?: _schema
	})
	// TODO(inline): make work for hidden fields.
	// @test(err, at=foo, code=structural_cycle)
	x: {{_schema}}
	x: foo: disallowed: 5
}
-- out/compile --
--- embed.cue
{
  nestedEmbedded: {
    base: {
      close({
        foo?: close({
          foo?: _
        })
      })
      foo: {
        allowed: 5
      }
    }
  }
  nestedEmbedded: {
    t1: {
      {
        close({
          foo?: close({
            foo?: _
          })
        })
      }
      foo: {
        allowed: 5
      }
    }
  }
  nestedEmbedded: {
    t2: {
      {
        {
          close({
            foo?: close({
              foo?: _
            })
          })
        }
      }
      foo: {
        allowed: 5
      }
    }
  }
  unified: {
    base: {
      x: close({
        foo?: close({
          foo?: _
        })
      })
      x: {
        foo: {
          disallowed: 5
        }
      }
    }
  }
  unified: {
    t1: {
      x: {
        close({
          foo?: close({
            foo?: _
          })
        })
      }
      x: {
        foo: {
          disallowed: 5
        }
      }
    }
  }
  unified: {
    t2: {
      x: {
        {
          close({
            foo?: close({
              foo?: _
            })
          })
        }
      }
      x: {
        foo: {
          disallowed: 5
        }
      }
    }
  }
  nestedWithSelfReference: {
    t1: {
      _schema: close({
        foo?: 〈1;_schema〉
      })
      x: {
        〈1;_schema〉
      }
      x: {
        foo: {
          disallowed: 5
        }
      }
    }
  }
  nestedWithSelfReference: {
    t2: {
      _schema: close({
        foo?: 〈1;_schema〉
      })
      x: {
        {
          〈2;_schema〉
        }
      }
      x: {
        foo: {
          disallowed: 5
        }
      }
    }
  }
}
--- in.cue
{
  a: close({
    a: {
      b: int
    }
  })
  b: (〈0;a〉 & {
    x: int
  })
  c: (〈0;a〉 & {
    a: {
      c: int
    }
  })
  inDisjunctions: {
    x: {
      [string]: 〈1;#Def〉
    }
    #Def: {
      [string]: {
        a: {
          b: true
        }
        let X#1 = 〈0;a〉
        (close({
          uint: {
            a: {
              b: 〈3;let X#1〉.b
            }
          }
        })|close({
          string: {
            a: {
              b: true
            }
          }
        }))
      }
    }
    x: {
      socket: {
        string: {}
      }
    }
    x: {
      syslog: 〈1;x〉.socket
    }
    x: {
      syslog: {
        xxx: {}
      }
    }
  }
  issue642: {
    test: close(({
      a: _
      b: {
        x: _
      }
    } & {
      [string]: {
        y: _
      }
    }))
    test: {
      a: {
        x: _
      }
    }
    test: {
      b: {
        x: _
      }
    }
  }
  withSubfields: {
    test: close({
      a: _
      b: {
        x: _
      }
      [string]: {
        y: _
      }
    })
    test: {
      a: {
        x: _
      }
    }
    test: {
      b: {
        x: _
      }
    }
  }
  issue3572: {
    t1: (close({
      ...
    }) & {
      a: 5
    })
    e: close({
      ...
    })
    t2: (〈0;e〉 & {
      a: 5
    })
  }
  issue3580: {
    x: close({
      a: _
      b: 〈1;x〉.a
    })
  }
}
