Skip to content

Commit 52da2d6

Browse files
committed
[Constraint system] Extend SolutionApplicationTarget with an init pattern.
Initializer expressions are always type checked against a pattern, so also include the pattern in the solution application target and use that to compute the contextual type from the pattern type.
1 parent d8c9ef8 commit 52da2d6

File tree

3 files changed

+55
-31
lines changed

3 files changed

+55
-31
lines changed

lib/Sema/ConstraintSystem.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3996,6 +3996,32 @@ SolutionApplicationTarget::SolutionApplicationTarget(
39963996
expression.isDiscarded = isDiscarded;
39973997
}
39983998

3999+
SolutionApplicationTarget SolutionApplicationTarget::forInitialization(
4000+
Expr *initializer, Type patternType, Pattern *pattern) {
4001+
// Determine the contextual type for the initialization.
4002+
TypeLoc contextualType;
4003+
if (!isa<OptionalSomePattern>(pattern) &&
4004+
patternType && !patternType->isHole()) {
4005+
contextualType = TypeLoc::withoutLoc(patternType);
4006+
4007+
// Only provide a TypeLoc if it makes sense to allow diagnostics.
4008+
if (auto *typedPattern = dyn_cast<TypedPattern>(pattern)) {
4009+
const Pattern *inner = typedPattern->getSemanticsProvidingPattern();
4010+
if (isa<NamedPattern>(inner) || isa<AnyPattern>(inner)) {
4011+
contextualType = typedPattern->getTypeLoc();
4012+
if (!contextualType.getType())
4013+
contextualType.setType(patternType);
4014+
}
4015+
}
4016+
}
4017+
4018+
SolutionApplicationTarget target(
4019+
initializer, CTP_Initialization, contextualType,
4020+
/*isDiscarded=*/false);
4021+
target.expression.pattern = pattern;
4022+
return target;
4023+
}
4024+
39994025
bool SolutionApplicationTarget::contextualTypeIsOnlyAHint(
40004026
bool isOpaqueReturnType) const {
40014027
assert(kind == Kind::expression);

lib/Sema/ConstraintSystem.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,7 @@ class SolutionApplicationTarget {
11471147

11481148
union {
11491149
struct {
1150+
/// The expression being type-checked.
11501151
Expr *expression;
11511152

11521153
/// The purpose of the contextual type.
@@ -1155,6 +1156,10 @@ class SolutionApplicationTarget {
11551156
/// The type to which the expression should be converted.
11561157
TypeLoc convertType;
11571158

1159+
/// When initializing a pattern from the expression, this is the
1160+
/// pattern.
1161+
Pattern *pattern = nullptr;
1162+
11581163
/// Whether the expression result will be discarded at the end.
11591164
bool isDiscarded;
11601165
} expression;
@@ -1185,6 +1190,10 @@ class SolutionApplicationTarget {
11851190
function.body = body;
11861191
}
11871192

1193+
/// Form a target for the initialization of a pattern from an expression.
1194+
static SolutionApplicationTarget forInitialization(
1195+
Expr *initializer, Type patternType, Pattern *pattern);
1196+
11881197
Expr *getAsExpr() const {
11891198
switch (kind) {
11901199
case Kind::expression:
@@ -1236,6 +1245,13 @@ class SolutionApplicationTarget {
12361245
expression.convertType = type;
12371246
}
12381247

1248+
/// For a pattern initialization target, retrieve the pattern.
1249+
Pattern *getInitializationPattern() const {
1250+
assert(kind == Kind::expression);
1251+
assert(expression.contextualPurpose == CTP_Initialization);
1252+
return expression.pattern;
1253+
}
1254+
12391255
/// Whether the contextual type is only a hint, rather than a type
12401256
bool contextualTypeIsOnlyAHint(bool isOpaqueReturnType) const;
12411257

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,44 +2679,24 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
26792679

26802680
if (isa<OptionalSomePattern>(pattern)) {
26812681
flags |= TypeCheckExprFlags::ExpressionTypeMustBeOptional;
2682-
} else if (patternType && !patternType->isEqual(Context.TheUnresolvedType)) {
2683-
contextualType = TypeLoc::withoutLoc(patternType);
2684-
2685-
// If we already had an error, don't repeat the problem.
2686-
if (contextualType.getType()->hasError())
2687-
return true;
2688-
2689-
// Allow the initializer expression to establish the underlying type of an
2690-
// opaque type.
2691-
if (auto opaqueType = patternType->getAs<OpaqueTypeArchetypeType>()){
2692-
flags |= TypeCheckExprFlags::ConvertTypeIsOpaqueReturnType;
2693-
}
2694-
2695-
// Only provide a TypeLoc if it makes sense to allow diagnostics.
2696-
if (auto *typedPattern = dyn_cast<TypedPattern>(pattern)) {
2697-
const Pattern *inner = typedPattern->getSemanticsProvidingPattern();
2698-
if (isa<NamedPattern>(inner) || isa<AnyPattern>(inner)) {
2699-
contextualType = typedPattern->getTypeLoc();
2700-
if (!contextualType.getType())
2701-
contextualType.setType(patternType);
2702-
}
2703-
}
27042682
}
27052683

27062684
// Type-check the initializer.
2707-
auto resultTy = typeCheckExpression(initializer, DC, contextualType,
2708-
contextualPurpose, flags, &listener);
2685+
auto target = SolutionApplicationTarget::forInitialization(
2686+
initializer, patternType, pattern);
2687+
bool unresolvedTypeExprs = false;
2688+
auto resultTarget = typeCheckExpression(target, DC, unresolvedTypeExprs,
2689+
flags, &listener);
2690+
2691+
if (resultTarget) {
2692+
initializer = resultTarget->getAsExpr();
27092693

2710-
if (resultTy) {
27112694
TypeResolutionOptions options =
27122695
isa<EditorPlaceholderExpr>(initializer->getSemanticsProvidingExpr())
27132696
? TypeResolverContext::EditorPlaceholderExpr
27142697
: TypeResolverContext::InExpression;
27152698
options |= TypeResolutionFlags::OverrideType;
27162699

2717-
// FIXME: initTy should be the same as resultTy; now that typeCheckExpression()
2718-
// returns a Type and not bool, we should be able to simplify the listener
2719-
// implementation here.
27202700
auto initTy = listener.getPatternInitType(nullptr);
27212701
if (initTy->hasDependentMember())
27222702
return true;
@@ -2730,15 +2710,17 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
27302710
} else {
27312711
return true;
27322712
}
2713+
} else {
2714+
initializer = target.getAsExpr();
27332715
}
27342716

2735-
if (!resultTy && !initializer->getType())
2717+
if (!resultTarget && !initializer->getType())
27362718
initializer->setType(ErrorType::get(Context));
27372719

27382720
// If the type of the pattern is inferred, assign error types to the pattern
27392721
// and its variables, to prevent it from being referenced by the constraint
27402722
// system.
2741-
if (!resultTy &&
2723+
if (!resultTarget &&
27422724
(patternType->hasUnresolvedType() ||
27432725
patternType->hasUnboundGenericType())) {
27442726
pattern->setType(ErrorType::get(Context));
@@ -2754,7 +2736,7 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
27542736
});
27552737
}
27562738

2757-
return !resultTy;
2739+
return !resultTarget;
27582740
}
27592741

27602742
bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,

0 commit comments

Comments
 (0)