If mismatch detected by `repairFailures` is related to a complex
wrapped value of optional type formed from optional-to-optional
or value-to-optional conversion let's not try to fix it directly
but let `simplifyRestrictedConstraintImpl` record a top-level fix
for more context.
Resolves: rdar://problem/59703585
This allows the usage of the whole remark infrastructure developed in
LLVM, which includes a new binary format, metadata in object files, etc.
This gets rid of the YAMLTraits-based remark serialization and does the
plumbing for hooking to LLVM's main remark streamer.
For more about the idea behind LLVM's main remark streamer, see the
docs/Remarks.rst changes in https://reviews.llvm.org/D73676.
The flags are now:
* -save-optimization-record: enable remarks, defaults to YAML
* -save-optimization-record=<format>: enable remarks, use <format> for
serialization
* -save-optimization-record-passes <regex>: only serialize passes that
match <regex>.
The YAMLTraits in swift had a different `flow` setting for the debug
location, resulting in some test changes.
Implement support for switch statements within function builders. Cases can
perform arbitrary pattern matches, e.g.,
tuplify(true) { c in
"testSwitchCombined"
switch e {
case .a:
"a"
case .b(let i, _?), .b(let i, nil):
i + 17
}
}
subject to the normal rules of switch statements. Cases within function
builders cannot, however, include “fallthrough” statements, because those
(like “break” and “continue”) are control flow.
The translation of performed for `switch` statements is similar to that of
`if` statements, using `buildEither(first:)` and `buildEither(second:)` on
the function builder type.
This is the bulk of switch support, tracked by rdar://problem/50426203.
The DependencyVerifier is a DiagnosticVerifier-alike utility that takes annotations in user code and transforms them into a set of expectations. Those expectations are met by corresponding "obligations", which are constructed by reading the contents of the referenced name tracker associated with the source files for each of the primary inputs to a frontend job. The verifier will then pair off expectations and obligations, and ensure that any remaining unpaired obligations are diagnosed as failures.
This tool will not only ensure the correctness of the referenced name tracker's output, it will provide us with tests that ensure its output is stable, and give us the confidence to replace it with an evaluator-based tracking scheme in the future.
Resolves rdar://59773883
When enabled at the driver level, the frontends will inherit the flag. For each frontend that recieves this option, all primaries will have their reference dependencies validated.
Overlays are specifically allowed to do magic things that regular Swift
modules are not. In this case, the UIImage and NSImage overlays have
extensions that allow them to conform to `_ExpressibleByImageLiteral`.
This, unfortunately, means that subclassing these classes with the
overlays present is impossible as one must override the required
initializers, but one cannot override these initializers since they are
declared in an extension.
While we cannot correct the overlays without breaking ABI, we can at
least make sure we don't attempt to stick @objc into them when users
have a go at subclassing these classes.
Resolves rdar://59610201
Remove the `EvaluateConditionals` flags from the
parser, and instead query the source file.
This commit also changes ParserUnit such that it
doesn't evaluate #if conditions by default, as
none of its clients appear to require it. The
only client that wasn't explicitly disabling #if
evaluation and is processing the resulting AST is
swift-indent, so this commit also adds a test to
ensure it continues to work correctly with #if
decls.
Add flags for whether delayed body parsing or #if
condition evaluation is disabled, as well as
whether warnings should be suppressed. Then pass
down these flags from the frontend.
This is in preparation for the requestification of
source file parsing where the SourceFile will need
to be able to parse itself on demand.
Move the global PersistentParserState from
the CompilerInstance to the source file that code
completion is operating on, only hooking up the
state when it's needed. This will help make it
easier to requestify source file parsing.
If there are any conversion restrictions present while trying to repair
failures related to contextual type, let's give `simplifyRestrictedConstraintImpl`
a chance to run and fix the problem.
Resolves: rdar://problem/59773317
It detends on a situation whether try? would get a type inferred
so the mismatch is against a contextual type, or contextual type
would be used as a type of `try?` and fail comparsion with inner
expression type. In either case the mismatch is contextual.
As an example of how this is useful, consider the case where
ClangImporter fails with
"unexpected error produced: could not build C module 'ctypes'"
It would be useful to know what the underlying Clang error was that
caused building the module to fail, but so far, `-verify` mode would not
output that; to get the error, it would be necessary to run the compiler
invocation again without `-verify`.
This change causes any remaining diagnostics that weren't in the input file
to be output if there were unexpected diagnostics in `-verify` mode.
I haven't added any tests for this because I didn't find a place that
contains tests for the `-verify` functionality itself (as opposed to
tests that use `-verify` mode). I think the large number of tests that
run with `-verify` should at least ensure, however, that this change
does not regress anything.
I added a new API into OwnershipUtils called
getSingleBorrowIntroducingValue. This API returns a single
BorrowScopeIntroducingValue for a passed in guaranteed value. If we can not find
such a BorrowScopeIntroducingValue or we find multiple such, we return None.
Using that, I refactored StorageGuaranteesLoadVisitor::visitClassAccess(...) to
use this new API which should make it significantly more robust since the
routine uses the definitions of "guaranteed forwarding" that the ownership
verifier uses when it verifies meaning that we can rely on the routine to be
exhaustive and correct. This means that we now promote load [copy] ->
load_borrow even if our borrow scope introducer feeds through a switch_enum or
checked_cast_br result (the main reason I looked into this change).
To create getSingleBorrowIntroducingValue, I refactored
getUnderlyingBorrowIntroucingValues to use a generator to find all of its
underlying values. Then in getSingleBorrowIntroducingValue, I just made it so
that we call the generator 1-2 times (as appropriate) to implement this query.
Specifically, this PR adds support for optimizing simple cases where we do not
need to compute LiveRanges with the idea of first doing simple transforms that
involve small numbers of instructions first. With that in mind, we only optimize
cases where our copy_value has a single consuming user and our owned value has a
single destroy_value. To understand the transform here, consider the following
SIL:
```
%0 = ...
%1 = copy_value %0 (1)
apply %guaranteedUser(%0) (2)
destroy_value %0 (3)
apply %cviConsumer(%1) (4)
```
We want to eliminate (2) and (3), effectively joining the lifetimes of %0 and
%1, transforming the code to:
```
%0 = ...
apply %guaranteedUser(%0) (2)
apply %cviConsumer(%0) (4)
```
Easily, we can always do this transform in this case since we know that %0's
lifetime ends strictly before the end of %1's due to (3) being before (4). This
means that any uses that require liveness of %0 must be before (4) and thus no
use-after-frees can result from removing (3) since we are not shrinking the
underlying object's lifetime. Lets consider a different case where (3) and (4)
are swapped.
```
%0 = ...
%1 = copy_value %0 (1)
apply %guaranteedUser(%0) (2)
apply %cviConsumer(%1) (4)
destroy_value %0 (3)
```
In this case, since there aren't any liveness requiring uses of %0 in between
(4) and (3), we can still perform our transform. But what if there was a
liveness requiring user in between (4) and (3). To analyze this, lets swap (2)
and (4), yielding:
```
%0 = ...
%1 = copy_value %0 (1)
apply %cviConsumer(%1) (4)
apply %guaranteedUser(%0) (2)
destroy_value %0 (3)
```
In this case, if we were to perform our transform, we would get a use-after-free
due do the transform shrinking the lifetime of the underlying object here from
ending at (3) to ending at (4):
```
%0 = ...
apply %cviConsumer(%1) (4)
apply %guaranteedUser(%0) (2) // *kaboom*
```
So clearly, if (3) is after (4), clearly, we need to know that there aren't any
liveness requiring uses in between them to be able to perform this
optimization. But is this enough? Turns out no. There are two further issues
that we must consider:
1. If (4) is forwards owned ownership, it is not truly "consuming" the
underlying value in the sense of actually destroying the underlying value. This
can be worked with by using the LiveRange abstraction. That being said, this PR
is meant to contain simple transforms that do not need to use LiveRange. So, we
bail if we see a forwarding instruction.
2. At the current time, we may not be able to find all normal uses since all of
the instructions that are interior pointer constructs (e.x.: project_box) have
not been required yet to always be guarded by borrows (the eventual end
state). Thus we can not shrink lifetimes in general safely until that piece of
work is done.
Given all of those constraints, we only handle cases here where (3) is strictly
before (4) so we know 100% we are not shrinking any lifetimes. This effectively
is causing our correctness to rely on SILGen properly scoping lifetimes. Once
all interior pointers are properly guarded, we will be able to be more
aggressive here.
With that in mind, we perform this transform given the following conditions
noting that this pattern often times comes up around return values:
1. If the consuming user is a return inst. In such a case, we know that the
destroy_value must be before the actual return inst.
2. If the consuming user is in the exit block and the destroy_value is not.
3. If the consuming user and destroy_value are in the same block and the
consuming user is strictly later in that block than the destroy_value.
In all of these cases, we are able to optimize without the need for LiveRanges.
I am going to add support for this in a subsequent commit.
I looked when building the stdlib/overlays and the vast majority of uses were < 2 for all
of these values, so it makes sense to shrink them.
Part of the reason I am doing this is that I think the pass is starting to
coalesce a little bit and also I want to start optimizing owned phi arguments so
I am going to need to start storing these. I don't want to be storing such large
small arrays in any data structure anywhere.
I also added a comment to getAllBorrowIntroducingValues(...) that explained the
situations where one could have multiple borrow introducing values:
1. True phi arguments.
2. Aggregate forming instructions.