Whenever we have a call, retrieve the argument labels from the
argument structurally and associate them with the callee. We were
previously doing this as a separate AST walk (which was unnecessary),
so fold that into constraint generation for a CallExpr.
This is a slightly-pared-back version of
3753d779bc that isn't so rigid in its
interpretation of ASTs. I'll tighten up the semantics over time.
Whenever we have a call, retrieve the argument labels from the
argument structurally and associate them with the callee. We were
previously doing this as a separate AST walk (which was unnecessary),
so fold that into constraint generation for a CallExpr. We were also
allowing weird ASTs to effectively disable this information: tighten
that up and require that CallExprs always have a ParenExpr, TupleExpr,
or (as a temporary hack) a TypeExpr whose representation is a
TupleTypeRepr as their argument prior to type checking. This gives us
a more sane AST to work with, and guarantees that we aren't losing
label information.
From the user perspective, this should be NFC, because it's mostly AST
cleanup and staging.
Implements the core functionality of SE-0064 / SR-1239, which
introduces support for accessing the Objective-C selectors of the
getter and setter of an @objc property via #selector(getter:
propertyName) and #selector(setter: propertyName).
Introduce a bunch of QoI around mistakes using #selector to refer to a
property without the "getter:" or "setter:", using Fix-Its to help the
user get it right. There is more to do in this area, still, but we
have an end-to-end feature working.
Much of the implementation and nearly all of the test cases are from
Alex Hoppen (@ahoppen). I've done a bit of refactoring, simplified the
AST representation, and replaced Alex's custom
expression-to-declaration logic with an extension to the constraint
solver. The last bit might be short-lived, based on swift-evolution
PR280, which narrows the syntax of #selector considerably.
With a TypeLoc, we have a chance to offer diagnostics or even fix-its
to the contextual type, even though it's not represented by an
expression in the constraint system. This commit mostly just passes it
through, without attempting to use it anywhere or even pass a real
TypeLoc (with a valid TypeRepr).
(It does drop the contextual type parameter from
typeCheckExpressionShallow, since there were zero callers using it.)
No functionality change...yet.
In the following code example, compiler emits an error of "cannot express tuple conversion...". However,
this is trivially fixable by adding multiple labels in the tuple pattern of the for-each statement. This
commit adds such fixit.
func foo(array : [(some: Int, (key: Int, value: String))]) {
for (i, (k, v)) in array {
}
}
a generic function type during constraint solving, as opposed to
checking a bunch of implicit things that we already know. This
should significantly improve the efficiency of checking uses of
generic APIs by reducing the total number of type variables and
constraints.
It is becoming increasingly funny to refer to this minimized generic
signature as the "mangling" signature.
The test changes are kind of a wash: in one case, we've eliminated
a confusing extra error, but in another we've caused the confusing
extra error to refer to '<<error type>>'. Not worth fighting right
now. The reference-dependencies change is due to not needing to
pull in all of those associated types anymore, which seems correct.
Type level lookups can fail because the lookup is on an existential
metatype, like `MyProtocol.staticMethod(_:)` is invalid; however the
error message is unclear: “static member 'staticMethod(_:)' cannot be
used on instance of type ‘MyProtocol.Protocol’”.
This fix checks the base of member lookups that failed with the reason
UR_TypeMemberOnInstance for being existential metatypes. It produces
the clearer message “static member ‘staticMethod(_:)’ cannot be used on
protocol metatype ‘MyProtocol.Protocol’”. This change makes it clear
that the use of a static member on the *existential* metatype is the
problem.
immediately discard as non-viable any declarations that cannot be
called due to argument-label mismatch.
This heuristic already existed, but it was badly out-of-date vs.
the current language rules on argument-passing. Change it to use
the standard argument matching algorithm.
This greatly reduces the number of overloads we consider for certain
kinds of expression, most importantly explicit initialization syntax
('T(x)'). Ordinary type-matching will quickly reject such calls,
but backtracking will discard this rejection. Thus this heuristic
can greatly decrease the total work done by the type-checker when
something else in the system is causing a combinatorial explosion.
The diagnostic changes in the test-suite seem acceptable to me.
Shout-out to Doug for pointing out multiple places where I didn't
need to reinvent the wheel.
In member ref expressions, if the base is optional, and the expected
expression result is either optional or unknown, suggest a fixit that
makes it into an optional chain expr rather than force unwrapping.
Since in many cases the actual fixit is emitted during diagnosis, and
thus, while type checking sub exprs with no contextual type specified
(so nothing to check for preferring optionality), we also need an
additional flag to pass down from FailureDiagnosis for whether we
prefer to fix as force unwrapping or optional chaining.
I attempted to do this same job via providing a convert type but
setting the ConvertTypeIsOnlyAHint flag on the type checker, but
unfortunately there are a lot of other moving parts that look at that
type, even if it is only supposed to be a hint, so an additional flag
to the CS ended up being cleaner.
The two types are nearly identical, and Fixnum is only in the Swift branches of LLVM,
not in mainline LLVM.
I do want to add ++ to PointerEmbeddedInt and fix some of this ugliness, but that'll
have to go through LLVM review, so it might take a bit.
This reverts commit 5ce503c886 because it
breaks the stdlib build with:
Assertion failed: (!isPolymorphic() && "no args for polymorphic substitution"), function substGenericArgs
for initializer lookup, allowing it to produce more specific diagnostics
when referring to a private initializer that the compiler can see.
In addition to improving diagnostics, this allows us to eliminate the
NoPublicInitializers failure kind.
When member lookup completely fails and when CSDiags is the one performing
the lookup, reissue another lookup that ignores access control. This allows
it to find inaccessible members and diagnose them as such, instead of pretending
we have no idea what the user wants. We now produce an error message like this:
main.swift:1:6: error: 'foo' is inaccessible due to 'private' protection level
C().foo()
^
test.swift:1:35: note: 'foo' declared here
internal class C { private func foo() {} }
^
instead of:
main.swift:1:2: error: value of type 'C' has no member 'foo'
C().foo()
^~~ ~~~
Eliminate the last client of DependentTypeOpener,
RequirementTypeOpener, which tracked the opened Self type when doing
witness/requirement matching and substituted in the known type
witnesses for that protocol. It had a bunch of dead logic hanging
around from the days where we used the constraint system to deduce
type witnesses. Now, a simple substitution suffices.
With its last client gone, remove DependentTypeOpener as well.
The ArchetypeOpener was used only to replace dependent types with
archetypes (or concrete types) within the opening context. We can do
the same simply by letting the constraint system create type variables
and then binding those type variables to the appropriate
archetypes/concrete types in that context.
Eliminate the two DependentTypeOpener entry points that were only used
by the ArchetypeOpener.
Now that generic signatures of types include generic parameters
introduced by outer generic functions, we need to know to skip
them when forming bound generic types or substitutions.
Add a function that computes the depth of the innermost generic
context that is not a generic type context.
This time, the issue is that TypeNullifier skips bodies of
multi-statement closures. However, ExprRewriter will type
happily pass them on to typeCheckClosureBody(). This could
trigger assertions. Fix this by skipping type checking of
multi-statement closures when diagnosing.
There seems to be a minor QoI regression in some test cases
that already looked pretty dodgy and/or had FIXMEs. However
I think its worth fixing a crash.
This case attempts to diagnose assignment into an invalid lvalue which only had
a computable type due to a fixit that the constraint solver was assuming. In this
situation, don't diagnose the invalid lvalue at all, diagnose the required fix.
Introduce a new constraint kind, BindParam, which relates the type of a
function parameter to the type of a reference to it from within the
function body. If the param type is an inout type, the ref type is an
lvalue type with the same underlying object type; otherwise the two
types must be the same. This prevents DeclRefExprs from being inferred
to have inout type in some cases.
<rdar://problem/15998821> Fail to infer types for closure that takes an inout argument
Swift SVN r32183
of providing contextual diagnostics (e.g. producing the warning in
Constraints/dynamic_lookup.swift). This drops a specific diagnostic about
force casting the result of as! which was added in the Swift 1.2 timeframe
to explain the change in cast semantics. Now that as! has been around for
a long time, it is more confusing than helpful.
Swift SVN r31887
- Enhance the branch new argument label overload diagnostic to just
print the argument labels that are the problem, instead of printing
the types inferred at the argument context. This can lead to confusion
particularly when an argument label is missing. For example before:
error: argument labels '(Int)' do not match any available overloads
note: overloads for 'TestOverloadSets.init' exist with these partially matching parameter lists: (a: Z0), (value: Int), (value: Double)
after:
error: argument labels '(_:)' do not match any available overloads
note: overloads for 'TestOverloadSets.init' exist with these partially matching parameter lists: (a: Z0), (value: Int), (value: Double)
Second, fix <rdar://problem/22451001> QoI: incorrect diagnostic when argument to print has the wrong type
by specifically diagnosing the problem when you pass in an argument to a nullary function. Before:
error: cannot convert value of type 'Int' to expected argument type '()'
after:
error: argument passed to call that takes no arguments
print(r22451001(5))
^
Swift SVN r31795