@@ -849,14 +849,48 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC,
849849 " typecheck-expr-pattern" , EP);
850850 PrettyStackTracePattern stackTrace (Context, " type-checking" , EP);
851851
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 ();
852887 // Create a 'let' binding to stand in for the RHS value.
853888 auto *matchVar =
854889 new (Context) VarDecl (/* IsStatic*/ false , VarDecl::Introducer::Let,
855890 EP->getLoc (), Context.Id_PatternMatchVar , DC);
856- matchVar->setInterfaceType (rhsType ->mapTypeOutOfContext ());
891+ matchVar->setInterfaceType (enumType ->mapTypeOutOfContext ());
857892
858893 matchVar->setImplicit ();
859- EP->setMatchVar (matchVar);
860894
861895 // Find '~=' operators for the match.
862896 auto matchLookup =
@@ -866,19 +900,19 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC,
866900 auto &diags = DC->getASTContext ().Diags ;
867901 if (!matchLookup) {
868902 diags.diagnose (EP->getLoc (), diag::no_match_operator);
869- return true ;
903+ return None ;
870904 }
871-
905+
872906 SmallVector<ValueDecl*, 4 > choices;
873907 for (auto &result : matchLookup) {
874908 choices.push_back (result.getValueDecl ());
875909 }
876-
910+
877911 if (choices.empty ()) {
878912 diags.diagnose (EP->getLoc (), diag::no_match_operator);
879- return true ;
913+ return None ;
880914 }
881-
915+
882916 // Build the 'expr ~= var' expression.
883917 // FIXME: Compound name locations.
884918 auto *matchOp =
@@ -890,24 +924,10 @@ bool TypeChecker::typeCheckExprPattern(ExprPattern *EP, DeclContext *DC,
890924 auto *matchVarRef = new (Context) DeclRefExpr (matchVar,
891925 DeclNameLoc (EP->getEndLoc ()),
892926 /* Implicit=*/ true );
893- Expr *matchCall = BinaryExpr::create (Context, EP->getSubExpr (), matchOp,
927+ auto *matchCall = BinaryExpr::create (Context, EP->getSubExpr (), matchOp,
894928 matchVarRef, /* implicit*/ true );
895929
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);
911931}
912932
913933static Type replaceArchetypesWithTypeVariables (ConstraintSystem &cs,
0 commit comments