# Only strip optional properties from unsealed tables during subtyping **Status**: Implemented ## Summary Currently subtyping allows optional properties to be stripped from table types during subtyping. This RFC proposes only allowing that when the subtype is unsealed and the supertype is sealed. ## Motivation Table types can be *sealed* or *unsealed*. These are different in that: * Unsealed table types are *precise*: if a table has unsealed type `{ p: number, q: string }` then it is guaranteed to have only properties `p` and `q`. * Sealed tables support *width subtyping*: if a table has sealed type `{ p: number }` then it is guaranteed to have at least property `p`, so we allow `{ p: number, q: string }` to be treated as a subtype of `{ p: number }` * Unsealed tables can have properties added to them: if `t` has unsealed type `{ p: number }` then after the assignment `t.q = "hi"`, `t`'s type is updated to be `{ p: number, q: string }`. * Unsealed tables are subtypes of sealed tables. Currently we allow subtyping to strip away optional fields as long as the supertype is sealed. This is necessary for examples, for instance: ```lua local t : { p: number, q: string? } = { p = 5, q = "hi" } t = { p = 7 } ``` typechecks because `{ p : number }` is a subtype of `{ p : number, q : string? }`. Unfortunately this is not sound, since sealed tables support width subtyping: ```lua local t : { p: number, q: string? } = { p = 5, q = "hi" } local u : { p: number } = { p = 5, q = false } t = u ``` ## Design The fix for this source of unsoundness is twofold: 1. make all table literals unsealed, and 2. only allow stripping optional properties from when the supertype is sealed and the subtype is unsealed. This RFC is for (2). There is a [separate RFC](unsealed-table-literals.md) for (1). ## Drawbacks This introduces new type errors (it has to, since it is fixing a source of unsoundness). This means that there are now false positives such as: ```lua local t : { p: number, q: string? } = { p = 5, q = "hi" } local u : { p: number } = { p = 5, q = "lo" } t = u ``` These false positives are so similar to sources of unsoundness that it is difficult to see how to allow them soundly. ## Alternatives We could just live with unsoundness.