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 r31105
This commit is contained in:
Chris Lattner
2015-08-10 06:18:27 +00:00
parent 48276ecefd
commit de79b60c89
33 changed files with 186 additions and 76 deletions

View File

@@ -830,6 +830,18 @@ LookupConformanceResult Module::lookupConformance(Type type,
}
}
// UnresolvedType is a placeholder for an unknown type used when generating
// diagnostics. We consider it to conform to all protocols, since the
// intended type might have.
if (type->is<UnresolvedType>()) {
return {
ctx.getConformance(type, protocol, protocol->getLoc(), this,
ProtocolConformanceState::Complete),
ConformanceKind::Conforms
};
}
auto nominal = type->getAnyNominal();
// If we don't have a nominal type, there are no conformances.