Skip to content

Commit 9c8351b

Browse files
committed
[Type checker] Make typeCheckPattern() functional.
Make TypeChecker::typeCheckPattern() return the computed type, rather than returning an "error" flag. More importantly, make it functional, so that it doesn't set the type it computes on the pattern. Use UnresolvedType as a placeholder for types that need to be inferred, rather than a null type. This allows us to produce structural types involving types that need to be inferred. Note that with this change as-is, we get a number of duplicated diagnostics, because typeCheckPattern() will be called multiple times for the same pattern and will emit some diagnostics each time. This will be addressed in a subsequent commit.
1 parent 2a13b1d commit 9c8351b

File tree

6 files changed

+102
-82
lines changed

6 files changed

+102
-82
lines changed

lib/Sema/CSGen.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,10 +2158,11 @@ namespace {
21582158
}
21592159

21602160
case PatternKind::Typed: {
2161-
auto typedPattern = cast<TypedPattern>(pattern);
21622161
// FIXME: Need a better locator for a pattern as a base.
2163-
Type openedType = CS.openUnboundGenericType(typedPattern->getType(),
2164-
locator);
2162+
TypeResolutionOptions options(TypeResolverContext::InExpression);
2163+
options |= TypeResolutionFlags::AllowUnboundGenerics;
2164+
Type type = TypeChecker::typeCheckPattern(pattern, CurDC, options);
2165+
Type openedType = CS.openUnboundGenericType(type, locator);
21652166

21662167
// For a typed pattern, simply return the opened type of the pattern.
21672168
// FIXME: Error recovery if the type is an error type?

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,7 +2566,8 @@ TypeChecker::getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS,
25662566
}
25672567

