We want to eventually remove address phi arguments from SIL. This will enable
all sorts of nice IRGen optimizations and in general make life better. We are
not there yet, but given that is the direction we are going in, I don't think
there is much use in having to implement this sort of checking for SIL phi
arguments.
rdar://50676315
My intention is to use this checker to also verify that in_guaranteed arguments
are used in the same manner immutably. Beyond improving that in_guaranteed
parameters are properly used immutably (which is just goodness), by using the
same check it ensures that we can always inline a callee into a caller with an
open_existential_addr without violating any check on the oea instruction.
I am doing this separately from adding more checks/applying it to
in_guaranteed/fixing some exposed bugs for ease of review. This change is
completely mechanical.
rdar://50212579
We do not consider inout_aliasable to be "truly mutating" since today it is just
used as a way to mark a captured argument and not that something truly has
mutating semantics. The reason why this is safe is that the typechecker
guarantees that if our value was immutable, then the use in the closure must be
immutable as well.
In a future SIL, we want to remove Inout_Aliasable in favor of just using
inout/in_guaranteed using the capture info from the type checker.
rdar://50212579
I have been meaning to do this change for a minute, but kept on putting it off.
This describes what is actually happening and is a better name for the option.
This simplifies some boilerplate, and in particular, some SIL verifier
logic; and fixes a couple bugs related to always loadable reference
storage types.
yields in generalized accessors: _read and _modify, which are
yield-once corountines. This pass is based on the existing SIL verifier
checks but diagnoses only those errors that can be introduced by programmers
when using yields.
<rdar://43578476>
checked_cast_br in ownership SIL funnels through the original value to the
failure block as a SILArgument for cleanup purposes. In contrast, when SIL is
not in ossa, we do not want the failure bb case to have any arguments since that
is the pattern that SILOptimizer passes expect.
This commit just formalizes these constraints into the SILVerifier to catch
mistakes.
This method wasn’t returning the protocol on which the that the witness
method would satisfy, as documented. Rather, it was returning the protocol
to which the `Self` type conforms, which could be completely unrelated. For
example, in IndexingIterator’s conformance to IteratorProtocol, this method
would produce the protocol “Collection”, because that’s where the witness
itself was implemented. However, there isn’t necessarily a single such
protocol, so checking for/returning a single protocol was incorrect.
It turns out that there were only a few SIL verifier assertions of it
(that are trivially true) and two actual uses in code:
(1) The devirtualizer was using this computation to decide when it didn’t
need to perform any additional substitutions, but it’s predicate for doing
so was essentially incorrect. Instead, it really wanted to check whether
the Self type is still a type parameter.
(2) Our polymorphic convention was using it to essentially check whether
the ’Self’ instance type of a witness_method was a GenericTypeParamType,
which we can check directly.
Fixes rdar://problem/47767506 and possibly the hard-to-reproduce
rdar://problem/47772899.
Through a same-type constraint on an associated type, the Self type of
a protocol can conform to multiple protocols that are not related by
direct inheritance. There were two places that incorrectly assumed
that this didn't happen:
1) The SIL verifier checked that the archetype for Self conformed to
only a single protocol. This only tripped up +Asserts builds, and had
no effect on code generation. Change it to ensure that the archetype
for Self conforms to the expected protocol.
2) SILFunctionType's getDefaultWitnessMethodProtocol() asserted that
the Self type of a protocol only conformed to a single protocol, and
then returned the first protocol in the list. This could end up
returning the wrong protocol, in turn producing an incorrect
substitution list in IRGen. Change it to return the protocol from the
constraint in the generic signature.
Fixes SR-9848 / rdar://problem/47767506.
It does not take ownership of its non-trivial arguments, is a trivial
function type and therefore must not be destroyed. The compiler must
make sure to extend the lifetime of non-trivial arguments beyond the
last use of the closure.
%objc = copy_value %0 : $AnObject
%closure = partial_apply [stack] [callee_guaranteed] %16(%obj) : $@convention(thin) (@guaranteed AnObject) -> ()
%closure2 = mark_dependence %closure : $@noescape @callee_guaranteed () -> () on %obj : $AnObject
%user = function_ref @useClosure : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
apply %user(%closure2) : $@convention(thin) (@noescape @callee_guaranteed () -> ()) -> ()
dealloc_stack %closure : $() ->()
destroy_value %obj : $AnObject // noescape closure does not take ownership
SR-904
rdar://35590578
This undoes some of Joe's work in 8665342 to add a guarantee: if an
@objc convenience initializer only calls other @objc initializers that
eventually call a designated initializer, it won't result in an extra
allocation. While Objective-C /allows/ returning a different object
from an initializer than the allocation you were given, doing so
doesn't play well with some very hairy implementation details of
compiled nib files (or NSCoding archives with cyclic references in
general).
This guarantee only applies to
(1) calling `self.init`
(2) where the delegated-to initializer is @objc
because convenience initializers must do dynamic dispatch when they
delegate, and Swift only stores allocating entry points for
initializers in a class's vtable. To dynamically find an initializing
entry point, ObjC dispatch must be used instead.
(It's worth noting that this patch does NOT check that the calling
initializer is a convenience initializer when deciding whether to use
ObjC dispatch for `self.init`. If we ever add peer delegation to
designated initializers, which is totally a valid feature, that should
use static dispatch and therefore should not go through objc_msgSend.)
This change doesn't /always/ result in fewer allocations; if the
delegated-to initializer ends up returning a different object after
all, the original allocation was wasted. Objective-C has the same
problem (one of the reasons why factory methods exist for things like
NSNumber and NSArray).
We do still get most of the benefits of Joe's original change. In
particular, vtables only ever contain allocating initializer entry
points, never the initializing ones, and never /both/ (which was a
thing that could happen with 'required' before).
rdar://problem/46823518