@@ -849,14 +849,48 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC,
849
849
" typecheck-expr-pattern" , EP);
850
850
PrettyStackTracePattern stackTrace (Context, " type-checking" , EP);
851
851
852
+ auto tildeEqualsApplication =
853
+ synthesizeTildeEqualsOperatorApplication (EP, DC, rhsType);
854
+
855
+ if (!tildeEqualsApplication)
856
+ return true ;
857
+
858
+ VarDecl *matchVar;
859
+ Expr *matchCall;
860
+
861
+ std::tie (matchVar, matchCall) = *tildeEqualsApplication;
862
+
863
+ // Result of `~=` should always be a boolean.
864
+ auto contextualTy = Context.getBoolDecl ()->getDeclaredInterfaceType ();
865
+ auto target = SolutionApplicationTarget::forExprPattern (matchCall, DC, EP,
866
+ contextualTy);
867
+
868
+ // Check the expression as a condition.
869
+ auto result = typeCheckExpression (target);
870
+ if (!result)
871
+ return true ;
872
+
873
+ // Save the synthesized $match variable in the pattern.
874
+ EP->setMatchVar (matchVar);
875
+ // Save the type-checked expression in the pattern.
876
+ EP->setMatchExpr (result->getAsExpr ());
877
+ // Set the type on the pattern.
878
+ EP->setType (rhsType);
879
+ return false ;
880
+ }
881
+
882
+ Optional<std::pair<VarDecl *, BinaryExpr *>>
883
+ TypeChecker::synthesizeTildeEqualsOperatorApplication (ExprPattern *EP,
884
+ DeclContext *DC,
885
+ Type enumType) {
886
+ auto &Context = DC->getASTContext ();
852
887
// Create a 'let' binding to stand in for the RHS value.
853
888
auto *matchVar =
854
889
new (Context) VarDecl (/* IsStatic*/ false , VarDecl::Introducer::Let,
855
890
EP->getLoc (), Context.Id_PatternMatchVar , DC);
856
- matchVar->setInterfaceType (rhsType ->mapTypeOutOfContext ());
891
+ matchVar->setInterfaceType (enumType ->mapTypeOutOfContext ());
857
892
858
893
matchVar->setImplicit ();
859
- EP->setMatchVar (matchVar);
860
894
861
895
// Find '~=' operators for the match.
862
896
auto matchLookup =
@@ -866,19 +900,19 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC,
866
900
auto &diags = DC->getASTContext ().Diags ;
867
901
if (!matchLookup) {
868
902
diags.diagnose (EP->getLoc (), diag::no_match_operator);
869
- return true ;
903
+ return None ;
870
904
}
871
-
905
+
872
906
SmallVector<ValueDecl*, 4 > choices;
873
907
for (auto &result : matchLookup) {
874
908
choices.push_back (result.getValueDecl ());
875
909
}
876
-
910
+
877
911
if (choices.empty ()) {
878
912
diags.diagnose (EP->getLoc (), diag::no_match_operator);
879
- return true ;
913
+ return None ;
880
914
}
881
-
915
+
882
916
// Build the 'expr ~= var' expression.
883
917
// FIXME: Compound name locations.
884
918
auto *matchOp =
@@ -890,24 +924,10 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC,
890
924
auto *matchVarRef = new (Context) DeclRefExpr (matchVar,
891
925
DeclNameLoc (EP->getEndLoc ()),
892
926
/* Implicit=*/ true );
893
- Expr *matchCall = BinaryExpr::create (Context, EP->getSubExpr (), matchOp,
927
+ auto *matchCall = BinaryExpr::create (Context, EP->getSubExpr (), matchOp,
894
928
matchVarRef, /* implicit*/ true );
895
929
896
- // Result of `~=` should always be a boolean.
897
- auto contextualTy = Context.getBoolDecl ()->getDeclaredInterfaceType ();
898
- auto target = SolutionApplicationTarget::forExprPattern (matchCall, DC, EP,
899
- contextualTy);
900
-
901
- // Check the expression as a condition.
902
- auto result = typeCheckExpression (target);
903
- if (!result)
904
- return true ;
905
-
906
- // Save the type-checked expression in the pattern.
907
- EP->setMatchExpr (result->getAsExpr ());
908
- // Set the type on the pattern.
909
- EP->setType (rhsType);
910
- return false ;
930
+ return std::make_pair (matchVar, matchCall);
911
931
}
912
932
913
933
static Type replaceArchetypesWithTypeVariables (ConstraintSystem &cs,
0 commit comments