Whenever we visit a declaration via the DeclChecker, add it to the
list of declarations to finalize. This makes sure that we can centralize
the notion of “finalize for SILGen” and that it will be called for
everything in the source file being processed.
The @objc optional requirement near-miss heuristics were too
permissive, and could occasionally produce ridiculous results that
were nowhere close to a "near" miss. Make the diagnostics more
conservative, and fix an issue with an errant sentinel value.
Fixes rdar://problem/26380688.
An overriding declaration doesn't have a choice about its signature,
because the signature is dictated by the overridden
declaration. Therefore, don't produce a warning for it.
Fixes rdar://problem/28524237.
When @objc inference was extended to look at the conformances of
superclasses, the code that diagnosed near misses was not similarly
updated, so we could end up producing a near-miss diagnostic on a
declaration that was already a witness to another protocol. Use the
same witness-finding logic that we use for @objc inference so this
doesn't happen again.
Fixes the rest of rdar://problem/27348369
This is a follow-up to the change that allowed one to omit @objc (or
the name in an @objc) when it can be inferred by matching a
requirement. There is no point in suggesting that one add @objc if it
will be inferred anyway, since it's just syntactic noise.
Use the diagnostics machinery of the protocol conformance checker to
say why each near-miss actually missed, e.g., a type conflict. This
gives better information regarding how to fix the actual problem. Yet
more QoI for rdar://problem/25159872.
The differences between Swift 2 and Swift 3 names can be very
significant, when the Swift 2 names have a lot of restated type
information. These differences end up disabling the near-miss
heuristics because the magnitude of the change is so high. Therefore,
apply the omit-needless-words heuristics to the potential witness and
the requirement before scoring them.
Should finish up rdar://problem/25159872 for real.
The Grand API Renaming tends to split long base names into a shorter
base name + first argument label. To account for this in near-miss
checking, consider the base name + first argument label as a unit.
It's a common mistake to mistype a declaration that is intended to
satisfy an optional requirement. In such "near misses", we want to
warn about the mistake and give the user options to either fix the
declaration or suppress the warning. Approach this problem be walking
over all of the members of each nominal type declaration or extension
therefore and looking to see if there are any members remaining that
(1) are similarly-named to an unfilfilled optional requirement of a
protocol whose conformance is attributed to that nominal type
declaration or extension,
(2) are not witnesses to another optional requirement,
(3) haven't explicitly suppressed the warning (e.g., by adding
explicit "private" or explicit "@nonobjc"), and
(4) have a useful suppression mechanism.
In addition to the suppression mechanisms described in (3), one can
suppress this warning by moving the declaration to an(other)
extension. This encourages a programming style where one breaks an
interface into extensions each implement conformance to one
protocol. Note that we encode the various cases where one cannot move
the declaration to another extension (e.g., one cannot move a
designated initializer or stored property out of a class declaration)
and suppress the warning when there's no way for the user to cope with
it.
Each warning produced by this diagnostic can have a bunch of notes on
it for various courses of action. For example:
t2.swift:7:14: warning: instance method 'doSomething(z:)' nearly
matches optional requirement 'doSomething(x:)' of protocol 'P1'
@objc func doSomething(z: Double) { }
^
t2.swift:7:14: note: rename to 'doSomething(x:)' to satisfy this
requirement
@objc func doSomething(z: Double) { }
^
x
t2.swift:7:14: note: move 'doSomething(z:)' to an extension to silence
this warning
@objc func doSomething(z: Double) { }
^
t2.swift:7:14: note: make 'doSomething(z:)' private to silence this
warning
@objc func doSomething(z: Double) { }
^
private
t2.swift:2:17: note: requirement 'doSomething(x:)' declared here
optional func doSomething(x: Int)
^
It's a *lot* of detail, but is intended to cover the various choices
available to the user: Fix-It to the names of the requirement (for
naming-related mistakes) or suppress via various mechanisms. Combining
notes means losing Fix-Its, while dropping notes can lead users to
non-optimal solutions.
This is more of rdar://problem/25159872.