This commit replaces the `getValue()` and `getValue2()` members on
`ConstraintLocator::PathElement` with specific accessors for each
expected path component kind. IMO this adds some clarity to the call
sites, especially for `getArgIdx()` and `getParamIdx()`.
In addition, this commit adds a private `getValue` member that can
access a value at a given index, which will make it easier to add a
third value in the future.
Instead of keeping two locators in the fix let's store only the
original locator and simplify it later in process of emitting
a diagnostic. That helps to avoid some duplicate work as well
as makes sure that locators supplied to the diagnostic always
have an anchor.
Resolves: rdar://problem/53344815
We would previously fail to match something like (C<$T1> & P) against
(C<Int> & P) when the constraint kind was <= Subtype, because we would
fall back to a type equality test in that case.
However, this was only valid for protocol compositions without superclass
constraints since the superclass could contain a type variable on one
side of the constraint.
Fix this by adding support for protocol composition types to
matchDeepEqualityTypes().
It's only needed in one place in the constraint solver to allow
`() -> T` to `() -> ()` and `() -> Never` to `() -> T` for expressions
representing return of a single expression functions, so to simplify
contextual type handling in diagnostic and other places it would be
better to replace dedicated locator kind with a flag on existing `ContextualType`.
Resolves: rdar://problem/51641323
KeyPath dynamic member lookup is limited to what key path itself
could do, so let's detect and diagnose invalid references just
like we do for regular key path expressions.
Resolves: rdar://problem/50376224
New locator is going to store pointer to the base keypath declaration.
This information is useful to determine whether such keypath is appropriate
to access underlying properties/subscripts e.g. `WritableKeyPath` cannot be
used to access read-only storage.
There's no need to instantiate archetypes in the generic environment
of the declaration being opened.
A couple of diagnostics changed. They were already misleading, and the
new diagnostics, while different, are not any more misleading than
before.
Previously we would generate the following constraint here, where
'index' and 'output' are concrete types and $input is a type
variable:
- ValueMember(base, $input -> output)
- ArgumentTupleConversion(index, $input)
The problem is that we built a function type where the entire input
was a type variable, which would then bind to an argument list.
We could instead generate this constraint:
- ValueMember(base, $member)
- ApplicableFunction(index -> output, $member)
I also had to redo how keypaths map locators back to key path
components. Previously the ArgumentTupleConversion was created
with a locator ending in KeyPathComponent.
Now the ApplicableFunction is created with this locator, which means
the argument match is performed with a locator ending in
ApplyArgument.
A consequence of this is that the SubscriptIndex and SubscriptResult
locator path elements are no longer used, so remove them.
This requires various mechanical changes in places we look at
locators to handle this change. Should be NFC.
Having requirement kind encoded in the locator helps to identify
what kind of fix to generate (applicable to same-type, superclass)
without retrieving requirement itself.
This either became dead shortly after the removal of Swift 3
compatibility mode from the constraint solver, or even earlier.
Note that the code completion test change is actually correct
because (Any) -> () is not convertible to () -> () in the
language.
so that they must result in an optional type.
Add constraint locator path for identifying constraints/variables that are part of the convert type passed into the system.
8271c1a removed the last hacky usage of ArrayElementType,
leaving behind just the @lvalue-to-inout conversions. Rename
the locator path element to reflect this and do a bit of cleanup on the
unrelated-but-near-enough other hack RValueAdjustment.
Disallow implicit conversion or arguments from Array, String, and
InOut (formed by &) to pointer types if the argument is for an
@autoclosure parameter.
These conversions were really only intended to be used for C/ObjC
interop, and in some contexts like autoclosures they are not safe.
Fixes: rdar://problem/31538995
Stop creating ImplicitlyUnwrappedOptional<T> so that we can remove it
from the type system.
Enable the code that generates disjunctions for Optional<T> and
rewrites expressions based on the original declared type being 'T!'.
Most of the changes supporting this were previously merged to master,
but some things were difficult to merge to master without actually
removing IUOs from the type system:
- Dynamic member lookup and dynamic subscripting
- Changes to ensure the bridging peephole still works
Past commits have attempted to retain as much fidelity with how we
were printing things as possible. There are some cases where we still
are not printing things the same way:
- In diagnostics we will print '?' rather than '!'
- Some SourceKit and Code Completion output where we print a Type
rather than Decl.
Things like module printing via swift-ide-test attempt to print '!'
any place that we now have Optional types that were declared as IUOs.
There are some diagnostics regressions related to the fact that we can
no longer "look through" IUOs. For the same reason some output and
functionality changes in Code Completion. I have an idea of how we can
restore these, and have opened a bug to investigate doing so.
There are some small source compatibility breaks that result from
this change:
- Results of dynamic lookup that are themselves declared IUO can in
rare circumstances be inferred differently. This shows up in
test/ClangImporter/objc_parse.swift, where we have
var optStr = obj.nsstringProperty
Rather than inferring optStr to be 'String!?', we now infer this to
be 'String??', which is in line with the expectations of SE-0054.
The fact that we were only inferring the outermost IUO to be an
Optional in Swift 4 was a result of the incomplete implementation of
SE-0054 as opposed to a particular design. This should rarely cause
problems since in the common-case of actually using the property rather
than just assigning it to a value with inferred type, we will behave
the same way.
- Overloading functions with inout parameters strictly by a difference
in optionality (i.e. Optional<T> vs. ImplicitlyUnwrappedOptional<T>)
will result in an error rather than the diagnostic that was added
in Swift 4.1.
- Any place where '!' was being used where it wasn't supposed to be
allowed by SE-0054 will now treat the '!' as if it were '?'.
Swift 4.1 generates warnings for these saying that putting '!'
in that location is deprecated. These locations include for example
typealiases or any place where '!' is nested in another type like
`Int!?` or `[Int!]`.
This commit effectively means ImplicitlyUnwrappedOptional<T> is no
longer part of the type system, although I haven't actually removed
all of the code dealing with it yet.
ImplicitlyUnwrappedOptional<T> is is dead, long live implicitly
unwrapped Optional<T>!
Resolves rdar://problem/33272674.
Replace ImplicitlyUnwrappedCoercionResult with the more general
ImplicitlyUnwrappedValue.
Add ImplicitlyUnwrappedDisjunctionChoice as a marker that indicates
that we've already created a disjunction from an
ImplicitlyUnwrappedValue, in order to avoid infinite recursion during
binding.
Also add support to buildDisjunctionForImplicitlyUnwrappedOptional for
functions returning optionals.
NFC.
When opening generic types with type parameter requirements,
add information about requirement location to the locator of each
generated constraint to make it easier to extract such information
if needed.
Using this constraint locator element, we can check when a failed
constraint is due to an unsatisfied conditional requirement of a
protocol conformance. Unfortunately, it's hard to turn this into
an actionable diagnostic right now.
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
Previously we would check TMF_UnwrappingOptional flag, which does not
stick with the constraint, so it would not always persist. Now, add a
new OptionalPayload locator element, which is more correct.
Fixes <rdar://problem/30429709>.
Simplify and improve the checking of @objc names when matching a
witness to a requirement in the @objc protocol. First, don't use
@objc-ness as part of the initial screening to determine whether a
witness potentially matches an @objc requirement: we will only reject
a potential witness when the potential witness has an explicit
"@nonobjc" attribute on it. Otherwise, the presence of @objc and the
corresponding Objective-C name is checked only after selecting a
candidate. This more closely mirrors what we do for override checking,
where we match based on the Swift names (first) and validate
@objc'ness afterward. It is also a stepping stone to inferring
@objc'ness and @objc names from protocol conformances.
Second, when emitting a diagnostic about a missing or incorrect @objc
annotation, make sure the Fix-It gets the @objc name right: this might
mean adding the Objective-C name along with @objc (e.g.,
"@objc(fooWithString:bar:)"), adding the name to an
unadorned-but-explicit "@objc" attribute, or fixing the name of an
@objc attribute (e.g., "@objc(foo:bar:)" becomes
@objc(fooWithString:bar:)"). Make this diagnostic an error, rather
than a note on a generic "does not conform" diagnostic, so it's much
easier to see the diagnostic and apply the Fix-It.
Third, when emitting the warning about a non-@objc near-match for an
optional @objc requirement, provide two Fix-Its: one that adds the
appropriate @objc annotation (per the paragraph above), and one that
adds @nonobjc to silence the warning.
Part of the QoI improvements for conformances to @objc protocols,
rdar://problem/25159872.
Simplify and improve the checking of @objc names when matching a
witness to a requirement in the @objc protocol. First, don't use
@objc-ness as part of the initial screening to determine whether a
witness potentially matches an @objc requirement: we will only reject
a potential witness when the potential witness has an explicit
"@nonobjc" attribute on it. Otherwise, the presence of @objc and the
corresponding Objective-C name is checked only after selecting a
candidate. This more closely mirrors what we do for override checking,
where we match based on the Swift names (first) and validate
@objc'ness afterward. It is also a stepping stone to inferring
@objc'ness and @objc names from protocol conformances.
Second, when emitting a diagnostic about a missing or incorrect @objc
annotation, make sure the Fix-It gets the @objc name right: this might
mean adding the Objective-C name along with @objc (e.g.,
"@objc(fooWithString:bar:)"), adding the name to an
unadorned-but-explicit "@objc" attribute, or fixing the name of an
@objc attribute (e.g., "@objc(foo:bar:)" becomes
@objc(fooWithString:bar:)"). Make this diagnostic an error, rather
than a note on a generic "does not conform" diagnostic, so it's much
easier to see the diagnostic and apply the Fix-It.
Third, when emitting the warning about a non-@objc near-match for an
optional @objc requirement, provide two Fix-Its: one that adds the
appropriate @objc annotation (per the paragraph above), and one that
adds @nonobjc to silence the warning.
Part of the QoI improvements for conformances to @objc protocols,
rdar://problem/25159872.