Skip to content

Commit 23a85d1

Browse files
authored
Merge pull request #74387 from hamishknight/pattern-resolution
[Sema] Requestify pattern resolution
2 parents 598e510 + 26e8245 commit 23a85d1

File tree

5 files changed

+52
-9
lines changed

5 files changed

+52
-9
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,6 +2527,33 @@ class EnumElementExprPatternRequest
25272527
bool isCached() const { return true; }
25282528
};
25292529

2530+
/// Perform top-down syntactic disambiguation of a pattern. Where ambiguous
2531+
/// expr/pattern productions occur (tuples, function calls, etc.), favor the
2532+
/// pattern interpretation if it forms a valid pattern; otherwise, leave it as
2533+
/// an expression. This does no type-checking except for the bare minimum to
2534+
/// disambiguate semantics-dependent pattern forms.
2535+
///
2536+
/// Currently cached to ensure the constraint system does not resolve the same
2537+
/// pattern multiple times along different solver paths. Once we move pattern
2538+
/// resolution into pre-checking, we could make this uncached.
2539+
class ResolvePatternRequest
2540+
: public SimpleRequest<ResolvePatternRequest,
2541+
Pattern *(Pattern *, DeclContext *, bool),
2542+
RequestFlags::Cached> {
2543+
public:
2544+
using SimpleRequest::SimpleRequest;
2545+
2546+
private:
2547+
friend SimpleRequest;
2548+
2549+
// Evaluation.
2550+
Pattern *evaluate(Evaluator &evaluator, Pattern *P, DeclContext *DC,
2551+
bool isStmtCondition) const;
2552+
public:
2553+
// Cached.
2554+
bool isCached() const { return true; }
2555+
};
2556+
25302557
class InterfaceTypeRequest :
25312558
public SimpleRequest<InterfaceTypeRequest,
25322559
Type (ValueDecl *),

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ SWIFT_REQUEST(TypeChecker, ExprPatternMatchRequest,
248248
SWIFT_REQUEST(TypeChecker, EnumElementExprPatternRequest,
249249
ExprPattern *(const EnumElementPattern *),
250250
Cached, NoLocationInfo)
251+
SWIFT_REQUEST(TypeChecker, ResolvePatternRequest,
252+
Pattern *(Pattern *, DeclContext *, bool),
253+
Cached, NoLocationInfo)
251254
SWIFT_REQUEST(TypeChecker, OpaqueReadOwnershipRequest,
252255
OpaqueReadOwnership(AbstractStorageDecl *), SeparatelyCached,
253256
NoLocationInfo)

lib/Sema/TypeCheckPattern.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -625,13 +625,9 @@ class ResolvePattern : public ASTVisitor<ResolvePattern,
625625

626626
} // end anonymous namespace
627627

628-
/// Perform top-down syntactic disambiguation of a pattern. Where ambiguous
629-
/// expr/pattern productions occur (tuples, function calls, etc.), favor the
630-
/// pattern interpretation if it forms a valid pattern; otherwise, leave it as
631-
/// an expression. This does no type-checking except for the bare minimum to
632-
/// disambiguate semantics-dependent pattern forms.
633-
Pattern *TypeChecker::resolvePattern(Pattern *P, DeclContext *DC,
634-
bool isStmtCondition) {
628+
Pattern *ResolvePatternRequest::evaluate(Evaluator &evaluator, Pattern *P,
629+
DeclContext *DC,
630+
bool isStmtCondition) const {
635631
P = ResolvePattern(DC).visit(P);
636632

637633
TypeChecker::diagnoseDuplicateBoundVars(P);
@@ -692,6 +688,13 @@ Pattern *TypeChecker::resolvePattern(Pattern *P, DeclContext *DC,
692688
return P;
693689
}
694690

691+
Pattern *TypeChecker::resolvePattern(Pattern *P, DeclContext *DC,
692+
bool isStmtCondition) {
693+
auto &eval = DC->getASTContext().evaluator;
694+
return evaluateOrDefault(eval, ResolvePatternRequest{P, DC, isStmtCondition},
695+
nullptr);
696+
}
697+
695698
static Type
696699
validateTypedPattern(TypedPattern *TP, DeclContext *dc,
697700
TypeResolutionOptions options,
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %batch-code-completion
2+
3+
func takeClosure(closure: () -> Bool) {}
4+
5+
func test(someLocal: Int) {
6+
takeClosure {
7+
if case .begin(#^COMPLETE^#)
8+
}
9+
}
10+
// COMPLETE: someLocal

validation-test/Sema/type_checker_crashers_fixed/rdar92327807.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ func test(result: MyEnum, optResult: MyEnum?) {
1818
}
1919

2020
let _ = {
21-
if let .co = result { // expected-error 2 {{pattern matching in a condition requires the 'case' keyword}}
21+
if let .co = result { // expected-error {{pattern matching in a condition requires the 'case' keyword}}
2222
// expected-error@-1 {{type 'MyEnum' has no member 'co'}}
2323
}
2424
}
2525

2626
let _ = {
27-
if let .co = optResult { // expected-error 2 {{pattern matching in a condition requires the 'case' keyword}}
27+
if let .co = optResult { // expected-error {{pattern matching in a condition requires the 'case' keyword}}
2828
// expected-error@-1 {{type 'MyEnum?' has no member 'co'}}
2929
}
3030
}

0 commit comments

Comments
 (0)