diff --git a/include/swift/AST/Pattern.h b/include/swift/AST/Pattern.h index 250f6cbb91368..f91a95db954e9 100644 --- a/include/swift/AST/Pattern.h +++ b/include/swift/AST/Pattern.h @@ -639,7 +639,6 @@ class OptionalSomePattern : public Pattern { } }; - /// A pattern which matches a value obtained by evaluating an expression. /// The match will be tested using user-defined '~=' operator function lookup; /// the match succeeds if 'patternValue ~= matchedValue' produces a true value. @@ -649,24 +648,24 @@ class ExprPattern : public Pattern { /// An expression constructed during type-checking that produces a call to the /// '~=' operator comparing the match expression on the left to the matched /// value on the right. - Expr *MatchExpr; + Expr *MatchExpr = nullptr; /// An implicit variable used to represent the RHS value of the match. - VarDecl *MatchVar; + VarDecl *MatchVar = nullptr; + + ExprPattern(Expr *E, bool isResolved) + : Pattern(PatternKind::Expr), SubExprAndIsResolved(E, isResolved) {} public: - /// Construct an ExprPattern. - ExprPattern(Expr *e, bool isResolved, Expr *matchExpr, VarDecl *matchVar); - - /// Construct an unresolved ExprPattern. - ExprPattern(Expr *e) - : ExprPattern(e, false, nullptr, nullptr) - {} - - /// Construct a resolved ExprPattern. - ExprPattern(Expr *e, Expr *matchExpr, VarDecl *matchVar) - : ExprPattern(e, true, matchExpr, matchVar) - {} + /// Create a new parsed unresolved ExprPattern. + static ExprPattern *createParsed(ASTContext &ctx, Expr *E); + + /// Create a new resolved ExprPattern. This should be used in cases + /// where a user-written expression should be treated as an ExprPattern. + static ExprPattern *createResolved(ASTContext &ctx, Expr *E); + + /// Create a new implicit resolved ExprPattern. + static ExprPattern *createImplicit(ASTContext &ctx, Expr *E); Expr *getSubExpr() const { return SubExprAndIsResolved.getPointer(); } void setSubExpr(Expr *e) { SubExprAndIsResolved.setPointer(e); } diff --git a/include/swift/Sema/ConstraintSystem.h b/include/swift/Sema/ConstraintSystem.h index 8c00e1b68ca84..88e6a3531122e 100644 --- a/include/swift/Sema/ConstraintSystem.h +++ b/include/swift/Sema/ConstraintSystem.h @@ -2347,13 +2347,18 @@ class SolutionApplicationTarget { expression.convertType = type; } + /// Whether this target is for an initialization expression and pattern. + bool isForInitialization() const { + return kind == Kind::expression && + expression.contextualPurpose == CTP_Initialization; + } + /// For a pattern initialization target, retrieve the pattern. Pattern *getInitializationPattern() const { if (kind == Kind::uninitializedVar) return uninitializedVar.declaration.get(); - assert(kind == Kind::expression); - assert(expression.contextualPurpose == CTP_Initialization); + assert(isForInitialization()); return expression.pattern; } @@ -2378,16 +2383,14 @@ class SolutionApplicationTarget { /// Whether this is an initialization for an Optional.Some pattern. bool isOptionalSomePatternInit() const { - return kind == Kind::expression && - expression.contextualPurpose == CTP_Initialization && - dyn_cast_or_null(expression.pattern) && - !expression.pattern->isImplicit(); + return isForInitialization() && + dyn_cast_or_null(expression.pattern) && + !expression.pattern->isImplicit(); } /// Check whether this is an initialization for `async let` pattern. bool isAsyncLetInitializer() const { - if (!(kind == Kind::expression && - expression.contextualPurpose == CTP_Initialization)) + if (!isForInitialization()) return false; if (auto *PBD = getInitializationPatternBindingDecl()) @@ -2411,8 +2414,7 @@ class SolutionApplicationTarget { /// first \c wrappedValue argument of an apply expression so the initializer /// expression can be turned into a property wrapper generator function. bool shouldInjectWrappedValuePlaceholder(ApplyExpr *apply) const { - if (kind != Kind::expression || - expression.contextualPurpose != CTP_Initialization) + if (!isForInitialization()) return false; auto *wrappedVar = expression.propertyWrapper.wrappedVar; @@ -2439,20 +2441,17 @@ class SolutionApplicationTarget { /// Retrieve the wrapped variable when initializing a pattern with a /// property wrapper. VarDecl *getInitializationWrappedVar() const { - assert(kind == Kind::expression); - assert(expression.contextualPurpose == CTP_Initialization); + assert(isForInitialization()); return expression.propertyWrapper.wrappedVar; } PatternBindingDecl *getInitializationPatternBindingDecl() const { - assert(kind == Kind::expression); - assert(expression.contextualPurpose == CTP_Initialization); + assert(isForInitialization()); return expression.initialization.patternBinding; } unsigned getInitializationPatternBindingIndex() const { - assert(kind == Kind::expression); - assert(expression.contextualPurpose == CTP_Initialization); + assert(isForInitialization()); return expression.initialization.patternBindingIndex; } diff --git a/lib/AST/Pattern.cpp b/lib/AST/Pattern.cpp index 3e203972e1a86..c5e4fd87462cb 100644 --- a/lib/AST/Pattern.cpp +++ b/lib/AST/Pattern.cpp @@ -501,12 +501,18 @@ void IsPattern::setCastType(Type type) { TypeRepr *IsPattern::getCastTypeRepr() const { return CastType->getTypeRepr(); } -/// Construct an ExprPattern. -ExprPattern::ExprPattern(Expr *e, bool isResolved, Expr *matchExpr, - VarDecl *matchVar) - : Pattern(PatternKind::Expr), SubExprAndIsResolved(e, isResolved), - MatchExpr(matchExpr), MatchVar(matchVar) { - assert(!matchExpr || e->isImplicit() == matchExpr->isImplicit()); +ExprPattern *ExprPattern::createParsed(ASTContext &ctx, Expr *E) { + return new (ctx) ExprPattern(E, /*isResolved*/ false); +} + +ExprPattern *ExprPattern::createResolved(ASTContext &ctx, Expr *E) { + return new (ctx) ExprPattern(E, /*isResolved*/ true); +} + +ExprPattern *ExprPattern::createImplicit(ASTContext &ctx, Expr *E) { + auto *EP = ExprPattern::createResolved(ctx, E); + EP->setImplicit(); + return EP; } SourceLoc EnumElementPattern::getStartLoc() const { diff --git a/lib/Parse/ParsePattern.cpp b/lib/Parse/ParsePattern.cpp index c8a89f32a18c3..0068a0d4030e8 100644 --- a/lib/Parse/ParsePattern.cpp +++ b/lib/Parse/ParsePattern.cpp @@ -1314,8 +1314,9 @@ ParserResult Parser::parseMatchingPattern(bool isExprBasic) { // UnresolvedPatternExpr. Transform this now to simplify later code. if (auto *UPE = dyn_cast(subExpr.get())) return makeParserResult(status, UPE->getSubPattern()); - - return makeParserResult(status, new (Context) ExprPattern(subExpr.get())); + + auto *EP = ExprPattern::createParsed(Context, subExpr.get()); + return makeParserResult(status, EP); } ParserResult Parser::parseMatchingPatternAsLetOrVar(bool isLet, diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 3f47f82c3a115..c121ab1bca7dd 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1061,7 +1061,7 @@ static void parseGuardedPattern(Parser &P, GuardedPattern &result, // Do some special-case code completion for the start of the pattern. if (P.Tok.is(tok::code_complete)) { auto CCE = new (P.Context) CodeCompletionExpr(P.Tok.getLoc()); - result.ThePattern = new (P.Context) ExprPattern(CCE); + result.ThePattern = ExprPattern::createParsed(P.Context, CCE); if (P.IDECallbacks) { switch (parsingContext) { case GuardedPatternContext::Case: diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 60db3835cbfc0..2e13deb5fdb16 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -4577,7 +4577,7 @@ bool ConstraintSystem::generateConstraints( } // For an initialization target, generate constraints for the pattern. - if (target.getExprContextualTypePurpose() == CTP_Initialization && + if (target.isForInitialization() && generateInitPatternConstraints(*this, target, expr)) { return true; } diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index a123d239a0dd5..f6991ed9f2402 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -9847,8 +9847,8 @@ static bool inferEnumMemberThroughTildeEqualsOperator( // Slots for expression and variable are going to be filled via // synthesizing ~= operator application. - auto *EP = new (ctx) ExprPattern(pattern->getUnresolvedOriginalExpr(), - /*matchExpr=*/nullptr, /*matchVar=*/nullptr); + auto *EP = + ExprPattern::createResolved(ctx, pattern->getUnresolvedOriginalExpr()); auto tildeEqualsApplication = TypeChecker::synthesizeTildeEqualsOperatorApplication(EP, DC, enumTy); diff --git a/lib/Sema/DerivedConformanceCodingKey.cpp b/lib/Sema/DerivedConformanceCodingKey.cpp index 73c71ed106977..fc6b473bc229e 100644 --- a/lib/Sema/DerivedConformanceCodingKey.cpp +++ b/lib/Sema/DerivedConformanceCodingKey.cpp @@ -277,9 +277,7 @@ deriveBodyCodingKey_init_stringValue(AbstractFunctionDecl *initDecl, void *) { for (auto *elt : elements) { auto *litExpr = new (C) StringLiteralExpr(elt->getNameStr(), SourceRange(), /*Implicit=*/true); - auto *litPat = new (C) ExprPattern(litExpr, /*IsResolved=*/true, nullptr, - nullptr); - litPat->setImplicit(); + auto *litPat = ExprPattern::createImplicit(C, litExpr); auto labelItem = CaseLabelItem(litPat); diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp index a04c5a4806f39..3f669280b0b65 100644 --- a/lib/Sema/DerivedConformanceRawRepresentable.cpp +++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp @@ -323,9 +323,7 @@ deriveBodyRawRepresentable_init(AbstractFunctionDecl *initDecl, void *) { stringExprs.push_back(litExpr); litExpr = IntegerLiteralExpr::createFromUnsigned(C, Idx, SourceLoc()); } - auto litPat = new (C) ExprPattern(litExpr, /*isResolved*/ true, - nullptr, nullptr); - litPat->setImplicit(); + auto *litPat = ExprPattern::createImplicit(C, litExpr); /// Statements in the body of this case. SmallVector stmts; diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index dbce07586e44c..5bedd6dfff155 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -225,39 +225,7 @@ struct ExprToDeclRefTypeRepr : public ASTVisitor { }; } // end anonymous namespace - -namespace { - class UnresolvedPatternFinder : public ASTWalker { - bool &HadUnresolvedPattern; - public: - - UnresolvedPatternFinder(bool &HadUnresolvedPattern) - : HadUnresolvedPattern(HadUnresolvedPattern) {} - - MacroWalking getMacroWalkingBehavior() const override { - return MacroWalking::Arguments; - } - - PreWalkResult walkToExprPre(Expr *E) override { - // If we find an UnresolvedPatternExpr, return true. - if (isa(E)) { - HadUnresolvedPattern = true; - return Action::SkipChildren(E); - } - - return Action::Continue(E); - } - - static bool hasAny(Expr *E) { - bool HasUnresolvedPattern = false; - E->walk(UnresolvedPatternFinder(HasUnresolvedPattern)); - return HasUnresolvedPattern; - } - }; -} // end anonymous namespace - namespace { - class ResolvePattern : public ASTVisitorgetUnresolvedOriginalExpr(), - nullptr, nullptr); + P = ExprPattern::createResolved(Context, + EEP->getUnresolvedOriginalExpr()); return coercePatternToType( pattern.forSubPattern(P, /*retainTopLevel=*/true), type, options);