When the compiler fails to find an overload with suitable parameter or return types, it often attaches a note listing the available overloads so that users can find the one they meant to use. The overloads are currently ordered in a way that depends on the order they were declared, so swift-evolve would sometimes cause tests involving these diagnostics to fail.
This change emits the list in a textually-sorted order instead. The names were already being sorted as they were inserted into a std::set, so this shouldn’t significantly slow down the diagnostic.
...unless the argument is an `Any?`, in which case we prefer `f(_: Any?)`.
This change also results in our selecting f<T>(_: T) over f(_:
Any). Coercing with 'as Any' makes it possible to explicitly select
the Any overload. Previously there was no way to select the generic
overload.
Treat non-optional generic parameters as being more specialized than
optional generic parameters, and penalize any solutions that involve
generic arguments that are themselves Optional.
By doing these things, we can remove the special-cased code for the
two overloads of '??' in the stdlib, instead treating the (T?, T)
overload as better than the (T?, T?) overload except where a user
actually passes an optionally-typed value as the second parameter.
Fixes: rdar://problem/19748710
When we determine that an optional value needs to be unwrapped to make
an expression type check, use notes to provide several different
Fix-It options (with descriptions) rather than always pushing users
toward '!'. Specifically, the errors + Fix-Its now looks like this:
error: value of optional type 'X?' must be unwrapped to a value of
type 'X'
f(x)
^
note: coalesce using '??' to provide a default when the optional
value contains 'nil'
f(x)
^
?? <#default value#>
note: force-unwrap using '!' to abort execution if the optional
value contains 'nil'
f(x)
^
!
Fixes rdar://problem/42081852.
For the purposes of partial ordering of declarations (e.g., in
overload resolution), adjust `@autoclosure` parameter types to the
result type of the autoclosure, i.e., the type against which the
argument will be matched. This makes overload resoluton agnostic to
`@autoclosure`.
Fixes SR-6472.
There are possible situations when we find solutions with String
and String -> UnsafePointer conversions at the same time for
expressions with default string literals. In order to disambiguite
such situations let's prefer solutions without String -> UnsafePointer
conversions if possible.
Recent changes to the stdlib resulted in some expressions involving
literals and operators that have both generic and non-generic overloads
to become ambiguous. The ambiguity is due to an old performance hack in
the solver which unfortunately needs to remain in place at the moment to
avoid regressing expression type checker performance.
This commit changes the performance hack a bit in that instead of
stopping visiting the options in a disjunction as soon as we have a
solution involving non-generic operators and come across a constraint
involving generic operators, we instead continue visiting the elements
in the disjunction, but just skip over the generic operators.
Fixes rdar://problem/31695865 and rdar://problem/31698831.
When comparing the parameters of two declarations for the purpose of
partial ordering, it doesn't make sense to compare the parameter
labels: they're dealt with separately and aren't conceptually part of
the type.
We previously penalized bindings to Any, and that resulted in
inappropriately rejecting solutions where we bind a decl that is
explicitly typed Any. That penalty was removed in
170dc8acd7, but that has led to a variety
of source compatibility issues.
So now, we'll reintroduce a penalty for Any-typed things, but instead of
penalizing bindings (which happen both because of explicitly-typed
values in the source, and implicitly due to attempting various types for
a particular type variable), penalize casts, which are always present in
some form in the source.
Thanks go to John for the suggestion.
Fixes
SR-3817 (aka rdar://problem/30311052)
SR-3786 (aka rdar://problem/30268529)
rdar://problem/29907555
Otherwise, overload resolution and CSDiag disagree on what a viable
candidate is, so we can end up in a situation where the OverloadDeclRefExpr
has a concrete type that doesn't match the argument list in an ApplyExpr,
which causes a crash in CSDiag.
Add special logic to FailureDiagnosis::visitApplyExpr to
handle situation like following:
struct S {
mutating func f(_ i: Int) {}
func f(_ f: Float) {}
}
Given struct has an overloaded method "f" with a single argument of
multiple different types, one of the overloads is marked as
"mutating", which means it can only be applied on LValue base type.
So when struct is used like this:
let answer: Int = 42
S().f(answer)
Constraint system generator is going to pick `f(_ f: Float)` as
only possible overload candidate because "base" of the call is immutable
and contextual information about argument type is not available yet.
Such leads to incorrect contextual conversion failure diagnostic because
type of the argument is going to resolved as (Int) no matter what.
To workaround that fact and improve diagnostic of such cases we are going
to try and collect all unviable candidates for a given call and check if
at least one of them matches established argument type before even trying
to re-check argument expression.
Resolves: <rdar://problem/28051973>.
When comparing two functions for overload resolution, break apart the
parameter lists to compare individual parameters rather than comparing
the tuples. This allows us to prefer functions with fewer arguments to
ones with more, defaulted or variadic arguments. That preference was
already encoded in the constraint optimizer, which led to some strange
behavior where the preference was expressed for function calls but not
for calls to initializers. Fixes rdar://problem/24128153.
The standard library change tweaks the anachronistic, unavailable
"print" variants somewhat. The only behavior change here is a slight
regression for cases like:
print(a: 1, b: 2)
where we used to produce a diagnostic:
Please wrap your tuple argument in parentheses: 'print((...))'
but we now get:
argument labels '(a:, b:)' do not match any available overloads
However, this regression will happen at some point *anyway*, if
SE-0029 (or anything else that removes the implicit tuple splat
operation) goes through.
call expression onto a callee when it was a binary expression. Doing this
requires improving the diagnostics for when the contextual result type is
incompatible with all candidates, but that is general goodness all around.
This fixes:
<rdar://problem/22333090> QoI: Propagate contextual information in a call to operands
and improves a number of diagnostics where the problem is that an operator
is used in a context that expects a type that it cannot produce.
Swift SVN r31891
argument. For now we start with some of the most simple cases: single argument
calls. This dramatically improves the QoI for error messages in argument lists,
typically turning a error+note combo into a single specific error message.
Some minor improvements coming (and also generalizing this to n-ary calls), but it
is nice that all the infrastructure is starting to come together...
Swift SVN r30905
detailed analysis of callees, which give us overload sets in more cases,
producing notes more consistently, and producing much better diagnostics
for the curried cases in test/Constraints/diagnostics.swift.
This also allows us to eliminate getCalleeName, which simplifies things
in CSDiags.
Swift SVN r30491
we can start taking advantage of ambiguously typed subexpressions in CSDiags. We
start by validating the callee function of ApplyExprs, which substantially improves
our abilities to generate precise diagnostics about malformed calls.
This is the minimal introduction of this concept to CSDiags, a lot of refactoring
is yet to come, however, this is enough to resolve:
<rdar://problem/21080030> Bad diagnostic for invalid method call in boolean expression
<rdar://problem/21784170> Incongruous `unexpected trailing closure` error in `init` function which is cast and called without trailing closure.
one of the testcases from:
<rdar://problem/20789423> Unclear diagnostic for multi-statement closure with no return type
and a bunch of other places where we got weird "unexpected trailing closure"
diagnostics that made no sense. As usual, it is two steps forward and one step back,
as this exposed some other weird latent issues like:
<rdar://problem/21900971> QoI: Bogus conversion error in generics case
Swift SVN r30429
facilities used by operators etc. This required a bunch of changes to make
the diagnostics changes strictly an improvement:
- Teach the new path about calls to TypeExprs.
- Teach evaluateCloseness some simple things about varargs.
- Make the generic diagnosis logic produce a better error when there is
exactly one match.
Overall, the resultant diagnostics are a step forward: we now produce candidate
set notes more uniformly, and the messages about some existing ones are
more specific. This is just another stepping stone towards progress though.
Swift SVN r30057
is an instance method. Make sure it's a non-static function before
attempting to strip the implicit self parameter from the type.
<rdar://problem/20886179> compiler error
Swift SVN r29732
If 'x.init' appears as a member reference other than 'self.init' or 'super.init' within an initializer, treat it as a regular static member lookup for 'init' members. This allows a more explicit syntax for dynamic initializations; 'self.someMetatype()' looks too much like it's invoking a method. It also allows for partial applications of initializers using 'someMetatype.init' (though this needs some SILGen fixes, coming up next). While we're in the neighborhood, do some other correctness and QoI fixes:
- Only lookup initializers as members of metatypes, not instances, and add a fixit (instead of crashing) to insert '.dynamicType' if the initializer is found on an instance.
- Make it so that constructing a class-constrained archetype type correctly requires a 'required' or protocol initializer.
- Warn on unused initializer results. This seems to me like just the right thing to do, but is also a small guard against the fact that 'self.init' is now valid in a static method, but produces a newly-constructed value instead of delegating initialization (and evaluating to void).
Swift SVN r29344
This came out of today's language review meeting.
The intent is to match #available with the attribute
that describes availability.
This is a divergence from Objective-C.
Swift SVN r28484
This post-hoc diagnostic replaces r24915, r25045, and r25054 by doing a
very basic check for representation incompatibility between two types.
More cases can be added as necessary.
rdar://problem/19600325, again.
Swift SVN r25117
Most tests were using %swift or similar substitutions, which did not
include the target triple and SDK. The driver was defaulting to the
host OS. Thus, we could not run the tests when the standard library was
not built for OS X.
Swift SVN r24504
These changes make the following improvements to how we generate diagnostics for expression typecheck failure:
- Customizing a diagnostic for a specific expression kind is as easy as adding a new method to the FailureDiagnosis class,
and does not require intimate knowledge of the constraint solver’s inner workings.
- As part of this patch, I’ve introduced specialized diagnostics for call, binop, unop, subscript, assignment and inout
expressions, but we can go pretty far with this.
- This also opens up the possibility to customize diagnostics not just for the expression kind, but for the specific types
involved as well.
- For the purpose of presenting accurate type info, partially-specialized subexpressions are individually re-typechecked
free of any contextual types. This allows us to:
- Properly surface subexpression errors.
- Almost completely avoid any type variables in our diagnostics. In cases where they could not be eliminated, we now
substitute in "_".
- More accurately indicate the sources of errors.
- We do a much better job of diagnosing disjunction failures. (So no more nonsensical ‘UInt8’ error messages.)
- We now present reasonable error messages for overload resolution failures, informing the user of partially-matching
parameter lists when possible.
At the very least, these changes address the following bugs:
<rdar://problem/15863738> More information needed in type-checking error messages
<rdar://problem/16306600> QoI: passing a 'let' value as an inout results in an unfriendly diagnostic
<rdar://problem/16449805> Wrong error for struct-to-protocol downcast
<rdar://problem/16699932> improve type checker diagnostic when passing Double to function taking a Float
<rdar://problem/16707914> fatal error: Can't unwrap Optional.None…Optional.swift, line 75 running Master-Detail Swift app built from template
<rdar://problem/16785829> Inout parameter fixit
<rdar://problem/16900438> We shouldn't leak the internal type placeholder
<rdar://problem/16909379> confusing type check diagnostics
<rdar://problem/16951521> Extra arguments to functions result in an unhelpful error
<rdar://problem/16971025> Two Terrible Diagnostics
<rdar://problem/17007804> $T2 in compiler error string
<rdar://problem/17027483> Terrible diagnostic
<rdar://problem/17083239> Mysterious error using find() with Foundation types
<rdar://problem/17149771> Diagnostic for closure with no inferred return value leaks type variables
<rdar://problem/17212371> Swift poorly-worded error message when overload resolution fails on return type
<rdar://problem/17236976> QoI: Swift error for incorrectly typed parameter is confusing/misleading
<rdar://problem/17304200> Wrong error for non-self-conforming protocols
<rdar://problem/17321369> better error message for inout protocols
<rdar://problem/17539380> Swift error seems wrong
<rdar://problem/17559593> Bogus locationless "treating a forced downcast to 'NSData' as optional will never produce 'nil'" warning
<rdar://problem/17567973> 32-bit error message is really far from the mark: error: missing argument for parameter 'withFont' in call
<rdar://problem/17671058> Wrong error message: "Missing argument for parameter 'completion' in call"
<rdar://problem/17704609> Float is not convertible to UInt8
<rdar://problem/17705424> Poor error reporting for passing Doubles to NSColor: extra argument 'red' in call
<rdar://problem/17743603> Swift compiler gives misleading error message in "NSLayoutConstraint.constraintsWithVisualFormat("x", options: 123, metrics: nil, views: views)"
<rdar://problem/17784167> application of operator to generic type results in odd diagnostic
<rdar://problem/17801696> Awful diagnostic trying to construct an Int when .Int is around
<rdar://problem/17863882> cannot convert the expression's type '()' to type 'Seq'
<rdar://problem/17865869> "has different argument names" diagnostic when parameter defaulted-ness differs
<rdar://problem/17937593> Unclear error message for empty array literal without type context
<rdar://problem/17943023> QoI: compiler displays wrong error when a float is provided to a Int16 parameter in init method
<rdar://problem/17951148> Improve error messages for expressions inside if statements by pre-evaluating outside the 'if'
<rdar://problem/18057815> Unhelpful Swift error message
<rdar://problem/18077468> Incorrect argument label for insertSubview(...)
<rdar://problem/18079213> 'T1' is not identical to 'T2' lacks directionality
<rdar://problem/18086470> Confusing Swift error message: error: 'T' is not convertible to 'MirrorDisposition'
<rdar://problem/18098995> QoI: Unhelpful compiler error when leaving off an & on an inout parameter
<rdar://problem/18104379> Terrible error message
<rdar://problem/18121897> unexpected low-level error on assignment to immutable value through array writeback
<rdar://problem/18123596> unexpected error on self. capture inside class method
<rdar://problem/18152074> QoI: Improve diagnostic for type mismatch in dictionary subscripting
<rdar://problem/18242160> There could be a better error message when using [] instead of [:]
<rdar://problem/18242812> 6A1021a : Type variable leaked
<rdar://problem/18331819> Unclear error message when trying to set an element of an array constant (Swift)
<rdar://problem/18414834> Bad diagnostics example
<rdar://problem/18422468> Calculation of constant value yields unexplainable error
<rdar://problem/18427217> Misleading error message makes debugging difficult
<rdar://problem/18439742> Misleading error: "cannot invoke" mentions completely unrelated types as arguments
<rdar://problem/18535804> Wrong compiler error from swift compiler
<rdar://problem/18567914> Xcode 6.1. GM, Swift, assignment from Int64 to NSNumber. Warning shown as problem with UInt8
<rdar://problem/18784027> Negating Int? Yields Float
<rdar://problem/17691565> attempt to modify a 'let' variable with ++ results in typecheck error about @lvalue Float
<rdar://problem/17164001> "++" on let value could give a better error message
Swift SVN r23782
Start capitalizing on some of the new diagnostic machinery in a few different ways:
- When mining constraints for type information, utilize constraints "favored" by the overload resolution process.
- When printing type variables, if the variable was created by opening a literal expression, utilize the literal
default type or conformance if possible.
- Utilize syntactic information when crafting diagnostics:
- If the constraint miner can produce a better diagnostic than the recorded failure, diagnose via constraints.
- Factor in the expression kind when choosing which types to include in a diagnostic message.
- Start customizing diagnostics based on the amount of type data available.
What does all this mean?
- Fewer type variables leaking into diagnostic messages.
- Far better diagnostics for overload resolution failures. Specifically, we now print proper argument type data
for failed function calls.
- No more "'Foo' is not convertible to 'Foo'" error messages
- A greater emphasis on type data means less dependence on the ordering of failed constraints. This means fewer
inscrutable diagnostics complaining about 'UInt8' when all the constituent expressions are of type Float.
So we still have a ways to go, but these changes should greatly improve the number of head-scratchers served up
by the type checker.
These changes address the following radars:
rdar://problem/17618403
rdar://problem/17559042
rdar://problem/17007456
rdar://problem/17559042
rdar://problem/17590992
rdar://problem/17646988
rdar://problem/16979859
rdar://problem/16922560
rdar://problem/17144902
rdar://problem/16616948
rdar://problem/16756363
rdar://problem/16338509
Swift SVN r20927
Modify TypeBase::getRValueType to structurally convert lvalues embedded in tuple and paren types. Inside the constraint solver, coerce types to rvalues based on the structural 'isLValueType' test rather than shallow 'is<LValueType>' checking. Fixes <rdar://problem/17507421>, but exposes an issue with call argument matching and lvalues <rdar://problem/17786730>.
Swift SVN r20442
Expose Substitution's archetype, replacement, and conformances only through getters so we can actually assert invariants about them. To start, require replacement types to be materializable in order to catch cases where the type-checker tries to bind type variables to lvalue or inout types, and require the conformance array to match the number of protocol conformances required by the archetype. This exposes some latent bugs in the test suite I've marked as failures for now:
- test/Constraints/overload.swift was quietly suffering from <rdar://problem/17507421>, but we didn't notice because we never tried to codegen it.
- test/SIL/Parser/array_roundtrip.swift doesn't correctly roundtrip substitutions, which I filed as <rdar://problem/17781140>.
Swift SVN r20418
system has been "solved", meaning that all type variables have been
bound to concrete types or are completely free. Add the solvedness of
a particular system to the debug output.
Start adding some simple test cases.
Swift SVN r2706