When emitting accessor calls for keypaths, make sure that we reference
protocol requirements that introduce witness table entries. Other
protocol requirements don't have the necessary dispatch thunks,
resulting in linker errors.
Fixes rdar://problem/44187969.
When forming a witness_method instruction, follow the override chain of
a protocol requirement to reach a requirement that doesn’t override any
other protocol requirement. These will be the requirements that introduce
new witness table entries.
This is NFC for now, but I plan to build on this to (1) immediately
remove some unnecessary materialization and loads of the base value
and (2) to allow clients to load a borrowed value.
Print parens and "_:" in cases where a function has no named
parameters.
We already print the parens in cases with no parameters, and the "_:"
for unnamed parameters in cases where there are already named
parameters.
Fixes: rdar://problem/19785368
Delay allocating the result buffer for an opened Self return until right before it's needed. When a mutating method is invoked on an existential, the Self type won't be opened until late, when the formal access to the mutable value begins. Fixes rdar://problem/43507711.
Most of this patch is just removing special cases for materializeForSet
or other fairly mechanical replacements. Unfortunately, the rest is
still a fairly big change, and not one that can be easily split apart
because of the quite reasonable reliance on metaprogramming throughout
the compiler. And, of course, there are a bunch of test updates that
have to be sync'ed with the actual change to code-generation.
This is SR-7134.
I needed this for materializeForSet remission, but it makes inherited
variadic initializers work, too.
I tried to make this a reasonable starting point for a real language
feature. Here's what's still missing:
- syntax
- semantic restrictions to ensure that the expression isn't written in
invalid places or arbitrarily converted
- SILGen support for expansions that aren't the only variadic argument
rdar://16331406
This makes it easier to grep for and eventually remove the
remaining usages.
It also allows you to write FunctionType::get({}, ...) to call the
ArrayRef overload empty parameter list, instead of picking the Type
overload and calling it with an empty Type() value.
While I"m at it, in a few places instead of renaming just clean up
usages where it was completely mechanical to do so.
- getAsDeclOrDeclExtensionContext -> getAsDecl
This is basically the same as a dyn_cast, so it should use a 'getAs'
name like TypeBase does.
- getAsNominalTypeOrNominalTypeExtensionContext -> getSelfNominalTypeDecl
- getAsClassOrClassExtensionContext -> getSelfClassDecl
- getAsEnumOrEnumExtensionContext -> getSelfEnumDecl
- getAsStructOrStructExtensionContext -> getSelfStructDecl
- getAsProtocolOrProtocolExtensionContext -> getSelfProtocolDecl
- getAsTypeOrTypeExtensionContext -> getSelfTypeDecl (private)
These do /not/ return some form of 'this'; instead, they get the
extended types when 'this' is an extension. They started off life with
'is' names, which makes sense, but changed to this at some point. The
names I went with match up with getSelfInterfaceType and
getSelfTypeInContext, even though strictly speaking they're closer to
what getDeclaredInterfaceType does. But it didn't seem right to claim
that an extension "declares" the ClassDecl here.
- getAsProtocolExtensionContext -> getExtendedProtocolDecl
Like the above, this didn't return the ExtensionDecl; it returned its
extended type.
This entire commit is a mechanical change: find-and-replace, followed
by manual reformatted but no code changes.
1) It's possible to materialize a tuple value with an @escaping or
@autoclosure element in it.
I don't think this causes any bad behavior in 4.2 because these
flags have no semantic effect after the type checker, but now
I'm adding an assertion that will fire when such types are
serialized, so let's make sure it doesn't happen by explicitly
clearing out these flags when lowering tuples types.
2) It's also possible to materialize a tuple with a single vararg
element. Again, this was not a problem in 4.2, but with the above
change to start clearing tuple flags, we now end up in a
situation where the lowered type is not a tuple, because
TupleType::get() returns a ParenType if the tuple has one
element that is not vararg (which it no longer is, because we
just cleared all the flags).
Fix the second problem by treating one-element vararg tuples just
like tuples with inout, __shared and __owned elements, that is,
by always exploding them when they appear at the top level of a
function parameter list, ensuring we never try to materialize
a value whose type is the entire tuple type.
These problems all stem from the fact that lowering a function type
with the opaque abstraction pattern treats the top level argument
list as a single tuple argument. Once that is fixed, much of the
above will simplify down to assertions.
Even with an opaque abstraction pattern, we must explode a
parameter list containing __shared and __owned elements.
Otherwise, we produce invalid lowered SIL types.
Note that this is already an issue, because the stdlib has a
handful of declarations using __owned.
Add an abstraction to retrieve a name suitable for display for a given
source location for use with diagnostics, debug locations, and magic
file literals.
print and parse as a stable hexadecimal form that isn't interpreted as UTF8.
One use case is in representing serialized protobuf strings (as in the
tensorflow branch: f7ed452eba/lib/SILOptimizer/Mandatory/TFPartition.cpp (L3875)).
The original work was done by @lattner and merged into the tensorflow
branch. This PR is to upstream those changes.
For now, the accessors have been underscored as `_read` and `_modify`.
I'll prepare an evolution proposal for this feature which should allow
us to remove the underscores or, y'know, rename them to `purple` and
`lettuce`.
`_read` accessors do not make any effort yet to avoid copying the
value being yielded. I'll work on it in follow-up patches.
Opaque accesses to properties and subscripts defined with `_modify`
accessors will use an inefficient `materializeForSet` pattern that
materializes the value to a temporary instead of accessing it in-place.
That will be fixed by migrating to `modify` over `materializeForSet`,
which is next up after the `read` optimizations.
SIL ownership verification doesn't pass yet for the test cases here
because of a general fault in SILGen where borrows can outlive their
borrowed value due to being cleaned up on the general cleanup stack
when the borrowed value is cleaned up on the formal-access stack.
Michael, Andy, and I discussed various ways to fix this, but it seems
clear to me that it's not in any way specific to coroutine accesses.
rdar://35399664
There were several bits of code which were unnecessarily
repeating the core logic of breaking down an access strategy
and either setting up an LValue or directly emitting it.
These places have now been unified to just create and then
load or othrwise use an LValue.
Introduce a visitor which handles the common parts of breaking
down an access strategy and computing information like the
LValueTypeData. In addition to its direct benefits (which are
somewhat lost in the boilerplate of capturing local state into
the visitor subclass), this eliminates some of the ad-hocness
of how the various emission paths use AccessStrategy.
Finally, implement the MaterializeToTemporary strategy in its
full generality by using the actual read and write sub-strategies
instead of always falling back on calling the getter and setter.
This part is not NFC because it causes us to perform the read
part of a read/write to a stored-with-observers property by
directly accessing the storage instead of calling the getter.
This comes up when invoking protocol methods on an existential that have covariant arguments of function type with Self arguments, e.g.:
```swift
protocol P {
mutating func foo(_: (Self) -> Void)
}
func bar(x: inout P) {
x.foo { y in return }
}
```
Although the type-erased method is presented as formally taking an argument of the existential type P, it still has a conversion thunk to perform type erasure on the argument coming from the underlying implementation. Since the `self` argument is inout, it isn't formally opened until late when formal accesses begin, so this closure conversion must also be deferred until after that occurs.
The only time the generic signature of the callee won't
match the generic signature of the substitution map is when
the callee is a non-generic closure inside a generic context.
Instead of remapping substitutions it suffices to just drop
them.
SubstitutionMaps are now just a trivial pointer-sized value, so
pass them by value instead.
I did have to move a couple of functors from Type.h to SubstitutionMap.h
to resolve some issues with forward declarations.
This causes default arguments to get emitted after formal evaluation of `self`, allowing protocol methods to access the opened `Self` type of an existential receiver. Fixes rdar://problem/39524104
Turns out it's really expensive and not really needed. On my machine
the testcase reported in SR-7691 goes down from 24 seconds to 2 seconds
after this change.
<rdar://problem/40258978>
Introduced during the bring-up of the generics system in July, 2012,
Substitution (and SubstitutionList) has been completely superseded by
SubstitutionMap. R.I.P.