We want to compute the former independently of the latter.
It's only 16 bits so storing it inside the Decl is fine;
it also allows us to eliminate the 'compact' representation
where an AbstractStorageDecl without an accessor record is
assumed to be stored.
Since getStoredProperties() is a request that lowers lazy properties
and property wrappers to their underlying storage, and SIL can validate
stored property and enum element types, there's no longer any need for
Sema to explicitly finalize members of structs and enums. SILGen can
trigger any necessary type checkin work just by lowering a struct or
enum type.
Now the only remaining reason we need finalizeDecl() is adding implicit
methods to classes, and synthesizing accessors for storage in classes
and protocols.
The idea here is to split up the logic into three parts:
- computation of the final ImplInfo for lazy, property wrappers
and @NSManaged
- deciding if we should add accessors or not
- actually adding the accessors
Instead of requiring that function body synthesizers will always call
setBody(), which is annoyingly stateful, have function body synthesizers
always return the synthesized brace statement along with a bit that
indicates whether the body was already type-checked. This takes us a
step closer to centralizing the mutation of the body of a function.
Also since we're lazier about validating accessors now, relax some
checks in the ASTVerifier so that it can tolerate implicit accessors
without interface types. All other declarations must still have
interface types in verifyChecked().
ASTVerifier: Tolerate implicit accessors without interface types
Extend handling of enclosing-self subscripts by differentiating
between the original wrapped property (which now goes through
`subscript(_enclosingInstance:wrapped:storage:)`) and the projected
property (which goes through
`subscript(_enclosingInstance:projected:storage:)`). The new middle
argument provides a key path to the property that was accessed,
allowing one to distinguish the property being updated.
Allow property wrapper types to support a second access pattern for
instance properties of classes. When supported, the property wrapper's
static subscript(_enclosingInstance:storage:) is provided with the
enclosing "self" and a reference-writable key path referring to the
backing storage property.
Implements rdar://problem/52222560.
Fix a bug with cross-file uses of the synthesized _foo/$foo for
properties with attached wrappers by implicitly triggering the
appropriate synthesis during name lookup.
Fixes rdar://problem/51725203.
When the outermost property wrapper associated with a property has a
`wrapperValue`, create the projection property (with the `$` prefix)
at the same access level as the original property. This puts the
wrapped-value interface and the projection interface at the same level.
The newly-introduced @_projectionValueProperty attribute is implicitly
created to establish the link between the original property and the
projection value within module interfaces, where both properties will
be explicitly written out.
My recent refactoring of default arguments for the memberwise initializer
accidentally dropped support for getting a default argument when the
attached property wrapper has an init(). Reinstate that support,
fixing rdar://problem/52116923.
If a stored property has a didSet/willSet, we currently synthesize
the getter and the setter inside the parser. I want to get rid of
the parser's code path for doing that and consolidate all accessor
synthesis here in Sema.
Note that the parser did not synthesize a modify. This is now more
explicit in the code.
Also, we have to relax an assertion since addMemberToContextIfNeeded()
now gets called on declarations in local contexts.
Allow both explicit initialization and initial values to work together, e.g.,
```
@Clamping(min: 0, max: 255) var red: Int = 127
```
gets initialized as
```
Clamping(initialValue: 127, min: 0, max: 255)
```
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".
By calling isFinal() first in makeFinal(), we were triggering
computation of IsFinalRequest and caching a value of 'false'.
With lazy properties, we did direct storage access, and no
accessors were synthesized anyway, but add a test for that.
With property wrappers this now means the backing storage
property is final, as intended (?).
When the backing storage of a wrapped property is default-initialized via the
property wrapper type's init(), don't count that as a direct initialization
of the backing storage for the purposes of constructing the memberwise
initializer. Instead, treat this case the same as if there were no initializer,
keying the form of the memberwise initializer off the presence of
init(initialValue:).
Various optimizations / shortcuts in type checking property wrappers meant
that we weren't consistently verifying that a wrapped property type is
identical to the type of the 'value' property of the wrapper. Do so.
Fixes SR-10899 / rdar://problem/51588022.
Previously, we'd clone the superclass's initializer and update its
interface type, but we didn't reset the TypeLoc. This meant the
synthesized overridden initializer's parameter typeLocs would still be in
the parent decl context, which caused the ASTPrinter to print the
unsubstituted type.
rdar://50914733
Similarly to trivial accessors, the body of a synthesized
designated initializer override is simple enough that we can
build it directly without involving the constraint solver.