The root potential archetypes in an archetype builder are associated
with generic parameters. Start decoupling potential archetypes from a
specific GenericTypeParamType and instead work with the abstracted
depth/index. The goal here is to allow the same archetype builder to
be used within different generic environments (which includes both
different generic parameters and different archetypes).
As part of this, boost the archetype builder's GenericTypeParamKey
from a local type to a more generic GenericParamKey that can be used
in other interfaces that want to work with abstracted generic
parameters.
This triggered with an existing test that was run against
some other changes I was working on, but the current code
does not demonstrate the problem.
However, it's "obviously" more "correct", so here we go.
When collecting callee candidates, get the interface type and map it
into context, rather than calling getType() directly.
This produces almost the same result as getType(), except for two
differences:
1) where getType() would return a PolymorphicFunctionType with
a reference to the original generic parameters, now CSDiag just
sees a simple FunctionType appears with discombobulated archetypes.
This is fine since CSDiag does not do anything specific with
PolymorphicFunctionTypes.
2) substGenericArgs() calls Type::subst(), which produces
SubstitutedType sugar. This would confuse CSDiag, which was not
prepared to see SubstitutedTypes that arise from this particular
call of Type::subst().
As mentioned in a previous commit message, CSDiag should be
refactored to get substitutions via a call to getMemberSubstitutions(),
instead of 'recovering' them from result of getTypeOfMember().
Until this can be fixed, I'm just manually stripping off any
SubstitutedTypes that appear from the call to substGenericArgs().
A better approach here would be to redo the callee diagnostics
stuff to look at interface types, plumbing through the correct
generic signatures. Then questions like 'what protocols does this
generic parameter conform to' can be asked of the signature and
interface type, instead of looking at archetypes.
When matching a potential callee type against the actual argument
types in a call expression, CSDiag would walk both types in parallel,
noting differences and recording archetype substitutions in a map.
We would also walk the callee type and attempt to recover substitutions
that came from a 'self.foo' method application where self is a generic
nominal type. This relied on the fact that Type::subst() leaves behind
the old types in the form of SubstitutedType sugar.
Only one of the two call sites of findGenericSubstitutions() used the
second feature, so move the SubstitutedType walk over to that call site
instead of doing it for both.
Unfortunately the SubstitutedType walk is somewhat fragile, because
multiple subst() calls with different generic contexts will leave behind
an unpredictable structure of SubstitutedTypes. The code in CSDiag has
some heuristics to bail out when things don't make sense, but I think it
would be simpler to just call getMemberSubstitutions() and pass around
the substitution map together with the substituted type and original decl.
Notably, the only other place we rely on SubstitutedType showing up in
the result of Type::subst() is accessibility and availability checking
for nested typealiases, like 'Foo<T>.Bar', so it might be wise to redo
these passes to operate on the types of decls before we apply generic
parameters. Then we could remove SubstitutedType altogether.
Previously, getInterfaceType() would return getType() if no
interface type was set. Instead, always set an interface type
explicitly.
Eventually we want to remove getType() altogether, and this
brings us one step closer to this goal.
Note that ParamDecls are excempt from this treatment, because
they don't have a proper interface type yet. Cleaning this up
requires more effort.
Add a case to ExprRewriter.coerceToType which tries to look through
ImplicitlyUnwrappedOptional<T> and apply 'to-value' transformation
before coercing to required 'to' type.
Resolves: <rdar://problem/28023899>.
This handles situation when overload for the subscript hasn't been resolved
by constraint solver, such might happen, for example, if solver was allowed to
produce solutions with free or unresolved type variables (e.g. when running diagnostics).
Resolves: <rdar://problem/27329076>, <rdar://problem/28619118>, <rdar://problem/2778734>.
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 a generic parameter list fails to parse, we don't call
DeclContext::setGenericParams(), even though the generic
parameters are still available for name lookup.
This causes various crashes, which this patch fixes by
mapping the generic parameters to ErrorTypes.
Previously, getInterfaceType() would return getType() if no
interface type was set. Instead, always set an interface type
explicitly.
Eventually we want to remove getType() altogether, and this
brings us one step closer to this goal.
Note that ParamDecls are excempt from this treatment, because
they don't have a proper interface type yet. Cleaning this up
requires more effort.
Since 'try' or '=' can be folded with type expression at the same time,
Shallow simplifyTypeExpr() results '->' being escaped from TypeChecker.
For instance:
try () -> Int
Used to crash the compiler.
Also, never return nullptr for ArrowExpr. `1 -> Int` is invalid anyway.
Instead of leave ArrowExpr as is, construct ErrorTypeRepr for '1' part.
_ = (P1 & P2 -> P3 & P4).self
This expression is parsed as a single SequenceExpr, thus folded the same time.
We have to rescusively simplifyTypeExpr() both LHS and RHS.