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.
My recent refactoring of witnesses in Sema and the AST disabled a
test for property behaviors, because they were no longer handling
substitutions correctly. Introduce a type checker entrypoint to record
information about a known witness, using the normal witness-matching
logic rather than trying to synthesize the correct answer (and getting
it wrong).
Note that I had to manually introduce some type witnesses to get the
property behavior tests passing, because the property-behavior code is
(intentionally) not introducing implicit typealiases for the type
witnesses it synthesized. The old witness-synthesizing code worked
around this issue, but the new code does not. A different fix is in
the works (i.e., better handling of type witnesses in the constraint
solver), so we'll take this temporary regression in an experimental
feature.
Reimplement the witness matching logic used for generic requirements
so that it properly models the expectations required of the witness,
then captures the results in the AST. The new approach has a number of
advantages over the existing hacks:
* The constraint solver no longer requires hacks to try to tangle
together the innermost archetypes from the requirement with the
outer archetypes of the context of the protocol
conformance. Instead, we create a synthetic set of archetypes that
describes the requirement as it should be matched against
witnesses. This eliminates the infamous 'SelfTypeVar' hack.
* The type checker no longer records substitutions involving a weird
mix of archetypes from different contexts (see above), so it's
actually plausible to reason about the substitutions of a witness. A
new `Witness` class contains the declaration, substitutions, and all
other information required to interpret the witness.
* SILGen now uses the substitution information for witnesses when
building witness thunks, rather than computing all of it from
scratch. ``substSelfTypeIntoProtocolRequirementType()` is now gone
(absorbed into the type checker, and improved from there), and the
witness-thunk emission code is simpler. A few other bits of SILGen
got simpler because the substitutions can now be trusted.
* Witness matching and thunk generation involving generic requirements
and nested generics now works, based on some work @slavapestov was
already doing in this area.
* The AST verifier can now verify the archetypes that occur in witness substitutions.
* Although it's not in this commit, the `Witness` structure is
suitable for complete (de-)serialization, unlike the weird mix of
archetypes previously present.
Fixes rdar://problem/24079818 and cleans up an area that's been messy
and poorly understood for a very, very long time.
Targeted fix for SR-2673: if a potential protocol witness is
@NSManaged, add accessors the NSManaged way, not the stored property
way.
There's probably more weirdness around here, so I'll clone the bug to
go through maybeAddAccessorsToVariable a lot more often. (Lazy
properties could easily be broken in the same way.)
While the use of a local property from within its own accessors is a
bit dubious, Swift 3 only warned on it, so model the existing lookup
behavior in the scope map.
SILType substitutions are still done with the old form, and until
BoundGenericTypes hold conformances, we still have to pass around
a ModuleDecl in a few places we really shouldn't, but one step
at a time.
Lazy property initializers can refer to 'self' either directly or
implicitly (via references to instance members). Model this in
ASTScope-based unqualified name lookup.
Note that the modeling of 'self' with the current name lookup
mechanism is broken, so when ASTScope-based unqualified name lookup is
enabled, it fixes SR-2203, rdar://problem/16954496, and the many dupes
of the latter.
This patch is rather large, since it was hard to make this change
incrementally, but most of the changes are mechanical.
Now that we have a lighter-weight data structure in the AST for mapping
interface types to archetypes and vice versa, use that in SIL instead of
a GenericParamList.
This means that when serializing a SILFunction body, we no longer need to
serialize references to archetypes from other modules.
Several methods used for forming substitutions can now be moved from
GenericParamList to GenericEnvironment.
Also, GenericParamList::cloneWithOuterParameters() and
GenericParamList::getEmpty() can now go away, since they were only used
when SILGen-ing witness thunks.
Finally, when printing generic parameters with identical names, the
SIL printer used to number them from highest depth to lowest, by
walking generic parameter lists starting with the innermost one.
Now, ambiguous generic parameters are numbered from lowest depth
to highest, by walking the generic signature, which means test
output in one of the SILGen tests has changed.
A GenericEnvironment stores the mapping between GenericTypeParamTypes
and context archetypes (or eventually, concrete types, once we allow
extensions to constrain a generic parameter to a concrete type).
The goals here are two-fold:
- Eliminate the GenericTypeParamDecl::getArchetype() method, and
always use mapTypeIntoContext() instead
- Replace SILFunction::ContextGenericParams with a GenericEnvironment
This patch adds the new data type as well as serializer and AST
verifier support. but nothing else uses it yet.
Note that GenericSignature::get() now asserts if there are no
generic parameters, instead of returning null. This requires a
few tweaks here and there.
This is the first, and most trivial, usage of the new
GenericSignature::getSubstitutions() method.
Note that getForwardingSubstitutions() now takes a
GenericSignature, which is slightly awkward.
However, this is in line with our goal of 'hollowing out'
GenericParamList by removing knowledge of the finalized
generic requirements.
Also, there is now a new getForwardingSubstitutionMap()
function, which returns an interface type substitution
mapping. This is used in the new getForwardingSubstitutions()
implementation, and all also be used elsewhere later.
Finally, in the SILFunction we now cache the forwarding
substitutions, instead of re-computing them every time.
I doubt this makes a big difference in performance, but
it's a simple enhancement and every little bit helps.
Factor out the trailing storage of call arguments, since we'll need it
for a few different kinds of expression nodes. Use it for both
CallExpr (which already had this storage, albeit with a specialized
implementation) and now SubscriptExpr.
Yet another step on the way to SE-0111, capture the argument labels
(and their locations) directly in CallExpr, rather than depending on
them being part of the tuple argument.
More detail: some members are intended to have the same the access as
their containing types. This doesn't fly for SE-0025 'private', which
would limit the members to only being accessed from lexically within
the type decl, instead anywhere the type itself can be seen. Instead,
follow the rule for user-written members---internal by default---and
then raise the access level to 'public' if necessary. This affects:
- enum cases
- deinitializers
- protocol requirements
- generic parameters
- implicit initializers
- inherited initializers
- derived conformance members
- synthesized typealiases for associated types
Introduce several new factory methods to create CallExprs, and hide
the constructor. The primary reason for this refactor is to start
moving clients over to the factory method that takes the call
arguments separately from the argument labels. Internally, it
repackages those arguments into a TupleExpr or ParenExpr (as
appropriate) so the result ASTs are the same. However, this will make
it easier for us to tease out the arguments themselves in the
implementation of SE-0111.
Start chipping away at cross-file type checker performance issues by
avoiding type checking of lazy property accessor bodies when the type in
question is defined in a different file and the lazy property is a typed
pattern.
We still type check these in the file they are defined in when we go to
type check the types defined within that file.
Resolves rdar://problem/26894118.
Previously getInterfaceType() would punt to getType() if no
interface type was set. This patch changes getInterfaceType()
to assert if no interface type is set, and updates various
places to set the interface type explicitly.
This brings us a step closer to removing PolymorphicFunctionType.
The code in recordTypeWitness() seemed to be completely bogus;
it already receives a type written in terms of the archetypes
of the adoptee's context, so mapTypeOutOfContext() did nothing
here, because it was using the wrong substitutions.
The logic for synthesizing designated initializers was also
slightly wrong if the class was nested inside a generic
function.
Finally, interface and contextual types of a derived rawValue
were flipped around.
Before we would construct types containing a mix of interface and
contextual types, and then map them in and out. Straighten this out.
Note that I've also had to start untangling the issue where
synthesized ParamDecls do not have an interface type.