This presents a regression in diagnostic quality that is definitely
worth it not to lie to SILGen about whether a switch is covered or not.
At the same time, disable SIL’s unreachable diagnostic for ‘default’
clauses which would previously cause a warning to be emitted if the
default was proven to be unreachable. This analysis is incomplete
anyways and can be done by Sema in the future if we desire.
This fixes a serious false negative in static exclusivity enforcement when
a noescape closure performs an access that conflicts with an in-progress access
but is not reported because the closure is passed via a reabstraction thunk.
When diagnosing at a call site, the enforcement now looks through partial
applies that are passed as noescape arguments. If the partial apply takes
an argument that is itself a noescape partial apply, it recursively checks
the captures for that partial apply for conflicts and diagnoses if it finds one.
This means, for example, that the compiler will now diagnose when there is a
conflict involving a closure with a concrete return type that is passed to a
function that expects a closure returning a generic type. To preserve source
compatibility these diagnostics are emitted as warnings for now. The intent is
that they will be upgraded to errors in a future version of Swift.
rdar://problem/35215926, SR-6103
...unless the struct contains a field that cannot be zero-initialized,
such as a non-nullable pointer.
This suggestion is only made for C structs because 'init()' may not be
the right choice for other structs.
...as detected by initializing an individual field without having
initialized the whole object (via `self = value`).
This only applies in pre-Swift-5 mode because the next commit will
treat all cross-module struct initializers as delegating in Swift 5.
This allows reporting successful and unsuccessful optimizations similar to
clang/llvm.
This first patch adds support for the
options -Rpass=<pass-name-regex> -Rpass-missed=<pass-name-regex>. These allow
reporting successful/unsuccessful optimization on the compiler output for passes
specified by the regex. I've also added one missed and one passed remark type
to the inliner to test the infrastructure.
Clang also has the option of collecting these records in an external YAML data
file. This will be added in a later patch.
A few notes:
* The goal is to use this facility for both user-lever "performance" warnings
and expert-level performance analysis. There will probably be a flag in the
future differentiating the verbosity.
* The intent is match clang/llvm as much as it makes sense. On the other hand I
did make some changes. Unlike in llvm, the emitter is not a pass which
simplifies things. Also the remark class hierarchy is greatly simplified since
we don't derive from DiagnosticInfo. We also don't derive from Diagnostic to
support the streaming API for arbitrary named-value pairs.
* Currently function names are printed mangled which should be fixed.
Update static exclusivity diagnostics to not suggest copying to a local
when a call to swapAt() should be used instead. We already emit a FixIt in
this case, so don't suggest an an helpful fix in the diagnostic.
rdar://problem/32296784
Remove the descriptive decl kind (since with subpaths it is not correct and
cannot represent a tuple element) and change "simultaneous" to "overlapping"
in order to lower the register slightly and avoid connoting threading.
For example, for the following:
takesTwoInouts(&x.f, &x.f)
the diagnostic will change from
"simultaneous accesses to var 'x.f', but modification requires exclusive access;
consider copying to a local variable"
to
"overlapping accesses to 'x.f', but modification requires exclusive access;
consider copying to a local variable"
Relax the static enforcement of exclusive access so that we no longer diagnose
on accesses to separate stored structs of the same property:
takesInout(&s.f1, &s.f2) // no-warning
And perform the analogous relaxation for tuple elements.
To do this, track for each begin_access the projection path from that
access and record the read and write-like modifications on a per-subpath
basis.
We still warn if the there are conflicting accesses on subpaths where one is
the prefix of another.
This commit leaves the diagnostic text in a not-so-good shape since we refer
to the DescriptiveDeclKind of the access even describing a subpath.
I'll fix that up in a later commit that changes only diagnostic text.
https://bugs.swift.org/browse/SR-5119
rdar://problem/31909639
We silently miscompiled previously the following code:
protocol Gesture {}
struct Foo {}
struct Bar {}
enum FooOrBar {
case foo(Foo)
case bar(Bar)
}
func main(_ f : FooOrBar) {
switch f {
case .foo(let data as Gesture),
.bar(let data as Gesture):
...
}
...
}
This was because the multiple pattern per case code never implemented support
for address only types.
Now instead of miscompiling such programs, we do the following:
1. We emit an error.
2. When we construct the arguments for the named bindings, we just skip the
address only types. Everything else is normal.
3. In the case block, we use a SILUndef for the address only value.
This ensures that we preserve as many other diagnostics as possible.
rdar://32525952
P.S. As an additional benefit, this eliminates a source of address phi nodes
from SILGen.
Adjust the definition of some diagnostics that are already called with
DeclBaseNames so that the implicit conversion from DeclBaseName to
Identifier is no longer needed.
Adjust the call side of diagnostics which don't have to deal with
special names to pass an Identifier to the diagnostic.
Update the static diagnostics when enforcing exclusive access to suggest adding
a local variable. The new diagnostic text is:
"simultaneous accesses to var 'a', but modification requires exclusive
access; consider copying to a local variable"
Static diagnostics now refer to the identifier for the variable requiring
exclusive diagnostics. Additionally, when two accesses conflict we now always
emit the main diagnostic on the first modifying access and the note on either
the second modifying access or the read.
The diagnostics also now highlight the source range for the expression
beginning the access.
Change the error emitted when diagnosing an exclusivity violation to an warning.
This will make it easier to evaluate on large projects while staging. The
intent it to turn it back into an error before the diagnosis is turned on
by default.
Add a diagnostic pass that emits errors when a violation of the "Law of
Exclusivity" is detected at compile time. The Law of Exclusivity requires
that the access duration of any access to an address not overlap
with an access to the same address unless both accesses are reads.
This pass relies on 'begin_access' and 'end_access' SIL instruction
markers inserted by SILGen to determine when an access to an address begins and
ends. It models the in-progress accesses with a map from storage locations to
the counts of read and write-like accesses in progress for that location.
1. Make sure the actions taken by fixits are reflected in diagnostics messages.
2. Issue missing cases diagnostics at the start of the switch statement instead of its end.
3. Use <#code#> instead of <#Code#> in the stub.
Extend the checks in `LifetimeChecker` in
`SILOptimizer/Mandatory/DefiniteInitialization.cpp`
to catch when the memory object corresponding to a let constant is used
as an inout parameter in a protocol witness method.
Initializing a let constant separate from its declaration requires write
access. Therefore it is treated as `@lvalue TestProtocol` in the AST for
a certain scope.
Checking that the constant is not written to after being initialized is
supposed to happen in the Mandatory SILOptimizer phase instead.
On loads, the Optimizer checks, that a variable is fully initialized,
but perviously did not validate what happens to it after it is loaded.
This allowed loading the memory object through an open_existential_addr
instruction and applying the result as an Operand to a mutating witness
method.
Turn on the noreturn diagnostic for cases where a reachable unreachable
could be encountered. Previously, the diagnostic would not fire if the
function was marked noreturn and any of its reachable unreachable calls
were around. While this makes sense from a SILGen perspective (it Just
Crashes tm), it is still wrong. We need to diagnose *everything* that
has reachable unreachables.
Provide a general mechanism for bridging from a Swift value type to
its corresponding Objective-C class type through the
_bridgeToObjectiveC witness of the appropriate _ObjectiveCBridgeable
protocol conformance. Only enable this new code for bridging String ->
NSString and work through the issues that crop up.
We cannot actually *delete* the _convertStringtoNSString entrypoint
yet, because there is some code that is depending on it indirectly;
I'll address that separately as part of the continued generalization
of the _ObjectiveCBridgeable mechanism.
Certain type circularities weren't being checked until this point. Such as
```
struct X<T> { let a: X<X> }
struct Y<T> { let a: (Int, Y<Y>) }
enum Z<T> { case A(Optional<Z<Z>>) }
```
We introduce a more comprehensive approach to detect these in type checker.
After name lookup, exam each value field in declared structs and enums for
self-reference types that creates inifinite sizes.
its fields are initialized. Before:
t.swift:18:24: error: variable 'self.B' captured by a closure before being initialized
after:
t.swift:19:24: error: 'self' captured by a closure before all members were initialized
self.A.withCString { cString -> () in
^
t.swift:14:7: note: 'self.B' not initialized
var B: Int
^
This drives home the fact that 'self' is being captured here, not the individual
properties.
Diagnostic categories are entirely unused and arguably useless as
implemented, as they merely denote the sub-component of the
compiler.
As far as categorizing warnings are concerned, I'm abandoning the
effort for now, as the utility is marginal and Swift and the Swift
compiler are probalby not ready for these to be nailed down. For the
sake of cleanliness, the CATEGORY field is also stripped from
WARNINGS.
If there's a need for automatic identifying of compiler sub-components
for diagnstics in the future, there are better ways to do this.
NFC
There's no longer a direct use of the variable's address when we invoke the closure, but we have a handy mark_function_escape instruction to mark the use without requiring merging analysis of the box and its contents. This also gives us a slightly more accurate error message when a variable is prematurely captured, noting the variable was captured by a closure instead of just generically used.
Designated initializers in NSManagedObject subclasses, or other
classes with @requires_stored_property_inits cannot assign to
stored properties before doing a super.init() delegation.
Assignments after are OK.
DI did the wrong thing by creating a bitmap with only one bit,
but proceeding down the usual designated initializer path.
Now, handle [derivedselfonly] more like a convenience initializer,
with no stored property access allowed prior to delegation.
Also clean up duplicated diagnostics between designated and
convenience initializers, and make convenience initializers
diagnose method calls or property accesses on self in the same
manner as designated initializers.
Fixes <rdar://problem/22110837>.
Swift SVN r32858