The 'literalConformanceProto' field of
TypeVariableType::Implementation didn't take into account equivalence
classes of type variables. Eliminate it, and either look at the actual
expressions (for optimizing constraints during constraint generation)
or the actual constraints on a given type variable (for determining
whether to include optionals in the set of potential type variable
bindings).
While, tracking defaulted constraints based on their type variable
usually works in practice, it can break if the type variable ends up
being equivalent to some other type variable that. Instead, record the
locators associated with Defaultable constraints where we used the
default, which are easier to work with during constraint application.
We had a few places that were performing ad hoc variants of
ConstraintSystem::getFixedTypeRecursive(); simplify it's interface so
we can use it everywhere consistently. Fixes rdar://problem/27261929.
In most places where we were checking "is<ErrorType>()", we now mean
"any error occurred". The few exceptions are in associated type
inference, code completion, and expression diagnostics, where we might
still work with partial errors.
Type::subst()'s "IgnoreMissing" option was fairly unprincipled, dropping
unsubstituted types into the resulting AST without any indication
whatsoever that anything went wrong. Replace this notion with a new
form of ErrorType that explicitly tracks which substituted type caused
the problem. It's still an ErrorType, but it prints like the
substituted type (which is important for code completion) and allows
us to step back to the substituted type if needed (which is used by
associated type inference). Then, allow Type::subst(), when the new
UseErrorTypes flag is passed, to form partially-substituted types that
contain errors, which both code completion and associated type
inference relied on.
Over time, I hope we can use error-types-with-original-types more
often to eliminate "<<error type>>" from diagnostics and teach
Type::subst() never to return a "null" type. Clients can check
"hasError()" to deal with failure cases rather than checking null.
ExprCollector is extended to cover all generic collections instead of
only dictionary expressions. Contextual type propagation is extended
to support partial solving of collections embedded into coerce expressions.
This reverts commit f590a1ba03.
It breaks this kind of code:
test.swift:2:34: error: cannot convert value of type 'Int' to expected element type 'UInt32'
let lengthBytes: [UInt32] = [55 * 8, 0]
~~~^~~
UInt32( )
ExprCollector is extended to cover all generic collections instead of
only dictionary expressions. Contextual type propagation is extended
to support partial solving of collections embedded into coerce expressions.
Instead of failing shrinking when there are no solutions for current
sub-expression, let's restore overload domains for previously solved
sub-expressions and move on trying to solve next expression in the queue.
DPC algorithm tries to solve individual sub-expressions and combine
resolved types as a way to reduce pre-existing OSR domains. Solving
is done bottom-up so each consecutive sub-expression tightens
possible solution domain even further.
DPC algoritm tries to solve individual sub-expressions and combine
resolved types as a way to reduce pre-existing OSR domains. Solving
is done bottom-up so each consecutive sub-expression tightens
possible solution domain even further.
Simplify e.g., ASTContext::getBridgedToObjC(), which no longer needs
the optional return.
Eliminate the now-unused constraint kind for checking bridging to
Objective-C.
The join operation for optional types is straightforward to define/implement:
join(T?, U) ::= join(T, U)?
join(T, U?) ::= join(T, U)?
join(T?, U?) ::= join(T, U)?
As a special case in the constraint solver, handle the join of a 'nil'
literal with a non-ExpressibleByNilLiteral-conforming concrete type
'T' to produce 'T?'. This allows us, e.g., infer [String?] for the
expressions
["hello", nil]
and
true ? "hello" nil
for example. Fixes rdar://problem/16326914.
The id-as-Any work regressed cases where Swift code could specify
heterogeneous collection literals, e.g.,
var states: [String: Any] = [
"California": [
"population": 37_000_000,
"cities": ["Los Angeles", "San Diego", "San Jose"],
],
"Oregon": [
"population": 4_000_000,
"cities": ["Portland", "Salem", "Eugene"],
]
]
Prior to this, the code worked (when Foundation was imported) because
we'd end up with literals of type [NSObject : AnyObject].
The new defaulting rule says that the element type of an array literal
and the key/value types of a dictionary literal can be defaulted if no
stronger type can be inferred. The default type is:
Any, for the element type of an array literal or the value type of a
dictionary literal, or
AnyHashable, for the key type of a dictionary literal.
The latter is intended to compose with implicit conversions to
AnyHashable, so the most-general inferred dictionary type is
[AnyHashable : Any] and will work for any plausible dictionary
literal.
To prevent this inference from diluting types too greatly, we don't
allow this inference in "top-level" expressions, e.g.,
let d = ["a" : 1, "b" : "two"]
will produce an error because it's a heterogeneous dictionary literal
at the top level. One should annotate this with, e.g.,
let d = ["a" : 1, "b" : "two"] as [String : Any]
However, we do permit heterogeneous collections in nested positions,
to support cases like the original motivating example.
Fixes rdar://problem/27661580.
Stub out a simplistic 'meet' operation for types that currently only
handles finding the meet of two class types. Use it to optimize the
constraint solver ever so slightly: when we see a type variable whose
constraints state that it is a supertype of two different concrete
types, we attempt to compute their meet and, if we find it, only
produce one potential binding that is the meet itself.
Note that this is an extremely poor implementation of this concept
that is meant to address a specific regression being introduced by the
defaulting of collection literal element types. A real implementation
would, at the very least:
* Implement a proper 'meet' that covers all subtyping in the language.
* Distinguish between "I don't know if there is a meet" and "I am
absolutely certain that there is no meet".
* Collapse the constraints themselves to reduce the number of
constraints in the system, rather than just the number of type
variable bindings we attempt.
change includes both the necessary protocol updates and the deprecation
warnings
suitable for migration. A future patch will remove the renamings and
make this
a hard error.
ones, look through any lvalue types. Doing so can
prevent improper double-optional binds, which can
cause unexpected runtime behavior.
(rdar://problem/26360502)
This is a squash of the following commits:
* [SE-0054] Import function pointer arg, return types, typedefs as optional
IUOs are only allowed on function decl arguments and return types, so
don't import typedefs or function pointer args or return types as IUO.
* [SE-0054] Only allow IUOs in function arg and result type.
When validating a TypeRepr, raise a diagnostic if an IUO is found
anywhere other thn the top level or as a function parameter or return
tpye.
* [SE-0054] Disable inference of IUOs by default
When considering a constraint of the form '$T1 is convertible to T!',
generate potential bindings 'T' and 'T?' for $T1, but not 'T!'. This
prevents variables without explicit type information from ending up with
IUO type. It also prevents implicit instantiation of functions and types
with IUO type arguments.
* [SE-0054] Remove the -disable-infer-iuos flag.
* Add nonnull annotations to ObjectiveCTests.h in benchmark suite.
as well as on parameter decls. Also, tighten up the type checker to look at
parameter types instead of decl attributes in some cases (exposing a type
checker bug).
Still TODO:
- Reject autoclosure/noescape on non-parameter types.
- Move stdlib and other code to use noescape and autoclosure in the right
spot.
- Warn about autoclosure/noescape on parameters decls, with a fixit to move it.
- Upgrade the warning to an error.
If this option is enabled, when generating potential bindings for a type
variable, don't propagate IUO type. Instead try the optional type and
the underlying type. This way, untyped bindings will not be given IUO
type when they are initialized with exprs of IUO type.
Note that the typecheck perf for these kinds of expressions still isn't fantastic, but at least they're now computationally feasible. I have further improvements planned for this area which should bring performance in line with expectations.
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.
This is a really nasty problem where we'd explode trying to unify type variables
we found in the constraint graph, that didn't exist in the constraint system. This
happened because diagnostic generation is simplifying the system in
"ContinueAfterFailures" mode to try to get to a minimal system (to avoid
producing an error message about trivially solvable constraints that only
exist due to the solver stopping early) and in this mode we would see an
erroneous constraint, remove it from the constraint system, but not the
constraint graph. This only mattered in ContinueAfterFailures.
As with many things, the fix is pretty simple once the onion is peeled enough
to find the stinky part lurking inside.
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
bindings only bound the type variable from above with existential types.
<rdar://problem/22459135> error: 'print' is unavailable: Please wrap your tuple argument in parentheses: 'print((...))'
Swift SVN r31953
the regressions that r31105 introduced in the validation tests, as well as fixing a number
of other validation tests as well.
Introduce a new UnresolvedType to the type system, and have CSDiags start to use it
as a way to get more type information out of incorrect subexpressions. UnresolvedType
generally just propagates around the type system like a type variable:
- it magically conforms to all protocols
- it CSGens as an unconstrained type variable.
- it ASTPrints as _, just like a type variable.
The major difference is that UnresolvedType can be used outside the context of a
ConstraintSystem, which is useful for CSGen since it sets up several of them to
diagnose subexpressions w.r.t. their types.
For now, our use of this is extremely limited: when a closureexpr has no contextual
type available and its parameters are invalid, we wipe them out with UnresolvedType
(instead of the previous nulltype dance) to get ambiguities later on.
We also introduce a new FreeTypeVariableBinding::UnresolvedType approach for
constraint solving (and use this only in one place in CSDiags so far, to resolve
the callee of a CallExpr) which solves a system and rewrites any leftover type
variables as UnresolvedTypes. This allows us to get more precise information out,
for example, diagnosing:
func r22162441(lines: [String]) {
lines.map { line in line.fooBar() }
}
with: value of type 'String' has no member 'fooBar'
instead of: type of expression is ambiguous without more context
This improves a number of other diagnostics as well, but is just the infrastructural
stepping stone for greater things.
Swift SVN r31130
as a way to get more type information out of incorrect subexpressions. UnresolvedType
generally just propagates around the type system like a type variable:
- it magically conforms to all protocols
- it CSGens as an unconstrained type variable.
- it ASTPrints as _, just like a type variable.
The major difference is that UnresolvedType can be used outside the context of a
ConstraintSystem, which is useful for CSGen since it sets up several of them to
diagnose subexpressions w.r.t. their types.
For now, our use of this is extremely limited: when a closureexpr has no contextual
type available and its parameters are invalid, we wipe them out with UnresolvedType
(instead of the previous nulltype dance) to get ambiguities later on.
We also introduce a new FreeTypeVariableBinding::UnresolvedType approach for
constraint solving (and use this only in one place in CSDiags so far, to resolve
the callee of a CallExpr) which solves a system and rewrites any leftover type
variables as UnresolvedTypes. This allows us to get more precise information out,
for example, diagnosing:
func r22162441(lines: [String]) {
lines.map { line in line.fooBar() }
}
with: value of type 'String' has no member 'fooBar'
instead of: type of expression is ambiguous without more context
This improves a number of other diagnostics as well, but is just the infrastructural
stepping stone for greater things.
Swift SVN r31105
and use it in the diagnostics path (only!) to revisit active constraints that
are left in the system after a failure is found. This improves a number of
otherwise sad diagnostics in the testsuite and resolves rdar://22083115.
The one QoI regression (in throwing_functions.swift) is now tracked by 22158167.
Swift SVN r31027