This is a quick follow-up to
<https://github.com/apple/swift/pull/1160>, to replace the becoming
deprecated getArchetype() with doing the same thing via calling through
to ArchetypeBuilder with a declContext.
Uses findGenericSubstitutions() to do so. So this site could take
advantage of destructuring of more complex params containing generics.
Right now, though, that never happens. For complex params the
(unfortunately, worse) diagnosis happens in diagnoseFailureForExpr() on
the argument expression before reaching here. I’d like to improve that
in future work.
Correctly determine callee closeness for func/ops that include generics
as part of more complicated parameters, i.e. tuple or closure args
containing generics as elements or args/results. Still only handling
single archetypes.
Also added code to check generic substitutions already made in the callee
parameters, which further helps diagnosis.
When we have a contextual type of Optional<SomeNominal>, we get overload
lookup results indicating that the found member needs to look through the
optional. Do so!
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).
When one spells a compound declaration name in the source (e.g.,
insertSubview(_:aboveSubview:), keep track of the locations of the
base name, parentheses, and argument labels.
- Improve the specific cases of nil and empty collection literals.
- Improve cases of contextual member lookup where the result type of the looked up member disagrees with context.
- Add some fixme's to the testsuite for cases of this diagnostic that should be diagnosed in other ways.
This standardizes processing of callees in invalid applyexprs, eliminating
bogus diagnostics like:
t.swift:6:2: error: cannot invoke closure of type '() -> _' with an argument list of type '()'
we now properly diagnose the example in closure/closures.swift as ambiguous,
but don't do a particularly good job of saying why. That is to follow.
There are two problems here, first we were diagnosing type member
constraints with the "function 'foo' was used as a property" error,
which doesn't make sense.
Second, we were diagnosing member constraints as lookup failures when
the constraint was actually referring to an archetype in its anchor
expression that wasn't resolved. Address this by simply ignoring the
constraint and letting ambiguity resolution handle it.
Before:
t.swift:5:9: error: function 'foo' was used as a property; add () to call it
After:
t.swift:5:9: error: generic parameter 'T' could not be inferred
let a = foo()
t.swift:4:6: note: in call to function 'foo'
func foo<T: IntegerType>() -> T.Type { return T.self }
Thanks to Jordan for noticing this!
Producing single argument mismatches involving generics causes some
gross looking error messages if the generic mismatches get put into the
same closeness bucket as non-generic mismatches.
E.g. `var v71 = true + 1.0` used to produce `error: cannot convert
value of type 'Bool' to expected argument type 'Double’`, but would now
end up with `binary operator '+' cannot be applied to operands of type
'Bool' and 'Double’` `overloads for '+' exist with these partially
matching parameter lists: (Double, Double), (T, T.Stride), (T.Stride,
T)`.
Resolve this by adding CC_OneGenericArgumentNearMismatch and
CC_OneGenericArgumentMismatch, that are similar but ever so slightly
not as close as a mismatch involving non-generic functions. This gets
back the original error message in cases like the above, because there
is only one declaration of `+` which partially matches and is
non-generic, and the generic partial matches are now farther away.
But now single arg mismatches and nearness work for single-archetype
generic functions, as in the additions to the SR-69 test at the end of
deduction.swift.
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.
information about where the archetype was defined. Before:
t.swift:6:17: error: generic parameter 'T' could not be inferred
var a : Int = A.foo()
^
After:
t.swift:6:17: error: generic parameter 'T' could not be inferred
var a : Int = A.foo()
^
t.swift:2:8: note: 'T' declared as parameter to type 'A'
struct A<T> {
^
When a contextual conversion has a matching type, don't diagnose it as a
conversion error, the problem is due to something else (in this case, an
unresolved archetype somewhere else in the expression).
Before:
t.swift:6:17: error: cannot convert value of type 'Int' to specified type 'Int'
After:
t.swift:6:17: error: generic parameter 'T' could not be inferred
This should still be a bit better to provide information about where the T
archetype came from, but at least now it isn't completely wrong diagnostic.
UnresolvedConstructorExpr is not providing any value here; it's
essentially just UnresolvedDotExpr where the name refers to an
initializer, so use that instead. NFC
Basic implementatation of SE-0021, naming functions with argument
labels. Handle parsing of compound function names in various
unqualified-identifier productions, updating the AST representation of
various expressions from Identifiers to DeclNames. The result doesn't
capture all of the source locations we want; more on that later.
As part of this, remove the parsing code for the "selector-style"
method names, since we now have a replacement. The feature was never
publicized and doesn't make sense in Swift, so zap it outright.
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.
It is a common point of confusion that property initializers cannot access self, so
produce a tailored diagnostic for it.
Also, when building implicit TypeExprs for the self type, properly mark them implicit.
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()
^~~ ~~~