Open jclark opened 2 years ago
What makes this difficult is that this cannot be specified in terms of pure types (sets of shapes), since we need to apply default values which are not included in the type. The spec currently describes this in terms of the type descriptor and deals with just unions (by eliminating those members of the union that are not applicable).
But this is not really sufficient: we need to do some amount of processing on the type descriptor (for example to resolve references). We also need to select out the relevant basic type from the type descriptor (the spec does this currently with the concept of an applicable basic type).
The simplest way to do this is to specify a normalized form of the applicable contextually expected type. For a contextually expected type T, the applicable contextually expected type means T & B
where B is (any|error)[]
for list constructors and map<any|error>
for mapping constructors. The normalized form is a union, where each member of the union is either an atomic type descriptor A
or an intersection
readonly & A`. An atomic type descriptor is a tuple type descriptor in the list case or a record type descriptor in the mapping case.
This normalization process is applied to a syntax tree. I will describe it for the mapping case. It can be broken down into the following steps.
json
, any
, anydata
), stopping when you get to
never
readonly
type descriptor; in this case, leave as isreadonly
, never
. Now, get rid of never
by using the identities T|never == T
and T&never == never
. If the whole descriptor is never
, then that is treated as union with no members.T1 & (T2|T3)
becomes (T1 & T2)|(T1 & T3)
. This leaves a union, where each member is an intersection whose members are readonly
, record type descriptors or constants.R1 & R2
into a single record type descriptor R
: R
will have an individual field descriptor for every field name f
that occurring in R1
or R2
; the type of the field is the intersection of the types from R1
and R2
. If this produces a required field with type never
, then the record type descriptor is replaced by never
and never
is removed as in step 2. XXX need to handle constants hereThere's another subtlety: it need not be an error if we end up with more than one alternative if all of them are readonly, since in the readonly case we do not need an inherent type.
In #544 we will handle just intersection with readonly. This issue will handle defaults in the general case as described here https://github.com/ballerina-platform/ballerina-spec/issues/544#issuecomment-1199267849
Also need to handle annotations (as in #1258).
Currently the spec handles unions in the contextually expected type for mapping and list constructors, but not intersections.
The cloneWithType/fromJsonWithType functions work similarly to constructors and should also be able to handle intersections. This can happen when using Open API with a JSON schema that uses
allOf
.One important special case is intersection with
readonly
.This is a precondition to #544.
Edited: #544 will deal just with case of intersection with
readonly