Not all types are l-valuable, notably InoutType's. This seems like a
weird restriction to put in the type checker, but it is the cleanest
solution to this. The better solution would be to change how
inoutexpr/inouttype are represented completely... maybe someday.
In both figuring out candidate closeness and in diagnosing generic
parameter errors, if the parameter is a GenericTypeParamType, get its
decl’s archetype to perform archetype substitutability checking upon.
If the mismatched argument is on an archetype param, check to see
whether the argument conforms to all of the protocols on the archetype,
using a specific does-not-conform diagnosis if one or more protocols
fail.
Also added another closeness class
`CC_GenericNonsubstitutableMismatch`, which happens when more than one
argument is a mismatch, but all the failing arguments are of the same
type and mismatch only because of substitutability. This closeness is
farther away than normal `CC_ArgumentMismatch` so that if we note
expected matches, we’ll prefer non-generic matches. But if this is the
result, we can still produce the specific conforms-to-protocol
diagnosis (since, in a sense, it’s only one type of argument that is
wrong even though it is multiple arguments).
In the specific case of sr-69, and in a bunch of other code where
errors arise involving generic function application, better type
constraint failure diagnoses are being masked by the overly
conservative implementation in evaluateCloseness(). If the actual arg
types didn’t exactly match the parameter types, we’d always diagnose a
non-specific arguments-don’t-match error instead of allowing discovery
of better errors from the constraint system.
This commit adds more cases where evaluateCloseness will return
CC_ExactMatch, specifically in application of functions with one or
more arguments of a single archetype, like `func min<T: Comparable>(T,
T) -> T`. It verifies that the actual argument type
isSubstitutableFor() the archetype, and that all such arguments are of
the same type. Anything more complicated than that still has the
previous behavior of not matching at all.
I think the final answer here ought to be to make a constraint system
with type variables for any archetypes, add appropriate constraints to
the actual args and then see if the system can solve all the argument
constraints at once. That’s because the next most complicated set of
things to handle in the stdlib are things like `func -<T:
Strideable>(lhs: T, rhs: T.Stride)` where generic argument types depend
on each other. I tried attacking that, but it was too big of a bite for
me to manage all at once. But there are FIXME’s here to try that again
at some point.
New tests for SR-69 are at the end of deduction.swift, and the rest of
the test changes are generally improved deduced diagnoses. I think the
changed diagnoses in materializable_restrictions.swift is the only one
which is worse instead of better, and that’s just because the previous
general message mentioned `inout` basically accidentally. Opportunity
for further improvement (a new diagnosis maybe) there.
Validation tests run and passed.
Adds an associatedtype keyword to the parser tokens, and accepts either
typealias or associatedtype to create an AssociatedTypeDecl, warning
that the former is deprecated. The ASTPrinter now emits associatedtype
for AssociatedTypeDecls.
Separated AssociatedType from TypeAlias as two different kinds of
CodeCompletionDeclKinds. This part probably doesn’t turn out to be
absolutely necessary currently, but it is nice cleanup from formerly
specifically glomming the two together.
And then many, many changes to tests. The actual new tests for the fixits
is at the end of Generics/associated_types.swift.
Rearrange diagnoseGeneralConversionFailure to diagnose structural problems
even if we have some UnresolvedTypes floating around, then reject constraint
failures with UnresolvedTypes in them even harder. This keeps us giving
good errors about failures where we have a structural problem (with buried
irrelevant details) while not complaining about cases that are actually
ambiguous.
The end result of this is that we produce a lot better error messages in the
case of failed archetype inference. This also highlights the poor job we do
handling multi-stmt closureexprs...
On something like this:
let x = .Tomato(cloud: .None)
we previously emitted a "type of expression is ambiguous without more context" error
while pointing to .None. With a previous fix, we now produce the same error pointing
to the .Tomato. With this fix, we now produce:
error: reference to member 'Tomato' cannot be resolved without a contextual type
to really drive the problem home.
a constraint system in "allowFreeTypeVariables" mode. Previously, we
only allowed a few specific constraints, now we allow any relational and
member constraints. The later one is a big deal because it means that we
can allow ".Foo" expressions as ambiguous solutions, which CSDiags can
handle well.
This unblocks solving 23942743 and enables some minor improvements across
the board, including diagnosing things like this better:
Optional(.none) // now: generic parameter 'T' could not be inferred
That said, it also just permutes some non-awesome diagnostics.
Parameters (to methods, initializers, accessors, subscripts, etc) have always been represented
as Pattern's (of a particular sort), stemming from an early design direction that was abandoned.
Being built on top of patterns leads to patterns being overly complicated (e.g. tuple patterns
have to have varargs and default parameters) and make working on parameter lists complicated
and error prone. This might have been ok in 2015, but there is no way we can live like this in
2016.
Instead of using Patterns, carve out a new ParameterList and Parameter type to represent all the
parameter specific stuff. This simplifies many things and allows a lot of simplifications.
Unfortunately, I wasn't able to do this very incrementally, so this is a huge patch. The good
news is that it erases a ton of code, and the technical debt that went with it. Ignoring test
suite changes, we have:
77 files changed, 2359 insertions(+), 3221 deletions(-)
This patch also makes a bunch of wierd things dead, but I'll sweep those out in follow-on
patches.
Fixes <rdar://problem/22846558> No code completions in Foo( when Foo has error type
Fixes <rdar://problem/24026538> Slight regression in generated header, which I filed to go with 3a23d75.
Fixes an overloading bug involving default arguments and curried functions (see the diff to
Constraints/diagnostics.swift, which we now correctly accept).
Fixes cases where problems with parameters would get emitted multiple times, e.g. in the
test/Parse/subscripting.swift testcase.
The source range for ParamDecl now includes its type, which permutes some of the IDE / SourceModel tests
(for the better, I think).
Eliminates the bogus "type annotation missing in pattern" error message when a type isn't
specified for a parameter (see test/decl/func/functions.swift).
This now consistently parenthesizes argument lists in function types, which leads to many diffs in the
SILGen tests among others.
This does break the "sibling indentation" test in SourceKit/CodeFormat/indent-sibling.swift, and
I haven't been able to figure it out. Given that this is experimental functionality anyway,
I'm just XFAILing the test for now. i'll look at it separately from this mongo diff.
This adds special tuned diagnostics to handle the case when someone attempts to index
a string with an integer value, which is pretty common to do for people new to Swift.o
That said, this only handles one special case, if there are other cases that are
common, I'd love to hear about them. Subscripts are already handled with a different
approach, I'm not sure which is better, but I added a testcase for both of them.
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.
It is a somewhat common case where folks are accidentally referring to an
instance member with the Type as the base. This forms a curried member,
which then produced head scratching error messages downstream.
Now that the prep work has gone in, the first part of this is now
straight-forward to fix: simply check for this case and diagnose it
with a custom error, which makes it more clear what the mistake was.
The other half of this problem (tracked by 22108559) affects cases where
the method you're calling takes a single argument. This isn't fixed
yet, but I'm adding a testcase for it anyway.
the code to be actually readable since it unnests it greatly), and call it
both before and after argument type validation. This allows us to capture
many more structural errors than before, leading to much better diagnostics
in a lot of cases. This also fixes the specific regressions introduced by
96a1e96.
overloaded argument list mismatches. We printed them in simple cases
due to "Failure" detecting them in trivial situations. Instead of
doing that, let CSDiags do it, which allows us to pick things out of
overload sets and handle the more complex cases well.
This is a progression across the board except for a couple of cases
where we now produce "cannot convert value of type 'whatever' to
expected argument type '(arglist)'", this is a known issue that I'll
fix in a subsequent commit.
These APIs are from the Swift 1.2 => Swift 2.0 transition, and are not
relevant anymore.
Removing them reduces the surface area of the library that needs to be
reviewed.
Previously we erroneously complained:
error: cannot invoke 'contains' with an argument list of type '(String)'
now we correctly complain:
error: unexpected non-void return value in void function
This enhances CSDiags to use "getTypeOfMember" when analyzing method
candidates that are applied to a known base type. Using it allows us to
substitute information about the base, resolving archetypes that exist in
subsequent argument positions. In the testcase, this means that we use
information about Set<String> to know that the argument to "contains" is a
String.
This allows us to generate much better diagnostics in some cases, and works
around some limitations in the existing stuff for handling unresolved
archetypes. One unfortunate change is the notes in Misc/misc_diagnostics.swift.
Because we don't track argument lists very well, we are flattening an argument
list that is actually ((Int,Int)) into (Int, Int) so we get a bogus looking
diagnostic. This was possible before this patch though, it is just one
more case that triggers the issue.
The original issue has long since been fixed, but we were now producing:
error: cannot subscript a value of type 'UnsafePointer<Int8>'
which is pretty obviously wrong. The problem is that when ranking subscript
decl candidates, CSDiags was using TC.isConvertibleTo to evaluate whether the
actual base type is compatible with the base type of a subscript decl. This
was failing when the base was generic, because the logic isn't opening
archetypes. Instead of incorrectly deciding that they are incompatible, just
decide we don't know if an archetype is present. This allows us to generate
good errors in situation like this.
A crash in CSDiag that happened when we were unconditionally looking at the
getter of a subscript. This failed on UnsafeMutablePointer because it only
has addressors, not getter/setters.
and probably others.
When we're type-checking a failed ApplyExpr that has an overload set that
prevents getting a specific type to feed into the initial typechecking of
the argument list, ranking can often narrow down the list of candidates
further, to the point where there is only one candidate left or where all
candidates agree that one argument is wrong.
In this case, re-type-check the subexpr with the expected type. In the case of
rdar://problem/22243469 we now produce:
t.swift:6:11: error: invalid conversion from throwing function of type '() throws -> ()' to non-throwing function type '() -> Void'
process {
^
instead of:
t.swift:6:3: error: cannot invoke 'process' with an argument list of type '(() throws -> ())'
process {
^
t.swift:6:3: note: overloads for 'process' exist with these partially matching parameter lists: (UInt, fn: () -> Void)
process {
^
Which is a heck of a lot less specific. Similarly, in the testcase from rdar://23550816, instead
of producing:
takeTwoFuncsWithDefaults { $0 + 1 }
error: cannot invoke 'takeTwoFuncsWithDefaults' with an argument list of type '((Int -> Int)?)'
note: expected an argument list of type '(f1: (Int -> Int)?, f2: (String -> String)?)'
we now produce:
error: cannot convert value of type '_ -> Int' to expected argument type '(String -> String)?'
which is a lot closer to what we want to complain about.