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.
In 74d979f0ac, the policy was changed
so that only value type accessors are ever marked transparent, and
not class accessors.
This was intended to fix a bug where inlining an accessor of an
Objective-C-derived class across module boundaries caused a linker
failure because the accessor referenced a field offset variable,
which has hidden visibility.
However, this also caused a performance regression for Swift native
classes. Bring back the old behavior for Swift native classes in
non-resilient modules.
Fixes <rdar://problem/29884727>.
SubstitutionList is going to be a more compact representation of
a SubstitutionMap, suitable for inline allocation inside another
object.
For now, it's just a typedef for ArrayRef<Substitution>.
The problem is that the derived property's materializeForSet was
being synthesized after recordOverride() was called, so the new
accessor never got setOverridenDecl() called on it.
As a result, SIL didn't know that the derived materializeForSet
should replace the vtable entry for the base class materializeForSet.
The more fundamental problem here is that even after some recent
cleanups, accessors are still sometimes type checked before
the AbstractStorageDecla and sometimes after. So things like
inferring final, dynamic and overrides have to be duplicated in
multiple places.
Fixes <https://bugs.swift.org/browse/SR-3840> and
<rdar://problem/30336146>.
The problem is that the derived property's materializeForSet was
being synthesized after recordOverride() was called, so the new
accessor never got setOverridenDecl() called on it.
As a result, SIL didn't know that the derived materializeForSet
should replace the vtable entry for the base class materializeForSet.
The more fundamental problem here is that even after some recent
cleanups, accessors are still sometimes type checked before
the AbstractStorageDecla and sometimes after. So things like
inferring final, dynamic and overrides have to be duplicated in
multiple places.
Fixes <https://bugs.swift.org/browse/SR-3840> and
<rdar://problem/30336146>.
Fixes SR-2757.
Variables in capture lists are treated as 'let' constants, which can
result in misleading, incorrect diagnostics. Mark them as such in order
to produce better diagnostics, by adding an extra parameter to the
VarDecl initializer.
Alternatively, these variables could be marked as implicit, but that
results in other diagnostic problems: capture list variables that are
never used produce warnings, but these warnings aren't normally emitted for
implicit variables. Other assertions in the compiler also misfire when
these variables are treated as implicit.
Another alternative would be to walk up the AST and determine whether
the `VarDecl`, but there doesn't appear to be a way to do so.
Previously, validateDecl() would check if the declaration had an
interface type and use that as an indication not to proceed.
However for functions we can only set an interface type after
checking the generic signature, so a recursive call to validateDecl()
on a function would "steal" the outer call and complete validation.
For generic types, this meant we could have a declaration with a
valid interface type but no generic signature.
Both cases were problematic, so narrow workarounds were put in
place with additional new flags. This made the code harder to
reason about.
This patch consolidates the flags and establishes new invariants:
- If validateDecl() returns and the declaration has no interface
type and the isBeingValidated() flag is not set, it means one
of the parent contexts is being validated by an outer recursive
call.
- If validateDecl() returns and the declaration has the
isBeingValidated() flag set, it may or may not have an interface
type. In this case, the declaration itself is being validated
by an outer recursive call.
- If validateDecl() returns and the declaration has an interface
type and the isBeingValidated() flag is not set, it means the
declaration and all of its parent contexts are fully validated
and ready for use.
In general, we still want name lookup to find things that have an
interface type but are not in a valid generic context, so for this
reason nominal types and associated types get an interface type as
early as possible.
Most other code only wants to see fully formed decls, so a new
hasValidSignature() method returns true iff the interface type is
set and the isBeingValidated() flag is not set.
For example, while resolving a type, we can resolve an unqualified
reference to a nominal type without a valid signature. However, when
applying generic parameters, the hasValidSignature() flag is used
to ensure we error out instead of crashing if the generic signature
has not yet been formed.
- The DeclContext versions of these methods have equivalents
on the DeclContext class; use them instead.
- The GenericEnvironment versions of these methods are now
static methods on the GenericEnvironment class. Note that
these are not made redundant by the instance methods on
GenericEnvironment, since the static methods can also be
called with a null GenericEnvironment, in which case they
just assert that the type is fully concrete.
- Remove some unnecessary #includes of ArchetypeBuilder.h
and GenericEnvironment.h. Now changes to these files
result in a lot less recompilation.
Changes:
* Terminate all namespaces with the correct closing comment.
* Make sure argument names in comments match the corresponding parameter name.
* Remove redundant get() calls on smart pointers.
* Prefer using "override" or "final" instead of "virtual". Remove "virtual" where appropriate.
First, ensure all ParamDecls that are synthesized from scratch are given
both a contextual type and an interface type.
For ParamDecls written in source, add a new recordParamType() method to
GenericTypeResolver. This calls setType() or setInterfaceType() as
appropriate.
Interestingly enough a handful of diagnostics in the test suite have
improved. I'm not sure why, but I'll take it.
The ParamDecl::createUnboundSelf() method is now only used in the parser,
and no longer sets the type of the self parameter to the unbound generic
type. This was wrong anyway, since the type was always being overwritten.
This allows us to remove DeclContext::getSelfTypeOfContext().
Also, ensure that FuncDecl::getBodyResultTypeLoc() always has an interface
type for synthesized declarations, eliminating a mapTypeOutOfContext()
call when computing the function interface type in configureInterfaceType().
Finally, clean up the logic for resolving the DynamicSelfType. We now
get the interface or contextual type of 'Self' via the resolver, instead
of always getting the contextual type and patching it up inside
configureInterfaceType().
After recent changes, this asserts on all decls that are not VarDecls,
so we can just enforce that statically now. Interestingly, this turns
up some dead code which would have asserted immediately if called.
Also, replace AnyFunctionRef::getType() with
AnyFunctionRef::getInterfaceType(), since the old
AnyFunctionRef::getType() would just assert when called on
a Decl.
Previously, getInterfaceType() would return getType() if no
interface type was set. Instead, always set an interface type
explicitly.
Eventually we want to remove getType() altogether, and this
brings us one step closer to this goal.
Note that ParamDecls are excempt from this treatment, because
they don't have a proper interface type yet. Cleaning this up
requires more effort.