diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 956edb105d13b..22897dd19a4c6 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -4975,7 +4975,10 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl { TypeChecked, /// This is a memberwise initializer that will be synthesized by SILGen. - MemberwiseInitializer + MemberwiseInitializer, + + /// Function body text was deserialized from a .swiftmodule. + Deserialized // This enum currently needs to fit in a 3-bit bitfield. }; @@ -4997,6 +5000,9 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl { /// BodyKind::TypeChecked. BraceStmt *Body; + /// This enum member is active if getBodyKind() is BodyKind::Deserialized. + StringRef BodyStringRepresentation; + /// This enum member is active if getBodyKind() == BodyKind::Synthesize. BodySynthesizer Synthesizer; @@ -5091,6 +5097,11 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl { return getBodyKind() != BodyKind::None; } + /// Returns true if the text of this function's body can be retrieved either + /// by extracting the text from the source buffer or reading the inlinable + /// body from a deserialized swiftmodule. + bool hasInlinableBodyText() const; + /// Returns the function body, if it was parsed, or nullptr otherwise. /// /// Note that a null return value does not imply that the source code did not @@ -5154,6 +5165,18 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl { setBodyKind(BodyKind::TypeChecked); } + /// Gets the body of this function, stripping the unused portions of #if + /// configs inside the body. If this function was not deserialized from a + /// .swiftmodule, this body is reconstructed from the original + /// source buffer. + StringRef getInlinableBodyText(SmallVectorImpl &scratch) const; + + void setBodyStringRepresentation(StringRef body) { + assert(getBodyKind() == BodyKind::None); + setBodyKind(BodyKind::Deserialized); + BodyStringRepresentation = body; + } + bool isBodyTypeChecked() const { return getBodyKind() == BodyKind::TypeChecked; } diff --git a/include/swift/AST/PrintOptions.h b/include/swift/AST/PrintOptions.h index 7823671a1b182..f1a066b27c5c4 100644 --- a/include/swift/AST/PrintOptions.h +++ b/include/swift/AST/PrintOptions.h @@ -23,6 +23,7 @@ #include namespace swift { +class ASTPrinter; class GenericEnvironment; class CanType; class Decl; @@ -356,10 +357,9 @@ struct PrintOptions { QualifyNestedDeclarations ShouldQualifyNestedDeclarations = QualifyNestedDeclarations::Never; - /// \brief If this is not \c nullptr then functions (including accessors and - /// constructors) will be printed with a body that is determined by this - /// function. - std::function FunctionBody; + /// \brief If this is not \c nullptr then function bodies (including accessors + /// and constructors) will be printed by this function. + std::function FunctionBody; BracketOptions BracketOptions; diff --git a/include/swift/Serialization/DeclTypeRecordNodes.def b/include/swift/Serialization/DeclTypeRecordNodes.def index 4df30ac43349c..4859fbb625adb 100644 --- a/include/swift/Serialization/DeclTypeRecordNodes.def +++ b/include/swift/Serialization/DeclTypeRecordNodes.def @@ -180,6 +180,7 @@ OTHER(NORMAL_PROTOCOL_CONFORMANCE_ID, 246) OTHER(PROTOCOL_CONFORMANCE_XREF, 247) OTHER(MEMBERS, 248) OTHER(XREF, 249) +OTHER(INLINABLE_BODY_TEXT, 250) #undef RECORD #undef DECLTYPERECORDNODES_HAS_RECORD_VAL diff --git a/include/swift/Serialization/ModuleFile.h b/include/swift/Serialization/ModuleFile.h index dd656cada859e..d18457367f284 100644 --- a/include/swift/Serialization/ModuleFile.h +++ b/include/swift/Serialization/ModuleFile.h @@ -857,6 +857,9 @@ class ModuleFile /// Reads a foreign error conformance from \c DeclTypeCursor, if present. Optional maybeReadForeignErrorConvention(); + + /// Reads inlinable body text from \c DeclTypeCursor, if present. + Optional maybeReadInlinableBodyText(); }; } // end namespace swift diff --git a/include/swift/Serialization/ModuleFormat.h b/include/swift/Serialization/ModuleFormat.h index 1a8de4c6e0bae..6646dc9d77d06 100644 --- a/include/swift/Serialization/ModuleFormat.h +++ b/include/swift/Serialization/ModuleFormat.h @@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0; /// describe what change you made. The content of this comment isn't important; /// it just ensures a conflict if two people change the module format. /// Don't worry about adhering to the 80-column limit for this line. -const uint16_t VERSION_MINOR = 443; // Last change: serialize unsubstituted type alias type +const uint16_t VERSION_MINOR = 444; // Last change: inlinable body text using DeclIDField = BCFixed<31>; @@ -979,8 +979,11 @@ namespace decls_block { BCVBR<5>, // number of parameter name components BCArray // name components, // followed by TypeID dependencies - // Trailed by its generic parameters, if any, followed by the parameter - // patterns. + // This record is trailed by: + // - its generic parameters, if any + // - its parameter patterns, + // - the foreign error convention, if any + // - inlinable body text, if any >; using VarLayout = BCRecordLayout< @@ -1044,6 +1047,8 @@ namespace decls_block { // - its _silgen_name, if any // - its generic parameters, if any // - body parameter patterns + // - the foreign error convention, if any + // - inlinable body text, if any >; // TODO: remove the unnecessary FuncDecl components here @@ -1073,6 +1078,8 @@ namespace decls_block { // - its _silgen_name, if any // - its generic parameters, if any // - body parameter patterns + // - the foreign error convention, if any + // - inlinable body text, if any >; using PatternBindingLayout = BCRecordLayout< @@ -1176,6 +1183,12 @@ namespace decls_block { BCFixed<1>, // implicit? BCFixed<1>, // objc? GenericEnvironmentIDField // generic environment + // This record is trailed by its inlinable body text + >; + + using InlinableBodyTextLayout = BCRecordLayout< + INLINABLE_BODY_TEXT, + BCBlob // body text >; using ParameterListLayout = BCRecordLayout< diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 092d9a8b13178..99b3928d10a1a 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -81,6 +81,15 @@ PrintOptions PrintOptions::printTextualInterfaceFile() { result.SkipImports = true; result.OmitNameOfInaccessibleProperties = true; + result.FunctionBody = [](const ValueDecl *decl, ASTPrinter &printer) { + auto AFD = dyn_cast(decl); + if (!AFD || !AFD->hasInlinableBodyText()) return; + if (AFD->getResilienceExpansion() != ResilienceExpansion::Minimal) + return; + SmallString<128> scratch; + printer << " " << AFD->getInlinableBodyText(scratch); + }; + class ShouldPrintForTextualInterface : public ShouldPrintChecker { bool shouldPrint(const Decl *D, const PrintOptions &options) override { // Skip anything that isn't 'public' or '@usableFromInline'. @@ -645,6 +654,7 @@ class PrintAST : public ASTVisitor { void printAttributes(const Decl *D); void printTypedPattern(const TypedPattern *TP); + void printBraceStmt(const BraceStmt *stmt, bool newlineIfEmpty = true); public: void printPattern(const Pattern *pattern); @@ -686,6 +696,7 @@ class PrintAST : public ASTVisitor { void printGenericDeclGenericParams(GenericContext *decl); void printGenericDeclGenericRequirements(GenericContext *decl); void printInherited(const Decl *decl); + void printBodyIfNecessary(const AbstractFunctionDecl *decl); void printEnumElement(EnumElementDecl *elt); @@ -1471,6 +1482,29 @@ bool PrintAST::shouldPrint(const Decl *D, bool Notify) { return Result; } +void PrintAST::printBraceStmt(const BraceStmt *stmt, bool newlineIfEmpty) { + Printer << "{"; + if (printASTNodes(stmt->getElements()) || newlineIfEmpty) { + Printer.printNewline(); + indent(); + } + Printer << "}"; +} + +void PrintAST::printBodyIfNecessary(const AbstractFunctionDecl *decl) { + if (auto BodyFunc = Options.FunctionBody) { + BodyFunc(decl, Printer); + indent(); + return; + } + + if (!Options.FunctionDefinitions || !decl->getBody()) + return; + + Printer << " "; + printBraceStmt(decl->getBody(), /*newlineIfEmpty*/!isa(decl)); +} + static bool isAccessorAssumedNonMutating(AccessorKind kind) { switch (kind) { case AccessorKind::Get: @@ -1630,26 +1664,37 @@ void PrintAST::printAccessors(AbstractStorageDecl *ASD) { Printer << " "; Printer.printKeyword(getAccessorLabel(Accessor)); } else { - Printer.printNewline(); - IndentRAII IndentMore(*this); + { + IndentRAII IndentMore(*this); + indent(); + visit(Accessor); + } indent(); - visit(Accessor); + Printer.printNewline(); } }; - Printer << " {"; if ((PrintAbstract || (impl.getReadImpl() == ReadImplKind::Get && ASD->getGetter())) && !ASD->supportsMutation() && !ASD->isGetterMutating() && PrintAccessorBody && !Options.FunctionDefinitions) { // Omit the 'get' keyword. Directly print getter if (auto BodyFunc = Options.FunctionBody) { - Printer.printNewline(); - IndentRAII IndentBody(*this); + BodyFunc(ASD->getGetter(), Printer); indent(); - Printer << BodyFunc(ASD->getGetter()); + return; } - } else if (PrintAbstract) { + Printer.printNewline(); + indent(); + return; + } + + Printer << " {"; + + if (PrintAccessorBody) + Printer.printNewline(); + + if (PrintAbstract) { PrintAccessor(ASD->getGetter()); if (ASD->supportsMutation()) PrintAccessor(ASD->getSetter()); @@ -1693,12 +1738,16 @@ void PrintAST::printAccessors(AbstractStorageDecl *ASD) { break; } } - if (PrintAccessorBody) { - Printer.printNewline(); - indent(); - } else + + if (!PrintAccessorBody) Printer << " "; + Printer << "}"; + + if (!PrintAbstract) + Printer.printNewline(); + + indent(); } void PrintAST::printMembersOfDecl(Decl *D, bool needComma, @@ -2497,7 +2546,6 @@ void PrintAST::visitAccessorDecl(AccessorDecl *decl) { [&]{ Printer << getAccessorLabel(decl); }); - Printer << " {"; break; case AccessorKind::Set: case AccessorKind::WillSet: @@ -2515,24 +2563,9 @@ void PrintAST::visitAccessorDecl(AccessorDecl *decl) { } } }); - Printer << " {"; } - if (auto BodyFunc = Options.FunctionBody) { - { - IndentRAII IndentBody(*this); - indent(); - Printer.printNewline(); - Printer << BodyFunc(decl); - } - indent(); - Printer.printNewline(); - } else if (Options.FunctionDefinitions && decl->getBody()) { - if (printASTNodes(decl->getBody()->getElements())) { - Printer.printNewline(); - indent(); - } - } - Printer << "}"; + + printBodyIfNecessary(decl); } void PrintAST::visitFuncDecl(FuncDecl *decl) { @@ -2604,22 +2637,7 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) { printGenericDeclGenericRequirements(decl); } - if (auto BodyFunc = Options.FunctionBody) { - Printer << " {"; - Printer.printNewline(); - { - IndentRAII IndentBody(*this); - indent(); - Printer << BodyFunc(decl); - } - indent(); - Printer.printNewline(); - Printer << "}"; - - } else if (Options.FunctionDefinitions && decl->getBody()) { - Printer << " "; - visit(decl->getBody()); - } + printBodyIfNecessary(decl); } void PrintAST::printEnumElement(EnumElementDecl *elt) { @@ -2788,21 +2806,7 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) { printGenericDeclGenericRequirements(decl); - if (auto BodyFunc = Options.FunctionBody) { - Printer << " {"; - { - Printer.printNewline(); - IndentRAII IndentBody(*this); - indent(); - Printer << BodyFunc(decl); - } - indent(); - Printer.printNewline(); - Printer << "}"; - } else if (Options.FunctionDefinitions && decl->getBody()) { - Printer << " "; - visit(decl->getBody()); - } + printBodyIfNecessary(decl); } void PrintAST::visitDestructorDecl(DestructorDecl *decl) { @@ -2814,12 +2818,7 @@ void PrintAST::visitDestructorDecl(DestructorDecl *decl) { Printer << "deinit"; }); - if (!Options.FunctionDefinitions || !decl->getBody()) { - return; - } - - Printer << " "; - visit(decl->getBody()); + printBodyIfNecessary(decl); } void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) { @@ -2929,11 +2928,7 @@ void PrintAST::visitMissingMemberDecl(MissingMemberDecl *decl) { } void PrintAST::visitBraceStmt(BraceStmt *stmt) { - Printer << "{"; - printASTNodes(stmt->getElements()); - Printer.printNewline(); - indent(); - Printer << "}"; + printBraceStmt(stmt); } void PrintAST::visitReturnStmt(ReturnStmt *stmt) { diff --git a/lib/AST/ASTVerifier.cpp b/lib/AST/ASTVerifier.cpp index 7eeaf89e15dd0..ae1adc72a856b 100644 --- a/lib/AST/ASTVerifier.cpp +++ b/lib/AST/ASTVerifier.cpp @@ -490,6 +490,7 @@ class Verifier : public ASTWalker { case AbstractFunctionDecl::BodyKind::TypeChecked: case AbstractFunctionDecl::BodyKind::Skipped: case AbstractFunctionDecl::BodyKind::MemberwiseInitializer: + case AbstractFunctionDecl::BodyKind::Deserialized: return true; case AbstractFunctionDecl::BodyKind::Unparsed: diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 141c9f4aa92f7..1c13a98e01b13 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -5064,6 +5064,7 @@ SourceRange AbstractFunctionDecl::getBodySourceRange() const { switch (getBodyKind()) { case BodyKind::None: case BodyKind::MemberwiseInitializer: + case BodyKind::Deserialized: return SourceRange(); case BodyKind::Parsed: @@ -5419,6 +5420,34 @@ void AbstractFunctionDecl::computeType(AnyFunctionType::ExtInfo info) { computeSelfDeclType(); } +bool AbstractFunctionDecl::hasInlinableBodyText() const { + switch (getBodyKind()) { + case BodyKind::Deserialized: + return true; + case BodyKind::Parsed: + case BodyKind::TypeChecked: + return getBody() && !getBody()->isImplicit(); + case BodyKind::None: + case BodyKind::Unparsed: + case BodyKind::Synthesize: + case BodyKind::Skipped: + case BodyKind::MemberwiseInitializer: + return false; + } +} + +StringRef AbstractFunctionDecl::getInlinableBodyText( + SmallVectorImpl &scratch) const { + assert(hasInlinableBodyText() && + "can't get string representation of function with no text"); + + if (getBodyKind() == BodyKind::Deserialized) + return BodyStringRepresentation; + + auto body = getBody(); + return extractInlinableText(getASTContext().SourceMgr, body, scratch); +} + FuncDecl *FuncDecl::createImpl(ASTContext &Context, SourceLoc StaticLoc, StaticSpellingKind StaticSpelling, diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 3c904dcf4efcf..93667df9e03fb 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -4203,9 +4203,10 @@ struct Parser::ParsedAccessors { } }; -static bool parseAccessorIntroducer(Parser &P, bool parsingLimitedSyntax, - DeclAttributes &Attributes, AccessorKind &Kind, - AddressorKind &addressorKind, SourceLoc &Loc) { +static bool parseAccessorIntroducer(Parser &P, DeclAttributes &Attributes, + AccessorKind &Kind, + AddressorKind &addressorKind, + SourceLoc &Loc) { bool FoundCCToken; P.parseDeclAttributeList(Attributes, FoundCCToken); @@ -4260,20 +4261,8 @@ bool Parser::parseGetSet(ParseDeclOptions Flags, // SIL mode and textual interfaces use the same syntax. // Otherwise, we have a normal var or subscript declaration and we need // parse the full complement of specifiers, along with their bodies. - bool parsingLimitedSyntax = Flags.contains(PD_InProtocol); - if (!parsingLimitedSyntax) { - switch (SF.Kind) { - case SourceFileKind::Interface: - // FIXME: Textual interfaces /can/ have inlinable code but don't have to. - case SourceFileKind::SIL: - parsingLimitedSyntax = true; - break; - case SourceFileKind::Library: - case SourceFileKind::Main: - case SourceFileKind::REPL: - break; - } - } + bool parsingLimitedSyntax = Flags.contains(PD_InProtocol) || + SF.Kind == SourceFileKind::SIL; SyntaxParsingContext AccessorListCtx(SyntaxContext, SyntaxKind::AccessorBlock); @@ -4328,7 +4317,7 @@ bool Parser::parseGetSet(ParseDeclOptions Flags, AddressorKind addressorKind = AddressorKind::NotAddressor; SourceLoc Loc; bool NotAccessor = parseAccessorIntroducer( - *this, parsingLimitedSyntax, Attributes, Kind, addressorKind, Loc); + *this, Attributes, Kind, addressorKind, Loc); if (NotAccessor) { AccessorCtx->setTransparent(); AccessorCtx.reset(); @@ -4392,6 +4381,9 @@ bool Parser::parseGetSet(ParseDeclOptions Flags, // It's okay not to have a body if there's an external asm name. if (!Tok.is(tok::l_brace)) { + // Accessors don't need bodies in textual interfaces + if (SF.Kind == SourceFileKind::Interface) + continue; // _silgen_name'd accessors don't need bodies. if (!Attributes.hasAttribute()) { diagnose(Tok, diag::expected_lbrace_accessor, diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index db31376fd4768..e758b58d2cba4 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -2394,7 +2394,13 @@ printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter, Options.AccessFilter = AccessLevel::Private; Options.PrintAccess = false; Options.SkipAttributes = true; - Options.FunctionBody = [](const ValueDecl *VD) { return getCodePlaceholder(); }; + Options.FunctionBody = [&](const ValueDecl *VD, ASTPrinter &Printer) { + Printer << " {"; + Printer.printNewline(); + Printer << ExtraIndent << getCodePlaceholder(); + Printer.printNewline(); + Printer << "}"; + }; Options.setBaseType(AdopterTy); Options.CurrentModule = Adopter->getParentModule(); if (!Adopter->isExtensionContext()) { diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index dd294a09b8105..df39f92aafaed 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -2837,6 +2837,9 @@ ModuleFile::getDeclCheckedImpl(DeclID DID) { if (auto errorConvention = maybeReadForeignErrorConvention()) ctor->setForeignErrorConvention(*errorConvention); + if (auto bodyText = maybeReadInlinableBodyText()) + ctor->setBodyStringRepresentation(*bodyText); + if (isImplicit) ctor->setImplicit(); ctor->setIsObjC(isObjC); @@ -3229,6 +3232,9 @@ ModuleFile::getDeclCheckedImpl(DeclID DID) { if (auto errorConvention = maybeReadForeignErrorConvention()) fn->setForeignErrorConvention(*errorConvention); + if (auto bodyText = maybeReadInlinableBodyText()) + fn->setBodyStringRepresentation(*bodyText); + fn->setOverriddenDecl(cast_or_null(overridden.get())); if (fn->getOverriddenDecl()) AddAttribute(new (ctx) OverrideAttr(SourceLoc())); @@ -3933,6 +3939,9 @@ ModuleFile::getDeclCheckedImpl(DeclID DID) { auto dtor = createDecl(SourceLoc(), DC); declOrOffset = dtor; + if (auto bodyText = maybeReadInlinableBodyText()) + dtor->setBodyStringRepresentation(*bodyText); + configureGenericEnvironment(dtor, genericEnvID); dtor->setAccess(std::max(cast(DC)->getFormalAccess(), @@ -5341,6 +5350,25 @@ decodeRawStableForeignErrorConventionKind(uint8_t kind) { } } +Optional ModuleFile::maybeReadInlinableBodyText() { + using namespace decls_block; + + SmallVector scratch; + BCOffsetRAII restoreOffset(DeclTypeCursor); + StringRef blobData; + + auto next = DeclTypeCursor.advance(AF_DontPopBlockAtEnd); + if (next.Kind != llvm::BitstreamEntry::Record) + return None; + + unsigned recKind = DeclTypeCursor.readRecord(next.ID, scratch, &blobData); + if (recKind != INLINABLE_BODY_TEXT) + return None; + + restoreOffset.reset(); + return blobData; +} + Optional ModuleFile::maybeReadForeignErrorConvention() { using namespace decls_block; diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 6ac6b852791b0..e1d1b5d6900a6 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -1361,6 +1361,20 @@ void Serializer::writeGenericRequirements(ArrayRef requirements, } } +void Serializer::writeInlinableBodyTextIfNeeded( + const AbstractFunctionDecl *AFD) { + using namespace decls_block; + + if (AFD->getResilienceExpansion() != swift::ResilienceExpansion::Minimal) + return; + if (!AFD->hasInlinableBodyText()) return; + SmallString<128> scratch; + auto body = AFD->getInlinableBodyText(scratch); + + unsigned abbrCode = DeclTypeAbbrCodes[InlinableBodyTextLayout::Code]; + InlinableBodyTextLayout::emitRecord(Out, ScratchRecord, abbrCode, body); +} + bool Serializer::writeGenericParams(const GenericParamList *genericParams) { using namespace decls_block; @@ -3235,6 +3249,8 @@ void Serializer::writeDecl(const Decl *D) { if (auto errorConvention = fn->getForeignErrorConvention()) writeForeignErrorConvention(*errorConvention); + writeInlinableBodyTextIfNeeded(fn); + break; } @@ -3292,6 +3308,8 @@ void Serializer::writeDecl(const Decl *D) { if (auto errorConvention = fn->getForeignErrorConvention()) writeForeignErrorConvention(*errorConvention); + writeInlinableBodyTextIfNeeded(fn); + break; } @@ -3444,6 +3462,8 @@ void Serializer::writeDecl(const Decl *D) { if (auto errorConvention = ctor->getForeignErrorConvention()) writeForeignErrorConvention(*errorConvention); + + writeInlinableBodyTextIfNeeded(ctor); break; } @@ -3460,6 +3480,7 @@ void Serializer::writeDecl(const Decl *D) { dtor->isObjC(), addGenericEnvironmentRef( dtor->getGenericEnvironment())); + writeInlinableBodyTextIfNeeded(dtor); break; } @@ -4041,6 +4062,7 @@ void Serializer::writeAllDeclsAndTypes() { registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); + registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); diff --git a/lib/Serialization/Serialization.h b/lib/Serialization/Serialization.h index 92a09861ba278..ff401b43fc032 100644 --- a/lib/Serialization/Serialization.h +++ b/lib/Serialization/Serialization.h @@ -324,6 +324,10 @@ class Serializer { /// Writes a generic parameter list. bool writeGenericParams(const GenericParamList *genericParams); + /// Writes the body text of the provided funciton, if the function is + /// inlinable and has body text. + void writeInlinableBodyTextIfNeeded(const AbstractFunctionDecl *decl); + /// Writes a list of protocol conformances. void writeConformances(ArrayRef conformances, const std::array &abbrCodes); diff --git a/test/IDE/print_ast_tc_function_bodies.swift b/test/IDE/print_ast_tc_function_bodies.swift index 650383c4048b1..1d256966c3ff4 100644 --- a/test/IDE/print_ast_tc_function_bodies.swift +++ b/test/IDE/print_ast_tc_function_bodies.swift @@ -37,7 +37,7 @@ struct FooStruct { instanceVar = i + j } } -// CHECK-NEXT: {{^}} subscript(i: Int, j: Int) -> Double {{{$}} +// CHECK: {{^}} subscript(i: Int, j: Int) -> Double {{{$}} // CHECK-NEXT: {{^}} get {{{$}} // CHECK-NEXT: {{^}} return {{$}} // CHECK-NEXT: {{^}} }{{$}} @@ -139,7 +139,7 @@ class InClassVar1 { if true {} } } -// CHECK-NEXT: {{^}} var instanceVar2: Int {{{$}} +// CHECK: {{^}} var instanceVar2: Int {{{$}} // CHECK-NEXT: {{^}} get {{{$}} // CHECK-NEXT: {{^}} return {{$}} // CHECK-NEXT: {{^}} }{{$}} diff --git a/test/IDE/reconstruct_type_from_mangled_name.swift b/test/IDE/reconstruct_type_from_mangled_name.swift index bf739a038b958..5410b81226e0b 100644 --- a/test/IDE/reconstruct_type_from_mangled_name.swift +++ b/test/IDE/reconstruct_type_from_mangled_name.swift @@ -291,11 +291,11 @@ fileprivate func privateFunction(_ d: VeryPrivateData) {} struct HasSubscript { // CHECK: decl: subscript(t: Int) -> Int { get set } subscript(_ t: Int) -> Int { - // CHECK: decl: get {} for '' usr=s:14swift_ide_test12HasSubscriptVyS2icig + // CHECK: decl: get for '' usr=s:14swift_ide_test12HasSubscriptVyS2icig get { return t } - // CHECK: decl: set {} for '' usr=s:14swift_ide_test12HasSubscriptVyS2icis + // CHECK: decl: set for '' usr=s:14swift_ide_test12HasSubscriptVyS2icis set {} } } @@ -310,14 +310,14 @@ struct HasGenericSubscript { // CHECK: decl: FAILURE for 't' subscript(_ t: T) -> U { - // CHECK: decl: get {} for '' usr=s:14swift_ide_test19HasGenericSubscriptVyqd__xcluig + // CHECK: decl: get for '' usr=s:14swift_ide_test19HasGenericSubscriptVyqd__xcluig // FIXME // CHECK: dref: FAILURE for 't' get { return t as! U } - // CHECK: decl: set {} for '' usr=s:14swift_ide_test19HasGenericSubscriptVyqd__xcluis + // CHECK: decl: set for '' usr=s:14swift_ide_test19HasGenericSubscriptVyqd__xcluis set {} } } diff --git a/test/ModuleInterface/attrs.swift b/test/ModuleInterface/attrs.swift index aebf54930cdc5..4009368f8ae9f 100644 --- a/test/ModuleInterface/attrs.swift +++ b/test/ModuleInterface/attrs.swift @@ -1,7 +1,7 @@ // RUN: %target-swift-frontend -emit-interface-path %t.swiftinterface -enable-resilience -emit-module -o /dev/null %s // RUN: %FileCheck %s < %t.swiftinterface -// CHECK: @_transparent public func glass() -> Int{{$}} +// CHECK: @_transparent public func glass() -> Int { return 0 }{{$}} @_transparent public func glass() -> Int { return 0 } // CHECK: @_effects(readnone) public func illiterate(){{$}} diff --git a/test/ModuleInterface/inlinable-function.swift b/test/ModuleInterface/inlinable-function.swift new file mode 100644 index 0000000000000..86736f008c535 --- /dev/null +++ b/test/ModuleInterface/inlinable-function.swift @@ -0,0 +1,245 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-module -o %t/Test.swiftmodule -emit-interface-path %t/Test.swiftinterface -module-name Test %s +// RUN: %FileCheck %s < %t/Test.swiftinterface +// RUN: %target-swift-frontend -emit-module -o /dev/null -merge-modules %t/Test.swiftmodule -disable-objc-attr-requires-foundation-module -emit-interface-path - -module-name Test | %FileCheck %s + +// CHECK: public struct Foo : Hashable { +public struct Foo: Hashable { + // CHECK: public var inlinableGetPublicSet: [[INT:(Swift.)?Int]] { + public var inlinableGetPublicSet: Int { + // CHECK: @inlinable get { + // CHECK-NEXT: return 3 + // CHECK-NEXT: } + @inlinable + get { + return 3 + } + // CHECK-NEXT: set[[NEWVALUE:(\(newValue\))?]]{{$}} + set { + print("I am set to \(newValue)") + } + // CHECK-NEXT: {{^}} } + } + + // CHECK: public var noAccessors: [[INT]]{{$}} + public var noAccessors: Int + + // CHECK: public var hasDidSet: [[INT]] { + public var hasDidSet: Int { + // CHECK-NEXT: @_transparent get{{$}} + // CHECK-NEXT: set[[NEWVALUE]]{{$}} + // CHECK-NOT: didSet + didSet { + print("b set to \(hasDidSet)") + } + // CHECK-NEXT: {{^}} } + } + + + // CHECK: @_transparent public var transparent: [[INT]] { + // CHECK-NEXT: return 34 + // CHECK-NEXT: } + @_transparent + public var transparent: Int { + return 34 + } + + // CHECK: public var transparentSet: [[INT]] { + public var transparentSet: Int { + // CHECK-NEXT: get{{$}} + get { + return 34 + } + // CHECK-NEXT: @_transparent set[[NEWVALUE]] { + // CHECK-NOT: #if false + // CHECK-NOT: print("I should not appear") + // CHECK-NOT: #else + // CHECK-NOT: #if false + // CHECK-NOT: print("I also should not") + // CHECK-NOT: #else + // CHECK: print("I am set to \(newValue)") + // CHECK-NOT: #endif + // CHECK-NOT: #endif + // CHECK-NEXT: } + @_transparent + set { + #if false + print("I should not appear") + #else + #if false + print("I also should not") + #else + print("I am set to \(newValue)") + #endif + #endif + } + } + + // CHECK: @inlinable public var inlinableProperty: [[INT]] { + @inlinable + public var inlinableProperty: Int { + // CHECK: get { + // CHECK: return 32 + // CHECK: } + get { + return 32 + } + + // CHECK: set[[NEWVALUE]] { + // CHECK-NOT: #if true + // CHECK: print("I am set to \(newValue)") + // CHECK-NOT: #else + // CHECK-NOT: print("I should not appear") + // CHECK-NOT #endif + // CHECK: } + set { + #if true + print("I am set to \(newValue)") + #else + print("I should not appear") + #endif + } + // CHECK-NEXT: } + } + + // CHECK: @inlinable public func inlinableMethod() { + // CHECK-NOT: #if NO + // CHECK-NOT: print("Hello, world!") + // CHECK-NOT: #endif + // CHECK: print("Goodbye, world!") + // CHECK-NEXT: } + @inlinable + public func inlinableMethod() { + #if NO + print("Hello, world!") + #endif + print("Goodbye, world!") + } + + + // CHECK: @_transparent [[ATTRS:(mutating public|public mutating)]] func transparentMethod() { + // CHECK-NEXT: inlinableProperty = 4 + // CHECK-NEXT: } + @_transparent + mutating public func transparentMethod() { + inlinableProperty = 4 + } + + // CHECK: @inline(__always) [[ATTRS]] func inlineAlwaysMethod() { + // CHECK-NEXT: inlinableProperty = 4 + // CHECK-NEXT: } + @inline(__always) + mutating public func inlineAlwaysMethod() { + inlinableProperty = 4 + } + + // CHECK: public func nonInlinableMethod(){{$}} + // CHECK-NOT: print("Not inlinable") + public func nonInlinableMethod() { + print("Not inlinable") + } + + // CHECK: public subscript(i: [[INT]]) -> [[INT]] { + // CHECK-NEXT: get{{$}} + // CHECK-NEXT: @inlinable set[[NEWVALUE]] { print("set") } + // CHECK-NEXT: } + public subscript(i: Int) -> Int { + get { return 0 } + @inlinable set { print("set") } + } + + // CHECK: public subscript(j: [[INT]], k: [[INT]]) -> [[INT]] { + // CHECK-NEXT: @inlinable get { return 0 } + // CHECK-NEXT: set[[NEWVALUE]]{{$}} + // CHECK-NEXT: } + public subscript(j: Int, k: Int) -> Int { + @inlinable get { return 0 } + set { print("set") } + } + + // CHECK: @inlinable public subscript(l: [[INT]], m: [[INT]], n: [[INT]]) -> [[INT]] { + // CHECK-NEXT: get { return 0 } + // CHECK-NEXT: set[[NEWVALUE]] { print("set") } + // CHECK-NEXT: } + @inlinable + public subscript(l: Int, m: Int, n: Int) -> Int { + get { return 0 } + set { print("set") } + } + + // CHECK: public init(value: [[INT]]) { + // CHECK-NEXT: topLevelUsableFromInline() + // CHECK-NEXT: noAccessors = value + // CHECK-NEXT: hasDidSet = value + // CHECK-NEXT: } + @inlinable public init(value: Int) { + topLevelUsableFromInline() + noAccessors = value + hasDidSet = value + } + + // CHECK: public init(){{$}} + // CHECK-NOT: noAccessors = 0 + // CHECK-NOT: hasDidSet = 0 + public init() { + noAccessors = 0 + hasDidSet = 0 + } + + // CHECK: {{^}}} +} + +// CHECK-NOT: private func topLevelPrivate() +private func topLevelPrivate() { + print("Ssshhhhh") +} + +// CHECK: internal func topLevelUsableFromInline(){{$}} +@usableFromInline +internal func topLevelUsableFromInline() { + topLevelPrivate() +} + +// CHECK: @inlinable public func topLevelInlinable() { +// CHECK-NEXT: topLevelUsableFromInline() +// CHECK-NEXT: } +@inlinable public func topLevelInlinable() { + topLevelUsableFromInline() +} + +// CHECK: public class HasInlinableDeinit { +public class HasInlinableDeinit { + // CHECK: public init(){{$}} + public init() {} + + // CHECK: [[OBJC:(@objc )?]]@inlinable deinit { + // CHECK-NEXT: print("goodbye") + // CHECK-NEXT: } + @inlinable deinit { + print("goodbye") + } + + // CHECK-NEXT: } +} + +// CHECK: public class HasStandardDeinit { +public class HasStandardDeinit { + // CHECK: public init(){{$}} + public init() {} + + // CHECK: [[OBJC]]deinit{{$}} + deinit { + print("goodbye") + } + + // CHECK-NEXT: } +} + +// CHECK: public class HasDefaultDeinit { +public class HasDefaultDeinit { + // CHECK: public init(){{$}} + public init() {} + + // CHECK: [[OBJC]]deinit{{$}} + // CHECK-NEXT: } +} diff --git a/test/PrintAsObjC/availability-real-sdk.swift b/test/PrintAsObjC/availability-real-sdk.swift index 1838cce932aa0..8e9b14f976086 100644 --- a/test/PrintAsObjC/availability-real-sdk.swift +++ b/test/PrintAsObjC/availability-real-sdk.swift @@ -46,7 +46,7 @@ // CHECK-NEXT: - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER; // CHECK-NEXT: - (nonnull instancetype)initWithObjects:(id _Nonnull const * _Nullable)objects count:(NSUInteger)cnt OBJC_DESIGNATED_INITIALIZER; -// CHECK-NEXT: - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull)aDecoder OBJC_DESIGNATED_INITIALIZER; +// CHECK-NEXT: - (nullable instancetype)initWithCoder:(NSCoder * _Nonnull){{[a-zA-Z]+}} OBJC_DESIGNATED_INITIALIZER; // CHECK-NEXT: @end diff --git a/test/SourceKit/DocSupport/doc_source_file.swift.response b/test/SourceKit/DocSupport/doc_source_file.swift.response index ce73543feeda8..59e8f3a02ed77 100644 --- a/test/SourceKit/DocSupport/doc_source_file.swift.response +++ b/test/SourceKit/DocSupport/doc_source_file.swift.response @@ -2025,7 +2025,7 @@ key.usr: "s:4main2CCC4extVSivg", key.offset: 748, key.length: 11, - key.fully_annotated_decl: "get {}" + key.fully_annotated_decl: "get" } ] }, @@ -2069,14 +2069,14 @@ key.usr: "s:4main16ComputedPropertyC5valueSivg", key.offset: 853, key.length: 51, - key.fully_annotated_decl: "get {}" + key.fully_annotated_decl: "get" }, { key.kind: source.lang.swift.decl.function.accessor.setter, key.usr: "s:4main16ComputedPropertyC5valueSivs", key.offset: 910, key.length: 49, - key.fully_annotated_decl: "set(newVal) {}" + key.fully_annotated_decl: "set(newVal)" }, { key.kind: source.lang.swift.decl.var.instance, @@ -2089,7 +2089,7 @@ key.usr: "s:4main16ComputedPropertyC8readOnlySivg", key.offset: 987, key.length: 11, - key.fully_annotated_decl: "get {}" + key.fully_annotated_decl: "get" } ] }, @@ -2205,14 +2205,14 @@ key.usr: "s:4main3CC2CyS2icig", key.offset: 1162, key.length: 25, - key.fully_annotated_decl: "get {}" + key.fully_annotated_decl: "get" }, { key.kind: source.lang.swift.decl.function.accessor.setter, key.usr: "s:4main3CC2CyS2icis", key.offset: 1193, key.length: 31, - key.fully_annotated_decl: "set(vvv) {}" + key.fully_annotated_decl: "set(vvv)" } ] }, @@ -2269,7 +2269,7 @@ key.usr: "s:4main12globReadOnlyAA2S2Vvg", key.offset: 1449, key.length: 25, - key.fully_annotated_decl: "get {}" + key.fully_annotated_decl: "get" }, { key.kind: source.lang.swift.decl.function.free, @@ -2395,7 +2395,7 @@ { key.kind: source.lang.swift.decl.function.accessor.getter, key.usr: "s:4main5Prot2P1pSivg", - key.fully_annotated_decl: "get {}" + key.fully_annotated_decl: "get" }, { key.kind: source.lang.swift.decl.function.method.instance,