From 05363cd55aa49edae62e352cc2a32efcc82eb68b Mon Sep 17 00:00:00 2001 From: Richard Wei Date: Mon, 6 Dec 2021 19:10:07 -0800 Subject: [PATCH] Regex literal runtime plumbing. - Frontend: Implicitly import `_StringProcessing` when frontend flag `-enable-experimental-string-processing` is set. - Type checker: Set a regex literal expression's type as `_StringProcessing.Regex<(Substring, DynamicCaptures)>`. `(Substring, DynamicCaptures)` is a temporary `Match` type that will help get us to an end-to-end working system. This will be replaced by actual type inference based a regex's pattern in a follow-up patch (soon). - SILGen: Lower a regex literal expression to a call to `_StringProcessing.Regex.init(_regexString:)`. - String processing runtime: Add `Regex`, `DynamicCaptures` (matching actual APIs in apple/swift-experimental-string-processing), and `Regex(_regexString:)`. Upcoming: - Build `_MatchingEngine` and `_StringProcessing` modules with sources from apple/swift-experimental-string-processing. - Replace `DynamicCaptures` with inferred capture types. --- include/swift/AST/ASTContext.h | 3 ++ include/swift/AST/DiagnosticsFrontend.def | 2 + include/swift/AST/DiagnosticsSema.def | 11 ++-- include/swift/AST/Expr.h | 14 ++--- include/swift/AST/KnownIdentifiers.def | 5 +- include/swift/AST/KnownSDKTypes.def | 4 ++ include/swift/Frontend/Frontend.h | 12 +++++ include/swift/Strings.h | 2 + lib/AST/ASTContext.cpp | 17 +++++- lib/AST/ASTDumper.cpp | 5 +- lib/AST/ASTWalker.cpp | 5 -- lib/AST/Expr.cpp | 5 +- lib/Frontend/Frontend.cpp | 32 ++++++++++++ lib/Parse/ParseRegex.cpp | 26 +--------- lib/SILGen/SILGenApply.cpp | 21 ++++++++ lib/SILGen/SILGenExpr.cpp | 2 +- lib/Sema/CSApply.cpp | 5 +- lib/Sema/CSGen.cpp | 52 ++++++++----------- stdlib/public/StringProcessing/Regex.swift | 10 ++-- .../Sema/regex_invalid.swift | 4 -- .../Parse/regex.swift | 4 -- .../Parse/regex_parse_error.swift | 0 .../SILGen/regex_literal_silgen.swift | 8 +-- .../Sema/regex_literal_type_inference.swift | 13 +++++ .../string_processing_dummy.swift | 4 +- 25 files changed, 164 insertions(+), 102 deletions(-) delete mode 100644 test/ExperimentalRegex/Sema/regex_invalid.swift rename test/{ExperimentalRegex => StringProcessing}/Parse/regex.swift (82%) rename test/{ExperimentalRegex => StringProcessing}/Parse/regex_parse_error.swift (100%) rename test/{ExperimentalRegex => StringProcessing}/SILGen/regex_literal_silgen.swift (58%) create mode 100644 test/StringProcessing/Sema/regex_literal_type_inference.swift diff --git a/include/swift/AST/ASTContext.h b/include/swift/AST/ASTContext.h index 44e8ca951c9..abc32baf316 100644 --- a/include/swift/AST/ASTContext.h +++ b/include/swift/AST/ASTContext.h @@ -620,6 +620,9 @@ public: ConcreteDeclRef getBuiltinInitDecl(NominalTypeDecl *decl, KnownProtocolKind builtinProtocol, llvm::function_ref initName) const; + + /// Retrieve _StringProcessing.Regex.init(_regexString: String). + ConcreteDeclRef getRegexInitDecl(Type regexType) const; /// Retrieve the declaration of Swift.<(Int, Int) -> Bool. FuncDecl *getLessThanIntDecl() const; diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 7f52123bed7..a8da4202342 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -145,6 +145,8 @@ WARNING(emit_reference_dependencies_without_primary_file,none, WARNING(warn_implicit_concurrency_import_failed,none, "unable to perform implicit import of \"_Concurrency\" module: no such module found", ()) +WARNING(warn_implicit_string_processing_import_failed,none, + "unable to perform implicit import of \"_StringProcessing\" module: no such module found", ()) ERROR(error_module_name_required,none, "-module-name is required", ()) ERROR(error_bad_module_name,none, diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index ac805477ad2..d863ffd5375 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -3668,9 +3668,6 @@ ERROR(builtin_string_literal_broken_proto,none, ERROR(string_literal_broken_proto,none, "protocol 'ExpressibleByStringLiteral' is broken", ()) -ERROR(regex_decl_broken,none, - "cannot find 'Regex' type in scope", ()) - // Array literals ERROR(should_use_dictionary_literal,none, "dictionary of type %0 cannot be %select{used|initialized}1 " @@ -4722,6 +4719,14 @@ ERROR(async_unavailable_decl,none, "%0 %1 is unavailable from asynchronous contexts%select{|; %3}2", (DescriptiveDeclKind, DeclBaseName, bool, StringRef)) +//------------------------------------------------------------------------------ +// MARK: String Processing +//------------------------------------------------------------------------------ + +ERROR(string_processing_lib_missing,none, + "missing '%0' declaration, probably because the '_StringProcessing' " + "module was not imported properly", (StringRef)) + //------------------------------------------------------------------------------ // MARK: Type Check Types //------------------------------------------------------------------------------ diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index 9bbae48a092..7b325efa6aa 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -966,26 +966,18 @@ public: class RegexLiteralExpr : public LiteralExpr { SourceLoc Loc; StringRef RegexText; - Expr *SemanticExpr; - RegexLiteralExpr(SourceLoc loc, StringRef regexText, Expr *semanticExpr, - bool isImplicit) + RegexLiteralExpr(SourceLoc loc, StringRef regexText, bool isImplicit) : LiteralExpr(ExprKind::RegexLiteral, isImplicit), Loc(loc), - RegexText(regexText), SemanticExpr(semanticExpr) {} + RegexText(regexText) {} public: static RegexLiteralExpr *createParsed(ASTContext &ctx, SourceLoc loc, - StringRef regexText, - Expr *semanticExpr); + StringRef regexText); /// Retrieve the raw regex text. StringRef getRegexText() const { return RegexText; } - /// Retrieve the semantic expression that the regex will be type-checked and - /// emitted as. - Expr *getSemanticExpr() const { return SemanticExpr; } - void setSemanticExpr(Expr *expr) { SemanticExpr = expr; } - SourceRange getSourceRange() const { return Loc; } static bool classof(const Expr *E) { diff --git a/include/swift/AST/KnownIdentifiers.def b/include/swift/AST/KnownIdentifiers.def index e89d37d6b44..c79c17bc848 100644 --- a/include/swift/AST/KnownIdentifiers.def +++ b/include/swift/AST/KnownIdentifiers.def @@ -250,9 +250,10 @@ IDENTIFIER(pullback) IDENTIFIER(TangentVector) IDENTIFIER(zero) -// Regex literals +// String processing IDENTIFIER(Regex) -IDENTIFIER(_regexString) +IDENTIFIER_(regexString) +IDENTIFIER_(StringProcessing) // Distributed actors IDENTIFIER(transport) diff --git a/include/swift/AST/KnownSDKTypes.def b/include/swift/AST/KnownSDKTypes.def index 2511b9816dc..bc1e2e5d67a 100644 --- a/include/swift/AST/KnownSDKTypes.def +++ b/include/swift/AST/KnownSDKTypes.def @@ -48,4 +48,8 @@ KNOWN_SDK_TYPE_DECL(Distributed, DistributedActor, ProtocolDecl, 0) KNOWN_SDK_TYPE_DECL(Distributed, ActorIdentity, ProtocolDecl, 0) KNOWN_SDK_TYPE_DECL(Distributed, AnyActorIdentity, StructDecl, 0) +// String processing +KNOWN_SDK_TYPE_DECL(StringProcessing, Regex, StructDecl, 1) +KNOWN_SDK_TYPE_DECL(StringProcessing, DynamicCaptures, EnumDecl, 0) + #undef KNOWN_SDK_TYPE_DECL diff --git a/include/swift/Frontend/Frontend.h b/include/swift/Frontend/Frontend.h index 44bf8e550f1..ce06492dcd2 100644 --- a/include/swift/Frontend/Frontend.h +++ b/include/swift/Frontend/Frontend.h @@ -354,6 +354,10 @@ public: /// imported. bool shouldImportSwiftConcurrency() const; + /// Whether the Swift String Processing support library should be implicitly + /// imported. + bool shouldImportSwiftStringProcessing() const; + /// Performs input setup common to these tools: /// sil-opt, sil-func-extractor, sil-llvm-gen, and sil-nm. /// Return value includes the buffer so caller can keep it alive. @@ -533,6 +537,14 @@ public: /// i.e. if it can be found. bool canImportSwiftConcurrency() const; + /// Verify that if an implicit import of the `StringProcessing` module if + /// expected, it can actually be imported. Emit a warning, otherwise. + void verifyImplicitStringProcessingImport(); + + /// Whether the Swift String Processing support library can be imported + /// i.e. if it can be found. + bool canImportSwiftStringProcessing() const; + /// Gets the SourceFile which is the primary input for this CompilerInstance. /// \returns the primary SourceFile, or nullptr if there is no primary input; /// if there are _multiple_ primary inputs, fails with an assertion. diff --git a/include/swift/Strings.h b/include/swift/Strings.h index ad580a496ff..68e98975b27 100644 --- a/include/swift/Strings.h +++ b/include/swift/Strings.h @@ -26,6 +26,8 @@ constexpr static const StringLiteral SWIFT_ONONE_SUPPORT = "SwiftOnoneSupport"; constexpr static const StringLiteral SWIFT_CONCURRENCY_NAME = "_Concurrency"; /// The name of the Distributed module, which supports that extension. constexpr static const StringLiteral SWIFT_DISTRIBUTED_NAME = "_Distributed"; +/// The name of the StringProcessing module, which supports that extension. +constexpr static const StringLiteral SWIFT_STRING_PROCESSING_NAME = "_StringProcessing"; /// The name of the SwiftShims module, which contains private stdlib decls. constexpr static const StringLiteral SWIFT_SHIMS_NAME = "SwiftShims"; /// The name of the Builtin module, which contains Builtin functions. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c08f4317c30..ca37d195bbd 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1216,8 +1216,23 @@ ASTContext::getBuiltinInitDecl(NominalTypeDecl *decl, return witness; } +ConcreteDeclRef ASTContext::getRegexInitDecl(Type regexType) const { + auto *spModule = getLoadedModule(Id_StringProcessing); + DeclName name(*const_cast(this), + DeclBaseName::createConstructor(), + {Id_regexString}); + SmallVector results; + spModule->lookupQualified(getRegexType(), DeclNameRef(name), + NL_IncludeUsableFromInline, results); + assert(results.size() == 1); + auto *foundDecl = cast(results[0]); + auto subs = regexType->getMemberSubstitutionMap(spModule, foundDecl); + return ConcreteDeclRef(foundDecl, subs); +} + static -FuncDecl *getBinaryComparisonOperatorIntDecl(const ASTContext &C, StringRef op, FuncDecl *&cached) { +FuncDecl *getBinaryComparisonOperatorIntDecl(const ASTContext &C, StringRef op, + FuncDecl *&cached) { if (cached) return cached; diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 9b019396747..7f3e691a06e 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1909,7 +1909,10 @@ public: } void visitRegexLiteralExpr(RegexLiteralExpr *E) { printCommon(E, "regex_literal_expr"); - printRec(E->getSemanticExpr()); + PrintWithColorRAII(OS, LiteralValueColor) + << " text=" << QuotedString(E->getRegexText()) + << " initializer="; + E->getInitializer().dump(PrintWithColorRAII(OS, LiteralValueColor).getOS()); PrintWithColorRAII(OS, ParenthesisColor) << ')'; } diff --git a/lib/AST/ASTWalker.cpp b/lib/AST/ASTWalker.cpp index d010c6dd2e8..58cc4927782 100644 --- a/lib/AST/ASTWalker.cpp +++ b/lib/AST/ASTWalker.cpp @@ -1153,11 +1153,6 @@ class Traversal : public ASTVisitorgetSemanticExpr())) { - E->setSemanticExpr(newExpr); - } else { - return nullptr; - } return E; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6bdd133fbc0..14ba90b0246 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -2212,9 +2212,8 @@ SourceLoc TapExpr::getEndLoc() const { RegexLiteralExpr * RegexLiteralExpr::createParsed(ASTContext &ctx, SourceLoc loc, - StringRef regexText, Expr *semanticExpr) { - return new (ctx) RegexLiteralExpr(loc, regexText, semanticExpr, - /*implicit*/ false); + StringRef regexText) { + return new (ctx) RegexLiteralExpr(loc, regexText, /*implicit*/ false); } void swift::simple_display(llvm::raw_ostream &out, const ClosureExpr *CE) { diff --git a/lib/Frontend/Frontend.cpp b/lib/Frontend/Frontend.cpp index dd21e04623c..ab963847b8d 100644 --- a/lib/Frontend/Frontend.cpp +++ b/lib/Frontend/Frontend.cpp @@ -793,6 +793,10 @@ bool CompilerInvocation::shouldImportSwiftConcurrency() const { FrontendOptions::ParseInputMode::SwiftModuleInterface; } +bool CompilerInvocation::shouldImportSwiftStringProcessing() const { + return getLangOptions().EnableExperimentalStringProcessing; +} + /// Implicitly import the SwiftOnoneSupport module in non-optimized /// builds. This allows for use of popular specialized functions /// from the standard library, which makes the non-optimized builds @@ -833,6 +837,20 @@ bool CompilerInstance::canImportSwiftConcurrency() const { {getASTContext().getIdentifier(SWIFT_CONCURRENCY_NAME), SourceLoc()}); } +void CompilerInstance::verifyImplicitStringProcessingImport() { + if (Invocation.shouldImportSwiftStringProcessing() && + !canImportSwiftStringProcessing()) { + Diagnostics.diagnose(SourceLoc(), + diag::warn_implicit_string_processing_import_failed); + } +} + +bool CompilerInstance::canImportSwiftStringProcessing() const { + return getASTContext().canImportModule( + {getASTContext().getIdentifier(SWIFT_STRING_PROCESSING_NAME), + SourceLoc()}); +} + ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const { auto &frontendOpts = Invocation.getFrontendOptions(); @@ -873,6 +891,19 @@ ImplicitImportInfo CompilerInstance::getImplicitImportInfo() const { } } + if (Invocation.shouldImportSwiftStringProcessing()) { + switch (imports.StdlibKind) { + case ImplicitStdlibKind::Builtin: + case ImplicitStdlibKind::None: + break; + + case ImplicitStdlibKind::Stdlib: + if (canImportSwiftStringProcessing()) + pushImport(SWIFT_STRING_PROCESSING_NAME); + break; + } + } + imports.ShouldImportUnderlyingModule = frontendOpts.ImportUnderlyingModule; imports.BridgingHeaderPath = frontendOpts.ImplicitObjCHeaderPath; return imports; @@ -1084,6 +1115,7 @@ bool CompilerInstance::loadStdlibIfNeeded() { } verifyImplicitConcurrencyImport(); + verifyImplicitStringProcessingImport(); // If we failed to load, we should have already diagnosed. if (M->failedToLoad()) { diff --git a/lib/Parse/ParseRegex.cpp b/lib/Parse/ParseRegex.cpp index 7356c5c96f3..931554e2709 100644 --- a/lib/Parse/ParseRegex.cpp +++ b/lib/Parse/ParseRegex.cpp @@ -54,30 +54,6 @@ ParserResult Parser::parseExprRegexLiteral() { diagnose(Tok, diag::regex_literal_parsing_error, errorStr); auto loc = consumeToken(); - - // Create an implicit .init(_regexString: "") call to serve as the - // semantic expression for the regex. The type-checker will provide it with - // the correct contextual type. We delay the contextual type for a couple of - // reasons: - // 1. We need to delay type lookup until after parsing. - // 2. Even if the AST synthesis were done lazily in e.g a request, we don't - // currently have great support for implicit TypeExprs for unopened generic - // types, as we want to phase out the use of UnboundGenericType. The Regex - // type isn't currently generic, but might be in the future. - auto *regexStringExpr = - new (Context) StringLiteralExpr(Context.AllocateCopy(regexText), loc); - regexStringExpr->setImplicit(); - - DeclName initName(Context, DeclBaseName::createConstructor(), - {Context.Id__regexString}); - DeclNameRef initNameRef(initName); - auto *dotInit = new (Context) UnresolvedMemberExpr( - /*dotLoc*/ loc, DeclNameLoc(loc), initNameRef, /*implicit*/ true); - - auto *args = - ArgumentList::forImplicitCallTo(initNameRef, {regexStringExpr}, Context); - auto *call = CallExpr::createImplicit(Context, dotInit, args); - return makeParserResult( - RegexLiteralExpr::createParsed(Context, loc, regexText, call)); + RegexLiteralExpr::createParsed(Context, loc, regexText)); } diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 57a8da623df..d92c281ba47 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -1896,6 +1896,25 @@ buildBuiltinLiteralArgs(SILGenFunction &SGF, SGFContext C, return builtinLiteralArgs; } +static inline PreparedArguments +buildBuiltinLiteralArgs(SILGenFunction &SGF, SGFContext C, + RegexLiteralExpr *expr) { + auto &ctx = SGF.getASTContext(); + // %0 = string_literal + auto strLiteralArgs = emitStringLiteral(SGF, expr, expr->getRegexText(), C, + StringLiteralExpr::Encoding::UTF8); + // %1 = function_ref String.init( + // _builtinStringLiteral:utf8CodeUnitCount:isASCII:) + // %2 = apply %1(%0, ..., ...) -> $String + auto strInitDecl = ctx.getStringBuiltinInitDecl(ctx.getStringDecl()); + RValue string = SGF.emitApplyAllocatingInitializer( + expr, strInitDecl, std::move(strLiteralArgs), + /*overriddenSelfType*/ Type(), SGFContext()); + PreparedArguments args({AnyFunctionType::Param(ctx.getStringType())}); + args.add(expr, std::move(string)); + return args; +} + static inline PreparedArguments buildBuiltinLiteralArgs(SILGenFunction &SGF, SGFContext C, MagicIdentifierLiteralExpr *magicLiteral) { @@ -1961,6 +1980,8 @@ static inline PreparedArguments buildBuiltinLiteralArgs(SILGenFunction &SGF, return buildBuiltinLiteralArgs(SGF, C, integerLiteral); } else if (auto floatLiteral = dyn_cast(literal)) { return buildBuiltinLiteralArgs(SGF, C, floatLiteral); + } else if (auto regexLiteral = dyn_cast(literal)) { + return buildBuiltinLiteralArgs(SGF, C, regexLiteral); } else { return buildBuiltinLiteralArgs( SGF, C, cast(literal)); diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index 24fd13bd171..9c8e71884cf 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -2528,7 +2528,7 @@ visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E, } RValue RValueEmitter::visitRegexLiteralExpr(RegexLiteralExpr *E, SGFContext C) { - return SGF.emitRValue(E->getSemanticExpr()); + return SGF.emitLiteral(E, C); } RValue RValueEmitter:: diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 189d94061f2..ba492782818 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -2792,7 +2792,10 @@ namespace { } Expr *visitRegexLiteralExpr(RegexLiteralExpr *expr) { - return simplifyExprType(expr); + simplifyExprType(expr); + expr->setInitializer( + cs.getASTContext().getRegexInitDecl(cs.getType(expr))); + return expr; } Expr *visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *expr) { diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 3e3b2920fcd..fbc50026baa 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -1163,35 +1163,6 @@ namespace { return tv; } - Type visitRegexLiteralExpr(RegexLiteralExpr *expr) { - auto &ctx = CS.getASTContext(); - auto exprLoc = expr->getLoc(); - - // TODO: This should eventually be a known stdlib decl. - auto regexLookup = TypeChecker::lookupUnqualified( - CurDC, DeclNameRef(ctx.Id_Regex), exprLoc); - if (regexLookup.size() != 1) { - ctx.Diags.diagnose(exprLoc, diag::regex_decl_broken); - return Type(); - } - auto result = regexLookup.allResults()[0]; - auto *regexDecl = dyn_cast(result.getValueDecl()); - if (!regexDecl || isa(regexDecl)) { - ctx.Diags.diagnose(exprLoc, diag::regex_decl_broken); - return Type(); - } - - auto *loc = CS.getConstraintLocator(expr); - auto regexTy = CS.replaceInferableTypesWithTypeVars( - regexDecl->getDeclaredType(), loc); - - // The semantic expr should be of regex type. - auto semanticExprTy = CS.getType(expr->getSemanticExpr()); - CS.addConstraint(ConstraintKind::Bind, regexTy, semanticExprTy, loc); - - return regexTy; - } - Type visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *expr) { switch (expr->getKind()) { // Magic pointer identifiers are of type UnsafeMutableRawPointer. @@ -1286,6 +1257,29 @@ namespace { return witnessType; } + Type visitRegexLiteralExpr(RegexLiteralExpr *E) { + auto &ctx = CS.getASTContext(); + auto *regexDecl = ctx.getRegexDecl(); + if (!regexDecl) { + ctx.Diags.diagnose(E->getLoc(), + diag::string_processing_lib_missing, + ctx.Id_Regex.str()); + return Type(); + } + auto substringType = ctx.getSubstringType(); + auto dynCapturesType = ctx.getDynamicCapturesType(); + if (!dynCapturesType) { + ctx.Diags.diagnose(E->getLoc(), + diag::string_processing_lib_missing, + "DynamicCaptures"); + return Type(); + } + // TODO: Replace `(Substring, DynamicCaptures)` with type inferred from + // the regex. + auto matchType = TupleType::get({substringType, dynCapturesType}, ctx); + return BoundGenericStructType::get(regexDecl, Type(), {matchType}); + } + Type visitDeclRefExpr(DeclRefExpr *E) { auto locator = CS.getConstraintLocator(E); diff --git a/stdlib/public/StringProcessing/Regex.swift b/stdlib/public/StringProcessing/Regex.swift index 3b37d0408c2..07ef2c31785 100644 --- a/stdlib/public/StringProcessing/Regex.swift +++ b/stdlib/public/StringProcessing/Regex.swift @@ -1,8 +1,10 @@ import Swift import _MatchingEngine -public struct DummyRegex { - public init() { - fatalError("Unimplemented") - } +@frozen +public struct Regex { + @usableFromInline + init(_regexString: String) {} } + +public enum DynamicCaptures {} diff --git a/test/ExperimentalRegex/Sema/regex_invalid.swift b/test/ExperimentalRegex/Sema/regex_invalid.swift deleted file mode 100644 index a9d4badce98..00000000000 --- a/test/ExperimentalRegex/Sema/regex_invalid.swift +++ /dev/null @@ -1,4 +0,0 @@ -// RUN: %target-typecheck-verify-swift -enable-experimental-string-processing -// REQUIRES: libswift - -'abc' // expected-error {{cannot find 'Regex' type in scope}} diff --git a/test/ExperimentalRegex/Parse/regex.swift b/test/StringProcessing/Parse/regex.swift similarity index 82% rename from test/ExperimentalRegex/Parse/regex.swift rename to test/StringProcessing/Parse/regex.swift index d9682fca13d..ae8d7f10dc2 100644 --- a/test/ExperimentalRegex/Parse/regex.swift +++ b/test/StringProcessing/Parse/regex.swift @@ -1,10 +1,6 @@ // RUN: %target-typecheck-verify-swift -enable-experimental-string-processing // REQUIRES: libswift -struct Regex { - init(_regexString: String) {} -} - var s = 'abc' var s1 = ('*', '+', '?') diff --git a/test/ExperimentalRegex/Parse/regex_parse_error.swift b/test/StringProcessing/Parse/regex_parse_error.swift similarity index 100% rename from test/ExperimentalRegex/Parse/regex_parse_error.swift rename to test/StringProcessing/Parse/regex_parse_error.swift diff --git a/test/ExperimentalRegex/SILGen/regex_literal_silgen.swift b/test/StringProcessing/SILGen/regex_literal_silgen.swift similarity index 58% rename from test/ExperimentalRegex/SILGen/regex_literal_silgen.swift rename to test/StringProcessing/SILGen/regex_literal_silgen.swift index 311fba168ff..f7e7f3a3b22 100644 --- a/test/ExperimentalRegex/SILGen/regex_literal_silgen.swift +++ b/test/StringProcessing/SILGen/regex_literal_silgen.swift @@ -1,13 +1,9 @@ // RUN: %target-swift-frontend -emit-silgen -enable-experimental-string-processing %s | %FileCheck %s // REQUIRES: libswift -struct Regex { - init(_regexString: String) {} -} - var s = 'abc' // CHECK: [[REGEX_STR_LITERAL:%[0-9]+]] = string_literal utf8 "abc" // CHECK: [[STRING_INIT:%[0-9]+]] = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // CHECK: [[REGEX_STR:%[0-9]+]] = apply [[STRING_INIT]]([[REGEX_STR_LITERAL]] -// CHECK: [[REGEX_INIT:%[0-9]+]] = function_ref @$s20regex_literal_silgen5RegexV01_A6StringACSS_tcfC : $@convention(method) (@owned String, @thin Regex.Type) -> Regex -// CHECK: apply [[REGEX_INIT]]([[REGEX_STR]] +// CHECK: [[REGEX_INIT:%[0-9]+]] = function_ref @$s17_StringProcessing5RegexV06_regexA0ACyxGSS_tcfC : $@convention(method) <τ_0_0> (@owned String, @thin Regex<τ_0_0>.Type) -> Regex<τ_0_0> +// CHECK: apply [[REGEX_INIT]]<(Substring, DynamicCaptures)>([[REGEX_STR]], {{%.+}}) : $@convention(method) <τ_0_0> (@owned String, @thin Regex<τ_0_0>.Type) -> Regex<τ_0_0> diff --git a/test/StringProcessing/Sema/regex_literal_type_inference.swift b/test/StringProcessing/Sema/regex_literal_type_inference.swift new file mode 100644 index 00000000000..7075b50e51a --- /dev/null +++ b/test/StringProcessing/Sema/regex_literal_type_inference.swift @@ -0,0 +1,13 @@ +// RUN: %target-typecheck-verify-swift -enable-experimental-string-processing +// REQUIRES: libswift + +let r0 = '.' // okay + +let r1: Regex<(Substring, DynamicCaptures)> = '.(.)' // okay + +// expected-error @+2 {{cannot assign value of type 'Regex<(Substring, DynamicCaptures)>' to type 'Regex'}} +// expected-note @+1 {{arguments to generic parameter 'Match' ('(Substring, DynamicCaptures)' and 'Substring') are expected to be equal}} +let r2: Regex = '.(.)' + +func takesRegex(_: Regex) {} +takesRegex('') // okay diff --git a/test/StringProcessing/string_processing_dummy.swift b/test/StringProcessing/string_processing_dummy.swift index a096bdfb1d3..61745ec6cf3 100644 --- a/test/StringProcessing/string_processing_dummy.swift +++ b/test/StringProcessing/string_processing_dummy.swift @@ -1,11 +1,11 @@ // RUN: %target-swift-frontend -enable-experimental-string-processing -parse-as-library -emit-sil -verify %s -// REQUIRES: string_processing +// REQUIRES: libswift,string_processing import _MatchingEngine import _StringProcessing func foo() { _ = DummyMatchingEngine() - _ = DummyRegex() + let _: Regex<(Substring, DynamicCaptures)> = '' }