Fixes rdar://128981120 (Crash when inout arg captured through some
closures? (llvm::all_of(apply->getUses(), hasExpectedUsesOfNoEscapePartialApply)
&& "noescape partial_apply has unexpected use!"))
It is legal for a `move_value` to appear as a transitive user of a
`partial_apply`. Look through those like the other ownership
instructions.
rdar://107963619
Although nonescaping closures are representationally trivial pointers to their
on-stack context, it is useful to model them as borrowing their captures, which
allows for checking correct use of move-only values across the closure, and
lets us model the lifetime dependence between a closure and its captures without
an ad-hoc web of `mark_dependence` instructions.
During ownership elimination, We eliminate copy/destroy_value instructions and
end the partial_apply's lifetime with an explicit dealloc_stack as before,
for compatibility with existing IRGen and non-OSSA aware passes.
Potentially source breaking: SR-11700 Diagnose exclusivity violations
with Dictionary.subscript._modify:
Exclusivity violations within code that computes the `default`
argument during Dictionary access are now diagnosed.
```swift
struct Container {
static let defaultKey = 0
var dictionary = [defaultKey:0]
mutating func incrementValue(at key: Int) {
dictionary[key, default: dictionary[Container.defaultKey]!] += 1
}
}
error: overlapping accesses to 'self.dictionary', but modification requires exclusive access; consider copying to a local variable
dictionary[key, default: dictionary[Container.defaultKey]!] += 1
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: conflicting access is here
dictionary[key, default: dictionary[Container.defaultKey]!] += 1
~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
```
This reworks the logic so that four problems end up being fixed:
Fixes three problems related to coroutines:
(1) DiagnoseStaticExclusivity must consider begin_apply as a user of accessed variables. This was an undefined behavior hole in the diagnostics.
(2) AccessedSummaryAnalysis should consider begin_apply as a user of accessed arguments. This does not show up in practice because coroutines don't capture things.
(3) AccessedSummaryAnalysis must consider begin_apply a valid user of
noescape closures.
And fixes one problem related to resilience:
(4) AccessedSummaryAnalysis must conservatively consider arguments to external functions.
Fixes <rdar://problem/56378713> Investigate why AccessSummaryAnalysis is crashing
I also removed the -verify-sil-ownership flag in favor of a disable flag
-disable-sil-ownership-verifier. I used this on only two tests that still need
work to get them to pass with ownership, but whose problems are well understood,
small corner cases. I am going to fix them in follow on commits. I detail them
below:
1. SILOptimizer/definite_init_inout_super_init.swift. This is a test case where
DI is supposed to error. The only problem is that we crash before we error since
the code emitting by SILGen to trigger this error does not pass ownership
invariants. I have spoken with JoeG about this and he suggested that I fix this
earlier in the compiler. Since we do not run the ownership verifier without
asserts enabled, this should not affect compiler users. Given that it has
triggered DI errors previously I think it is safe to disable ownership here.
2. PrintAsObjC/extensions.swift. In this case, the signature generated by type
lowering for one of the thunks here uses an unsafe +0 return value instead of
doing an autorelease return. The ownership checker rightly flags this leak. This
is going to require either an AST level change or a change to TypeLowering. I
think it is safe to turn this off since it is such a corner case that it was
found by a test that has nothing to do with it.
rdar://43398898
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.
In a previous commit, I banned in the verifier any SILValue from producing
ValueOwnershipKind::Any in preparation for this.
This change arises out of discussions in between John, Andy, and I around
ValueOwnershipKind::Trivial. The specific realization was that this ownership
kind was an unnecessary conflation of the a type system idea (triviality) with
an ownership idea (@any, an ownership kind that is compatible with any other
ownership kind at value merge points and can only create). This caused the
ownership model to have to contort to handle the non-payloaded or trivial cases
of non-trivial enums. This is unnecessary if we just eliminate the any case and
in the verifier separately verify that trivial => @any (notice that we do not
verify that @any => trivial).
NOTE: This is technically an NFC intended change since I am just replacing
Trivial with Any. That is why if you look at the tests you will see that I
actually did not need to update anything except removing some @trivial ownership
since @any ownership is represented without writing @any in the parsed sil.
rdar://46294760
This does not eliminate the entrypoints on SILBuilder yet. I want to do this in
two parts so that it is functionally easier to disentangle changing the APIs
above SILBuilder and changing the underlying instruction itself.
rdar://33440767
The compile-time exclusivity diagnostics explicitly allow conflicting accesses
to a struct when it can prove that the two accesses are used to project addresses
for separate stored properties. Unfortunately, the logic that detects this special
case gets confused by Thread Sanitizer's SIL-level instrumentation. This causes
the exclusivity diagnostics to have false positives when TSan is enabled.
To fix this, teach the AccessSummaryAnalysis to ignore TSan builtins when
determining whether an access has a single projected subpath.
rdar://problem/40455335
Some of these did not have ownership at all and some were parsing ownership SIL
with the verifier disabled. Lets just run them with ownership+the verifier.
introduce a common superclass, SILNode.
This is in preparation for allowing instructions to have multiple
results. It is also a somewhat more elegant representation for
instructions that have zero results. Instructions that are known
to have exactly one result inherit from a class, SingleValueInstruction,
that subclasses both ValueBase and SILInstruction. Some care must be
taken when working with SILNode pointers and testing for equality;
please see the comment on SILNode for more information.
A number of SIL passes needed to be updated in order to handle this
new distinction between SIL values and SIL instructions.
Note that the SIL parser is now stricter about not trying to assign
a result value from an instruction (like 'return' or 'strong_retain')
that does not produce any.
Make the static enforcement of accesses in noescape closures stored-property
sensitive. This will relax the existing enforcement so that the following is
not diagnosed:
struct MyStruct {
var x = X()
var y = Y()
mutating
func foo() {
x.mutatesAndTakesClosure() {
_ = y.read() // no-warning
}
}
}
To do this, update the access summary analysis to summarize accesses to
subpaths of a capture.
rdar://problem/32987932
Make the static enforcement of accesses in noescape closures stored-property
sensitive. This will relax the existing enforcement so that the following is
not diagnosed:
struct MyStruct {
var x = X()
var y = Y()
mutating
func foo() {
x.mutatesAndTakesClosure() {
_ = y.read()
}
}
}
To do this, update the access summary analysis to be stored-property sensitive.
rdar://problem/32987932
This is a same-day fix for a typo introduced here:
commit c2c55eea12
Author: Andrew Trick <atrick@apple.com>
Date: Wed Jun 21 16:08:06 2017
AccessSummaryAnalysis: handle @convention(block) in nested nonescape closures.
Use the AccessSummaryAnalysis to statically enforce exclusive access for
noescape closures passed as arguments to functions.
We will now diagnose when a function is passed a noescape closure that begins
an access on capture when that same capture already has a conflicting access
in progress at the time the function is applied.
The interprocedural analysis is not yet stored-property sensitive (unlike the
intraprocedural analysis), so this will report violations on accesses to
separate stored properties of the same struct.
rdar://problem/32020710
Add an interprocedural SIL analysis pass that summarizes the accesses that
closures make on their @inout_aliasable captures. This will be used to
statically enforce exclusivity for calls to functions that take noescape
closures.
The analysis summarizes the accesses on each argument independently and
uses the BottomUpIPAnalysis utility class to iterate to a fixed point when
there are cycles in the call graph.
For now, the analysis is not stored-property-sensitive -- that will come in a
later commit.