mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Sema: Don't crash when key path literals appear in PartialKeyPath context.
And make an attempt to use the constraint system's contextualType to bind type information; this makes things better but doesn't seem to be a complete solution for contextually typing key paths.
This commit is contained in:
@@ -3776,7 +3776,7 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
|
||||
|
||||
keyPathTy = getFixedTypeRecursive(keyPathTy, /*want rvalue*/ true);
|
||||
auto tryMatchRootAndValueFromKeyPathType =
|
||||
[&](BoundGenericType *bgt) -> SolutionKind {
|
||||
[&](BoundGenericType *bgt, bool allowPartial) -> SolutionKind {
|
||||
Type boundRoot, boundValue;
|
||||
|
||||
// We can get root and value from a concrete key path type.
|
||||
@@ -3786,9 +3786,13 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
|
||||
boundRoot = bgt->getGenericArgs()[0];
|
||||
boundValue = bgt->getGenericArgs()[1];
|
||||
} else if (bgt->getDecl() == getASTContext().getPartialKeyPathDecl()) {
|
||||
// We can still get the root from a PartialKeyPath.
|
||||
boundRoot = bgt->getGenericArgs()[0];
|
||||
boundValue = Type();
|
||||
if (allowPartial) {
|
||||
// We can still get the root from a PartialKeyPath.
|
||||
boundRoot = bgt->getGenericArgs()[0];
|
||||
boundValue = Type();
|
||||
} else {
|
||||
return SolutionKind::Error;
|
||||
}
|
||||
} else {
|
||||
// We can't bind anything from this type.
|
||||
return SolutionKind::Solved;
|
||||
@@ -3804,14 +3808,26 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
|
||||
|
||||
return SolutionKind::Solved;
|
||||
};
|
||||
|
||||
// If the key path type is bound from context, feed that into the root and
|
||||
// value types.
|
||||
|
||||
// If we're fixed to a bound generic type, trying harvesting context from it.
|
||||
// However, we don't want a solution that fixes the expression type to
|
||||
// PartialKeyPath; we'd rather that be represented using an upcast conversion.
|
||||
if (auto keyPathBGT = keyPathTy->getAs<BoundGenericType>()) {
|
||||
if (tryMatchRootAndValueFromKeyPathType(keyPathBGT) == SolutionKind::Error)
|
||||
if (tryMatchRootAndValueFromKeyPathType(keyPathBGT, /*allowPartial*/false)
|
||||
== SolutionKind::Error)
|
||||
return SolutionKind::Error;
|
||||
}
|
||||
|
||||
// If the expression has contextual type information, try using that too.
|
||||
if (auto contextualTy = getContextualType(keyPath)) {
|
||||
if (auto contextualBGT = contextualTy->getAs<BoundGenericType>()) {
|
||||
if (tryMatchRootAndValueFromKeyPathType(contextualBGT,
|
||||
/*allowPartial*/true)
|
||||
== SolutionKind::Error)
|
||||
return SolutionKind::Error;
|
||||
}
|
||||
}
|
||||
|
||||
// See if we resolved overloads for all the components involved.
|
||||
enum {
|
||||
ReadOnly,
|
||||
@@ -3824,7 +3840,7 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
|
||||
|
||||
switch (component.getKind()) {
|
||||
case KeyPathExpr::Component::Kind::Invalid:
|
||||
return SolutionKind::Error;
|
||||
break;
|
||||
|
||||
case KeyPathExpr::Component::Kind::UnresolvedProperty:
|
||||
case KeyPathExpr::Component::Kind::UnresolvedSubscript: {
|
||||
|
||||
Reference in New Issue
Block a user