Fixes rdar://problem/53407949 | SR-11138. Previously, we'd only look at the outermost property wrapper to decide whether the wrapped property's getter and setter were `mutating` (or exist at all). In reality, this requires considering the semantics of the composed accesses of each wrapper layer's
`wrappedValue` property. Fixing this systematically addresses a number of issues:
- As SR-11138 reported, composing a nonmutating-get-set wrapper ought to produce a composed wrapper
that's nonmutating.
- We would previously allow a property wrapper with a mutating getter to be nested inside one with
only a getter, even though the resulting implementation was unsound (because there's no mutable
context for the inner wrapper to execute its get on.)
- Similarly, we would construct unsound setters in cases where the setter can't exist, such as when
the nested wrapper isn't settable but the outer wrapper is.
When multiple property wrapper attributes are provided on a declaration,
compose them outside-in to form a composite property wrapper type. For
example,
@A @B @C var foo = 17
will produce
var $foo = A(initialValue: B(initialValue: C(initialValue: 17)))
and foo's getter/setter will access "foo.value.value.value".
Introduce another form of debugging dump for the evaluator, rendering the
complete dependency graph using GraphViz, including all dependencies and
values cached within the evaluator.
Introduce a CRTP base class, SimpleRequest, which simplifies the task of
defining a new request kind by handling the storage of the values (in a
std::tuple), their hashing, equality, printing, etc. The values are passed
along to the subclass’s operator() so they’re mostly treated as (const)
parameters, making mutation of the request state impossible.
Extend AnyValue and AnyRequest with printing logic, so we can print any
request for debugging purposes, and
Meant as a replacement for the barely-started iterative type checker,
introduce a simpler "evaluator" that can evaluate individual requests
(essentially, function objects with some additional API), caching
results as appropriate and detecting cycles.