With constraint propagation enabled, we go down a different path in the
solver that results in a type with ParenType wrapped around it. Normally
in diagnostic formatting we would strip these off, but in explicitly
forming a string for a fixit, we need to do it ourself. Hits in
test/Parse/try.swift with constraint propagation enabled.
All of this information is recoverable from the more-general,
more-sane signature conformances, so stop
recording/serializing/deserializing all of this extra stuff.
It turns out that for disjunctions formed for subscripts, we have an
explicit function type (e.g. ($T1)->$T2) for the LHS of the bind
overload constraint, and when a subscript is mixed with an explicit
call (e.g. x[i](2)) we end up with an applicable function constraint
where the RHS is $T2 (which is a function type itself), so this assert
was invalid.
Fundamentally the assert wasn't checking anything important, so it won't
be missed. The important check here is that the applicable function
constraint that we started with is only involved in one disjunction
since we're only returning one.
This shows up in test/Constraints/overload.swift when I run it with
-propagate-constraints enabled:
func test20886179(_ handlers: [(Int) -> Void], buttonIndex: Int) {
handlers[buttonIndex](buttonIndex)
}
TODO:
- Select the KeyPath subclass corresponding to the write capability of the key path components
- Figure out an issue with unresolved solutions being chosen with contextually-typed keypaths
- Diagnostic QoI
The overall idea is like this:
- first, collect the generic params that are explicitly used by types of arguments or return type
- then perform a fix-point analysis, where at each step, a set of generic signature’s requirements is checked.
- If there is a requirement where one of the involved generic params is already proven to be used, then all other generic params from the same requirement are also considered to be implicitly used in the function signature, because they are used to put a requirement on a generic param that is already known to be used in the function signature.
The fix-point iteration is required to handle chains of dependencies between requirements. See the updated test case for an example.
Fixes rdar://29585211
When looking up a particular conformance in a SubstitutionMap, use the
associated generic signature to determine how to find that conformance
(via a conformance access path). Follow that conformance access path
to retrieve the desired conformance.
FIXME: There is still one failure, here
Constraints/generic_overload.swift
which appears to be because we either have the wrong generic signature
for the override case or we are looking in the wrong map.
When we are checking the conformance of a nominal type to a particular
protocol, we check each of the requirements in the requirement
signature, substituting in our Self type and (by extension) type
witnesses. However, when we're trying to fulfill requirements for
associated types (which might be mapped to concrete types), perform
the conformance lookup in the module of the conformance itself---not
the SubstitutionMap, which can't possibly have them at this point.
Fixes rdar://problem/31041997.
This is an initial implementation of the constraint propagation pass,
disabled by default at the moment as it does not currently pass all
tests.
I have other changes that I'll hold off on for now because they are
incomplete. Without those changes, this pass doesn't really achieve
much, so this is really just a checkpoint on some progress and not
something really worth trying out at this point.
An assertion I added recently to check property overrides in
the ASTVerifier uncovered some bugs in this area:
- We did not synthesize a materializeForSet for properties
defined in extensions of imported classes unless they
witnessed a protocol requirement.
This triggered an assertion if the property had an
override that was checked before the protocol conformance,
since the override's materializeForSet would not be marked
as an override of the base materializeForSet.
- materializeForSet for properties defined in extensions would
statically dispatch the getter and setter instead of dynamically
dispatching. This is incorrect since we statically dispatch
to the materializeForSet in this case, and we can in fact
override it in a subclass.
Fixes <rdar://problem/31334272>.
Warn about cases where a storage declaration (property or subscript)
has an accessor with an explicit @objc, but for which the storage
declaration itself is only @objc due to deprecated @objc inference.
When the 'dynamic' modifier is explicitly written on a declaration, it
requires the Objective-C runtime. In Swift 3, this (directly) implies
'@objc'. In Swift 4, it requires that the '@objc' be written
explicitly. Hence, a Swift 3 -> Swift 4 migration will always retain
the @objc-ness of the entry point, so we don't need to treat it as
"inferred".
Overriding of members introduced in class extensions depends on the
presence of an Objective-C entrypoint. When we override such a
member---which used the deprecated @objc inference rule and occurs in
a class extension, where non-@objc methods currently cannot be
overridden---warn about the use of explicit @objc.
Split the warning into two warnings, because we want different Fix-It behavior.
* For the ‘dynamic’ warning, drop the “in Swift 4” part and keep the @objc Fix-It on the main warning. This is always auto-applyable.
* For the inferred-for-members-of-Objective-C-derived-classes warning, drop the “in Swift 4” part. More importantly, split off two notes: one with the @objc Fix-It (Swift 3 behavior) and one with the @nonobjc Fix-It (Swift 4 behavior). This makes it clearer that there is a choice, and neither is “obviously” correct.
Introduce flags `-enable-swift3-objc-inference` and
`-disable-swift3-objc-inference` to enable/disable the Swift 3 `@objc`
inference rules. Under `-swift-version 3`, default to the former;
under `-swift-version 4`, default to the latter. For testing purposes,
one can provide either flag in eiher language mode.
When in Swift 3 compatibility mode without
`-warn-swift3-objc-inference`, warn on the *uses* of declarations that
depend on the Objective-C runtime that became `@objc` due to the
deprecated inference rule. This far more directly captures important
uses of the deprecated Objective-C entrypoints. We diagnose:
* `#selector` expressions that refer to one of these `@objc` members
* `#keyPath` expressions that refer to one of these `@objc` members
* Dynamic lookup (i.e., member access via `AnyObject`) that refers to
one of these `@objc` members.
Introduce an opt-in warning (enabled by the frontend option
-warn-swift3-objc-inference) for each declaration for which @objc is
inferred based on Swift 3 rules that no longer apply after SE-0160.
Rather than the nebulous “do not diagnose”, separate out the two reasons for a non-diagnosed @objc: it’s a member of an Objective-C-derived subclass or it’s an accessor for a property.
The requirement signature concerns the conforming type and its
associated types, so check it once we've resolved all of the type
witnesses---and before we check the other requirements.
This code was only there while we waited for IRGen to start depending
on conformance access paths, as an assertion. Now, it's just a waste
of time to compute this information for *every* conformance.
Two problems:
1) We were tearing down the type checker too early, before all
relevant decls in other files had been type checked, so there
was no LazyResolver available for use in the ASTContext.
This might explain the crashes coming through
diagnoseUnintendedObjCMethodOverrides().
2) When a lazy resolver was set in the ASTContext, we were not
using it in the case where nullptr was passed in as the
'resolver' parameter to inheritsSuperclassInitializers().
This might fix the crashes where we were coming in from other
code paths, but I'm less confident about this case.
Possibly fixes <rdar://problem/29043074>, <rdar://problem/30976765>,
<rdar://problem/31122590>, and <rdar://problem/31286627>, and the
many other similar-looking dupes.