We don't want @_fixed_layout to apply to static properties, or you
get fun consequences like not being able to change static stored
properties defined in extensions of imported types to computed.
This has three principal advantages:
- It gives some additional type-safety when working
with known accessors.
- It makes it significantly easier to test whether a declaration
is an accessor and encourages the use of a common idiom.
- It saves a small amount of memory in both FuncDecl and its
serialized form.
Follow-up for 7c707ce97c. Without this, the declaration would be
accepted, but any uses of the overridden property would be treated as
ambiguous because the property wouldn't really be marked as an
override.
rdar://problem/35900345
Rather than storing contextual types in the type witnesses and associated
conformances of NormalProtocolConformance, store only interface types.
@huonw did most of the work here, and @DougGregor patched things up to
complete the change.
When overriding storage with a forced static dispatch materializeForSet,
the override's materializeForSet should not override the base
materializeForSet.
This is the case where a dynamic property witnesses a protocol
requirement, and Sema synthesizes a materializeForSet for it.
In this case, the synthesized materializeForSet dynamically dispatches
to the dynamic property's getter and setter, and the protocol witness
thunk directly calls the synthesized materializeForSet.
The subclass only needs to override the getter and setter in this case,
since the base class's materializeForSet will already do the right
thing.
In fact, marking it as an override exposes a problem where we cannot
serialize an xref to an imported property's materializeForSet, since
it was not created by the importer.
Follow-up to my earlier changes to drop 'inout' types when cloning parameter
lists, we also need to deal with substitutions into those parameter types.
This is an artifact of us having mostly---but not entirely---removed
InOutType from the AST. Fixes rdar://problem/34818336.
When type-checking a function or subscript that itself does not have generic
parameters (but is within a generic context), we were creating a generic
signature builder which will always produce the same generic signature as
the enclosing context. Stop creating that generic signature builder.
Instead, teach the CompleteGenericTypeResolver to use the generic signature
+ the canonical generic signature builder for that signature to resolve
types, which also eliminates some extraneous re-type-checking.
Improves type-checking performance of the standard library by 36%.
When type-checking a function or subscript that itself does not have generic
parameters (but is within a generic context), we were creating a generic
signature builder which will always produce the same generic signature as
the enclosing context. Stop creating that generic signature builder.
Instead, teach the CompleteGenericTypeResolver to use the generic signature
+ the canonical generic signature builder for that signature to resolve
types, which also eliminates some extraneous re-type-checking.
Improves type-checking performance of the standard library by 36%.
The base mutability of storage is part of the signature, so be sure
to compute that during validation. Also, serialize it as part of
the storage declaration, and fix some places that synthesize
declarations to set it correctly.
A lazy property setter stores a value to the underlying storage
of the lazy property. The underlying storage is private, and it
is not proper for a public transparent function body to reference
a private member.
In practice, this only failed if the private member had a
non-constant offset, which only occurs with subclasses of @objc
classes, and resilient classes.
For @objc classes we already had a workaround where no accessors
for stored properties are ever transparent. I put this in to fix
this very issue with lazy properties, but now I realize it was
the wrong workaround, because we still had this problem with
resilient classes.
Note that I'm keeping the logic which made @objc accessors
non-transparent in place, because there's a good chance we will
decide that field offset globals should always be private.
Also, to make this issue reproducible in the test, I changed the
resilience execution tests to build the resilient library as a
dylib and link against that instead of just linking .o files
together. This is because .o files can see each other's internal
symbols, so I was not able to reproduce the original failure
this way. I went ahead and updated the other resilient tests to
do this as well. Also, each test now builds in WMO and non-WMO
mode, to exercise different SIL linking behavior. Again, the
WMO variant was needed to reproduce the issue fixed by this
commit, because without WMO we currently discard serialized SIL,
so no cross-module inlining of the lazy property setter was
taking place.
"Accessibility" has a different meaning for app developers, so we've
already deliberately excised it from our diagnostics in favor of terms
like "access control" and "access level". Do the same in the compiler
now that we aren't constantly pulling things into the release branch.
This commit changes the 'Accessibility' enum to be named 'AccessLevel'.
Pushes __consuming through the frontend and extends existing
attribute-based diagnsotics to cover it. Unlike `nonmutating`,
__consuming is allowed in class methods, though it makes little
sense to put it there.
Also, begin to pass around base types instead of raw InOutType types. Ideally, only Sema needs to deal with them, but this means that a bunch of callers need to unwrap any inouts that might still be lying around before forming these types.
Multiple parts of the compiler were slicing, dicing, or just dropping these flags. Because I intend to use them for the new function type representation, I need them to be preserved all across the compiler. As a first pass, this stubs in what will eventually be structural rules as asserts and tracks down all callers of consequence to conform to the new invariants.
This is temporary.
In anticipation of future attributes, and perhaps the ability to
declare lvalues with specifiers other than 'let' and 'var', expand
the "isLet" bit into a more general "specifier" field.
- A mutating method or accessor always has 'inout self'.
- A nonmutating method or accessor never has 'inout self'.
- Only instance members can be mutating.
- Addressors are still addressors even when on static members.
Came up after reviewing another patch that confused the two as
possibly distinct concepts.
If synthesizeWitnessAccessorsForStorage() got called on a lazy
property before maybeAddAccessorsToVariable(), we would build
it as a stored property instead.
This count result in bogus diagnostics, assertions and bad runtime
behavior.
Fixes <https://bugs.swift.org/browse/SR-1825>.
Allow instance properties and methods to be referenced from
within a lazy property initializer, with or without explicit
'self.' qualification.
The old behavior in Swift 3 was an incredible combination
of odd quirks:
- If the lazy property had an explicitly-written type, it was
possible to reference instance members from the initializer
expression by explicitly prefixing 'self.'.
- However, if the lazy property type is inferred, it would
first be type checked in the initializer context, which
has no 'self' available.
- Unqualified references to instance members did not work
at all, because name lookup thought the "location" of the
lookup was outside of the body of the getter.
- Unqualified references to static properties worked, however
unqualified references to static methods did not, and
produced a bogus diagnostic, because one part of the name
lookup code thought that initializers were "instance
context" and another thought they were "static context".
This patch improves on the old behavior with the following
fixes:
- Give PatternBindingInitializers associated with lazy
properties an implicit 'self' declaration for use by
name lookup.
- In order to allow "re-parenting" the initializer after it
has been type checked into the body of the getter, "steal"
the initializer's 'self' when buiding the getter.
- Fix up name lookup and make it aware of the implicit
'self' decl of a PatternBindingInitializer.
This improves upon an earlier fix for this issue by Doug Gregor
which only worked with ASTScope enabled; the new fix is more
general and shares logic between the two name lookup
implementations.
Fixes <rdar://problem/16888679>, <https://bugs.swift.org/browse/SR-48>,
<https://bugs.swift.org/browse/SR-2203>,
<https://bugs.swift.org/browse/SR-4663>, and the countless other
dupes of this issue.
Uncovered by Slava's bcbd1d2, which infers 'dynamic' in more places,
but this was always a problem when an initializer was /explicitly/
marked 'dynamic'.
rdar://problem/32026930
This lets us serialize that decision, which means we can conceivably
/change/ the decision in later versions of the compiler without
breaking existing code. More immediately, it's groundwork that will
eventually allow us to drop decls from the AST without affecting
vtable layout.
This isn't actually a great answer; what we really want is for SIL
vtables to be serialized consistently and treated as the point of
truth. But that would be more change than we're comfortable taking in
the Swift 4 timeframe.
First part of rdar://problem/31878396.
Enums with the ns_error_domain attribute represent codes for NSError,
which means Swift developers will expect to interact with them in
terms of Error. SE-0112 improved bridging for these enums to generate
a struct with the following form:
struct MyError: Error {
@objc enum Code: RawRepresentable {
case outOfMemory
case fileNotFound
}
var userInfo: [NSObject: AnyObject] { get }
static var outOfMemory: Code { get }
static var fileNotFound: Code { get }
}
where MyError.Code corresponds to the original MyError enum defined in
Objective-C. Until recently, both the enum and the synthesized struct
were marked as having the original enum as their "Clang node", but
that leads to problems: the struct isn't really ObjC-compatible, and
the two decls have the same USR. (The latter had already been worked
around.)
This commit changes the struct to be merely considered a synthesized
"external definition", with no associated Clang node. This meant
auditing everywhere that's looking for a Clang node and seeing which
ones applied to external definitions in general.
There is one regression in quality here: the generated struct is no
longer printed as part of the Swift interface for a header file, since
it's not actually a decl with a corresponding Clang node. The previous
change to AST printing mitigates this a little by at least indicating
that the enum has become a nested "Code" type.
An assertion I added recently to check property overrides in
the ASTVerifier uncovered some bugs in this area:
- We did not synthesize a materializeForSet for properties
defined in extensions of imported classes unless they
witnessed a protocol requirement.
This triggered an assertion if the property had an
override that was checked before the protocol conformance,
since the override's materializeForSet would not be marked
as an override of the base materializeForSet.
- materializeForSet for properties defined in extensions would
statically dispatch the getter and setter instead of dynamically
dispatching. This is incorrect since we statically dispatch
to the materializeForSet in this case, and we can in fact
override it in a subclass.
Fixes <rdar://problem/31334272>.
In the old vtable emission code, IRGen would skip addressors,
but they had entries in the SILVTable. This is still correct
behavior, so skip addressors explicitly in SILVTableVisitor.
We never call addressors dynamically, only inside a getter,
setter or materializeForSet. When a property with addressors
is overridden we provide new getters and setters (which may
or may not statically dispatch to a peer addressor).
We had some non-deterministic behavior where depending on
validation order, synthesized accessors would end up in
different places because we would sometimes just add them
at the end of the member list.
Now add the getter right after the storage, the setter
right after the getter and the materializeForSet right
after the setter.
This changes some test output where the declaration order
did not make sense before but should otherwise have no
functional effect.