25682568
bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
2569-
DeclContext *DC) {
2569+
DeclContext *DC,
2570+
Type patternType) {
25702571

25712572
/// Type checking listener for pattern binding initializers.
25722573
class BindingListener : public ExprTypeCheckListener {
@@ -2763,28 +2764,31 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
27632764
// if there's an error we can use that information to inform diagnostics.
27642765
contextualPurpose = CTP_Initialization;
27652766

2766-
if (pattern->hasType()) {
2767-
contextualType = TypeLoc::withoutLoc(pattern->getType());
2767+
if (isa<OptionalSomePattern>(pattern)) {
2768+
flags |= TypeCheckExprFlags::ExpressionTypeMustBeOptional;
2769+
} else if (patternType && !patternType->isEqual(Context.TheUnresolvedType)) {
2770+
contextualType = TypeLoc::withoutLoc(patternType);
27682771

27692772
// If we already had an error, don't repeat the problem.
27702773
if (contextualType.getType()->hasError())
27712774
return true;
27722775

27732776
// Allow the initializer expression to establish the underlying type of an
27742777
// opaque type.
2775-
if (auto opaqueType = pattern->getType()->getAs<OpaqueTypeArchetypeType>()){
2778+
if (auto opaqueType = patternType->getAs<OpaqueTypeArchetypeType>()){
27762779
flags |= TypeCheckExprFlags::ConvertTypeIsOpaqueReturnType;
27772780
flags -= TypeCheckExprFlags::ConvertTypeIsOnlyAHint;
27782781
}
27792782

27802783
// Only provide a TypeLoc if it makes sense to allow diagnostics.
27812784
if (auto *typedPattern = dyn_cast<TypedPattern>(pattern)) {
27822785
const Pattern *inner = typedPattern->getSemanticsProvidingPattern();
2783-
if (isa<NamedPattern>(inner) || isa<AnyPattern>(inner))
2786+
if (isa<NamedPattern>(inner) || isa<AnyPattern>(inner)) {
27842787
contextualType = typedPattern->getTypeLoc();
2788+
if (!contextualType.getType())
2789+
contextualType.setType(patternType);
2790+
}
27852791
}
2786-
} else if (isa<OptionalSomePattern>(pattern)) {
2787-
flags |= TypeCheckExprFlags::ExpressionTypeMustBeOptional;
27882792
}
27892793

27902794
// Type-check the initializer.
@@ -2797,6 +2801,8 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
27972801
? TypeResolverContext::EditorPlaceholderExpr
27982802
: TypeResolverContext::InExpression;
27992803
options |= TypeResolutionFlags::OverrideType;
2804+
options |= TypeResolutionFlags::AllowUnspecifiedTypes;
2805+
options |= TypeResolutionFlags::AllowUnboundGenerics;
28002806

28012807
// FIXME: initTy should be the same as resultTy; now that typeCheckExpression()
28022808
// returns a Type and not bool, we should be able to simplify the listener
@@ -2819,7 +2825,8 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
28192825
// and its variables, to prevent it from being referenced by the constraint
28202826
// system.
28212827
if (!resultTy &&
2822-
(!pattern->hasType() || pattern->getType()->hasUnboundGenericType())) {
2828+
(patternType->hasUnresolvedType() ||
2829+
patternType->hasUnboundGenericType())) {
28232830
pattern->setType(ErrorType::get(Context));
28242831
pattern->forEachVariable([&](VarDecl *var) {
28252832
// Don't change the type of a variable that we've been able to
@@ -2837,7 +2844,8 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
28372844
}
28382845

28392846
bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
2840-
unsigned patternNumber) {
2847+
unsigned patternNumber,
2848+
Type patternType) {
28412849
Pattern *pattern = PBD->getPattern(patternNumber);
28422850
Expr *init = PBD->getInit(patternNumber);
28432851

@@ -2851,7 +2859,24 @@ bool TypeChecker::typeCheckPatternBinding(PatternBindingDecl *PBD,
28512859
DC = initContext;
28522860
}
28532861

2854-
bool hadError = TypeChecker::typeCheckBinding(pattern, init, DC);
2862+
// If we weren't given a pattern type, compute one now.
2863+
if (!patternType) {
2864+
if (pattern->hasType())
2865+
patternType = pattern->getType();
2866+
else {
2867+
TypeResolutionOptions options(TypeResolverContext::InExpression);
2868+
options |= TypeResolutionFlags::AllowUnspecifiedTypes;
2869+
options |= TypeResolutionFlags::AllowUnboundGenerics;
2870+
patternType = typeCheckPattern(pattern, DC, options);
2871+
}
2872+
2873+
if (patternType->hasError()) {
2874+
PBD->setInvalid();
2875+
return true;
2876+
}
2877+
}
2878+
2879+
bool hadError = TypeChecker::typeCheckBinding(pattern, init, DC, patternType);
28552880
if (!init) {
28562881
PBD->setInvalid();
28572882
return true;
@@ -2973,7 +2998,9 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
29732998
TypeResolutionOptions options(TypeResolverContext::InExpression);
29742999
options |= TypeResolutionFlags::AllowUnspecifiedTypes;
29753000
options |= TypeResolutionFlags::AllowUnboundGenerics;
2976-
if (TypeChecker::typeCheckPattern(Stmt->getPattern(), DC, options)) {
3001+
Type patternType = TypeChecker::typeCheckPattern(
3002+
Stmt->getPattern(), DC, options);
3003+
if (patternType->hasError()) {
29773004
// FIXME: Handle errors better.
29783005
Stmt->getPattern()->setType(ErrorType::get(ctx));
29793006
return true;
@@ -3040,6 +3067,8 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
30403067
Pattern *pattern = Stmt->getPattern();
30413068
TypeResolutionOptions options(TypeResolverContext::ForEachStmt);
30423069
options |= TypeResolutionFlags::OverrideType;
3070+
options |= TypeResolutionFlags::AllowUnboundGenerics;
3071+
options |= TypeResolutionFlags::AllowUnspecifiedTypes;
30433072
if (TypeChecker::coercePatternToType(pattern,
30443073
TypeResolution::forContextual(DC),
30453074
InitType, options)) {
@@ -3195,15 +3224,16 @@ bool TypeChecker::typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc,
31953224
TypeResolutionOptions options(TypeResolverContext::InExpression);
31963225
options |= TypeResolutionFlags::AllowUnspecifiedTypes;
31973226
options |= TypeResolutionFlags::AllowUnboundGenerics;
3198-
if (TypeChecker::typeCheckPattern(pattern, dc, options)) {
3227+
Type patternType = TypeChecker::typeCheckPattern(pattern, dc, options);
3228+
if (patternType->hasError()) {
31993229
typeCheckPatternFailed();
32003230
continue;
32013231
}
32023232

32033233
// If the pattern didn't get a type, it's because we ran into some
32043234
// unknown types along the way. We'll need to check the initializer.
32053235
auto init = elt.getInitializer();
3206-
hadError |= TypeChecker::typeCheckBinding(pattern, init, dc);
3236+
hadError |= TypeChecker::typeCheckBinding(pattern, init, dc, patternType);
32073237
elt.setPattern(pattern);
32083238
elt.setInitializer(init);
32093239
hadAnyFalsable |= pattern->isRefutablePattern();

lib/Sema/TypeCheckPattern.cpp

Lines changed: 30 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -664,12 +664,9 @@ Pattern *TypeChecker::resolvePattern(Pattern *P, DeclContext *DC,
664664
return P;
665665
}
666666

667-
static bool validateTypedPattern(TypeResolution resolution,
667+
static Type validateTypedPattern(TypeResolution resolution,
668668
TypedPattern *TP,
669669
TypeResolutionOptions options) {
670-
if (TP->hasType())
671-
return TP->getType()->hasError();
672-
673670
TypeLoc TL = TP->getTypeLoc();
674671

675672
bool hadError;
@@ -678,7 +675,7 @@ static bool validateTypedPattern(TypeResolution resolution,
678675
// variable binding, then we can bind the opaque return type from the
679676
// property definition.
680677
auto &Context = resolution.getASTContext();
681-
if (auto opaqueRepr = dyn_cast<OpaqueReturnTypeRepr>(TL.getTypeRepr())) {
678+
if (auto opaqueRepr = dyn_cast_or_null<OpaqueReturnTypeRepr>(TL.getTypeRepr())) {
682679
auto named = dyn_cast<NamedPattern>(
683680
TP->getSubPattern()->getSemanticsProvidingPattern());
684681
if (named) {
@@ -699,18 +696,14 @@ static bool validateTypedPattern(TypeResolution resolution,
699696
}
700697

701698
if (hadError) {
702-
TP->setType(ErrorType::get(Context));
703-
return hadError;
699+
return ErrorType::get(Context);
704700
}
705701

706-
TP->setType(TL.getType());
707-
708702
assert(!dyn_cast_or_null<SpecifierTypeRepr>(TL.getTypeRepr()));
709-
710-
return hadError;
703+
return TL.getType();
711704
}
712705

713-
bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc,
706+
Type TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc,
714707
TypeResolutionOptions options) {
715708
auto &Context = dc->getASTContext();
716709
switch (P->getKind()) {
@@ -723,17 +716,14 @@ bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc,
723716
SP = PP->getSubPattern();
724717
else
725718
SP = cast<VarPattern>(P)->getSubPattern();
726-
if (TypeChecker::typeCheckPattern(SP, dc, options)) {
727-
P->setType(ErrorType::get(Context));
728-
return true;
729-
}
730-
if (SP->hasType()) {
731-
auto type = SP->getType();
732-
if (P->getKind() == PatternKind::Paren)
733-
type = ParenType::get(Context, type);
734-
P->setType(type);
735-
}
736-
return false;
719+
Type subType = TypeChecker::typeCheckPattern(SP, dc, options);
720+
if (subType->hasError())
721+
return ErrorType::get(Context);
722+
723+
auto type = subType;
724+
if (P->getKind() == PatternKind::Paren)
725+
type = ParenType::get(Context, type);
726+
return type;
737727
}
738728

739729
// If we see an explicit type annotation, coerce the sub-pattern to
@@ -751,16 +741,15 @@ bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc,
751741
// If we're type checking this pattern in a context that can provide type
752742
// information, then the lack of type information is not an error.
753743
if (options & TypeResolutionFlags::AllowUnspecifiedTypes)
754-
return false;
744+
return Context.TheUnresolvedType;
755745

756746
Context.Diags.diagnose(P->getLoc(), diag::cannot_infer_type_for_pattern);
757-
P->setType(ErrorType::get(Context));
758747
if (auto named = dyn_cast<NamedPattern>(P)) {
759748
if (auto var = named->getDecl()) {
760749
var->setInvalid();
761750
}
762751
}
763-
return true;
752+
return ErrorType::get(Context);
764753

765754
// A tuple pattern propagates its tuple-ness out.
766755
case PatternKind::Tuple: {
@@ -769,31 +758,21 @@ bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc,
769758
SmallVector<TupleTypeElt, 8> typeElts;
770759

771760
const auto elementOptions = options.withoutContext();
772-
bool missingType = false;
773761
for (unsigned i = 0, e = tuplePat->getNumElements(); i != e; ++i) {
774762
TuplePatternElt &elt = tuplePat->getElement(i);
775763
Pattern *pattern = elt.getPattern();
776-
if (TypeChecker::typeCheckPattern(pattern, dc, elementOptions)) {
764+
Type subType = TypeChecker::typeCheckPattern(pattern, dc, elementOptions);
765+
if (subType->hasError())
777766
hadError = true;
778-
continue;
779-
}
780-
if (!pattern->hasType()) {
781-
missingType = true;
782-
continue;
783-
}
784767

785-
typeElts.push_back(TupleTypeElt(pattern->getType(), elt.getLabel()));
768+
typeElts.push_back(TupleTypeElt(subType, elt.getLabel()));
786769
}
787770

788771
if (hadError) {
789-
P->setType(ErrorType::get(Context));
790-
return true;
772+
return ErrorType::get(Context);
791773
}
792-
if (!missingType && !(options &
793-
TypeResolutionFlags::AllowUnspecifiedTypes)) {
794-
P->setType(TupleType::get(typeElts, Context));
795-
}
796-
return false;
774+
775+
return TupleType::get(typeElts, Context);
797776
}
798777

799778
//--- Refutable patterns.
@@ -809,11 +788,10 @@ bool TypeChecker::typeCheckPattern(Pattern *P, DeclContext *dc,
809788
if (!(options & TypeResolutionFlags::AllowUnspecifiedTypes)) {
810789
Context.Diags.diagnose(P->getLoc(),
811790
diag::refutable_pattern_requires_initializer);
812-
P->setType(ErrorType::get(Context));
813-
return true;
791+
return ErrorType::get(Context);
814792
}
815793

816-
return false;
794+
return Context.TheUnresolvedType;
817795
}
818796
llvm_unreachable("bad pattern kind!");
819797
}
@@ -923,9 +901,10 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution,
923901
// that type.
924902
case PatternKind::Typed: {
925903
TypedPattern *TP = cast<TypedPattern>(P);
926-
bool hadError = validateTypedPattern(resolution, TP, options);
927-
if (!hadError) {
928-
if (!type->isEqual(TP->getType()) && !type->hasError()) {
904+
Type patternType = validateTypedPattern(resolution, TP, options);
905+
bool hadError = false;
906+
if (!patternType->hasError()) {
907+
if (!type->isEqual(patternType) && !type->hasError()) {
929908
if (options & TypeResolutionFlags::OverrideType) {
930909
TP->setType(type);
931910
} else {
@@ -934,10 +913,12 @@ bool TypeChecker::coercePatternToType(Pattern *&P, TypeResolution resolution,
934913
hadError = true;
935914
}
936915
}
916+
} else {
917+
hadError = true;
937918
}
938919

939920
Pattern *sub = TP->getSubPattern();
940-
hadError |= coercePatternToType(sub, resolution, TP->getType(),
921+
hadError |= coercePatternToType(sub, resolution, type,
941922
subOptions | TypeResolutionFlags::FromNonInferredPattern);
942923
if (!hadError) {
943924
TP->setSubPattern(sub);

lib/Sema/TypeCheckStorage.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,9 @@ PatternBindingEntryRequest::evaluate(Evaluator &eval,
214214
options |= TypeResolutionFlags::AllowUnboundGenerics;
215215
}
216216

217-
if (TypeChecker::typeCheckPattern(pattern, binding->getDeclContext(), options)) {
217+
Type patternType = TypeChecker::typeCheckPattern(
218+
pattern, binding->getDeclContext(), options);
219+
if (patternType->hasError()) {
218220
swift::setBoundVarsTypeError(pattern, Context);
219221
binding->setInvalid();
220222
pattern->setType(ErrorType::get(Context));
@@ -225,20 +227,20 @@ PatternBindingEntryRequest::evaluate(Evaluator &eval,
225227
// default-initializable. If so, do it.
226228
if (!pbe.isInitialized() &&
227229
binding->isDefaultInitializable(entryNumber) &&
228-
pattern->hasStorage() &&
229-
!pattern->getType()->hasError()) {
230-
auto type = pattern->getType();
231-
if (auto defaultInit = TypeChecker::buildDefaultInitializer(type)) {
230+
pattern->hasStorage()) {
231+
if (auto defaultInit = TypeChecker::buildDefaultInitializer(patternType)) {
232232
// If we got a default initializer, install it and re-type-check it
233233
// to make sure it is properly coerced to the pattern type.
234234
binding->setInit(entryNumber, defaultInit);
235235
}
236236
}
237237

238-
// If the pattern didn't get a type or if it contains an unbound generic type,
239-
// we'll need to check the initializer.
240-
if (!pattern->hasType() || pattern->getType()->hasUnboundGenericType()) {
241-
if (TypeChecker::typeCheckPatternBinding(binding, entryNumber)) {
238+
// If the pattern contains some form of unresolved type, we'll need to
239+
// check the initializer.
240+
if (patternType->hasUnresolvedType() ||
241+
patternType->hasUnboundGenericType()) {
242+
if (TypeChecker::typeCheckPatternBinding(binding, entryNumber,
243+
patternType)) {
242244
binding->setInvalid();
243245
return &pbe;
244246
}
@@ -255,7 +257,7 @@ PatternBindingEntryRequest::evaluate(Evaluator &eval,
255257
// Coerce the pattern to the computed type.
256258
auto resolution = TypeResolution::forContextual(binding->getDeclContext());
257259
if (TypeChecker::coercePatternToType(pattern, resolution,
258-
pattern->getType(), options)) {
260+
patternType, options)) {
259261
binding->setInvalid();
260262
pattern->setType(ErrorType::get(Context));
261263
return &pbe;

0 commit comments

Comments
 (0)