diff --git a/lib/Serialization/ModuleFile.cpp b/lib/Serialization/ModuleFile.cpp index dfe2e5e769c..1f51ae8b928 100644 --- a/lib/Serialization/ModuleFile.cpp +++ b/lib/Serialization/ModuleFile.cpp @@ -896,6 +896,71 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional ForcedContext) { break; } + case decls_block::ONEOF_DECL: { + IdentifierID nameID; + DeclID contextID; + bool isImplicit; + ArrayRef inheritedIDs; + + decls_block::OneOfLayout::readRecord(scratch, nameID, contextID, + isImplicit, inheritedIDs); + + MutableArrayRef inherited; + DeclContext *DC; + { + BCOffsetRAII restoreOffset(DeclTypeCursor); + inherited = getTypes(inheritedIDs); + DC = getDeclContext(contextID); + } + + auto genericParams = maybeReadGenericParams(DC); + + auto oneOf = new (ctx) OneOfDecl(SourceLoc(), getIdentifier(nameID), + SourceLoc(), inherited, + genericParams, DC); + declOrOffset = oneOf; + + if (isImplicit) + oneOf->setImplicit(); + if (genericParams) + for (auto &genericParam : *oneOf->getGenericParams()) + genericParam.getAsTypeParam()->setDeclContext(oneOf); + + SmallVector conformanceBuf; + while (ProtocolConformance *conformance = maybeReadConformance()) + conformanceBuf.push_back(conformance); + oneOf->setConformances(ctx.AllocateCopy(conformanceBuf)); + + auto members = readMembers(); + assert(members.hasValue() && "could not read oneof members"); + oneOf->setMembers(members.getValue(), SourceRange()); + + break; + } + + case decls_block::ONEOF_ELEMENT_DECL: { + IdentifierID nameID; + DeclID contextID; + TypeID argTypeID, ctorTypeID; + bool isImplicit; + + decls_block::OneOfElementLayout::readRecord(scratch, nameID, contextID, + argTypeID, ctorTypeID, + isImplicit); + + auto argTy = getType(argTypeID); + auto elem = new (ctx) OneOfElementDecl(SourceLoc(), getIdentifier(nameID), + TypeLoc::withoutLoc(argTy), + getDeclContext(contextID)); + declOrOffset = elem; + + elem->setType(getType(ctorTypeID)); + if (isImplicit) + elem->setImplicit(); + + break; + } + case decls_block::XREF: { uint8_t kind; TypeID expectedTypeID; diff --git a/lib/Serialization/ModuleFormat.h b/lib/Serialization/ModuleFormat.h index 16ca6391144..8aad4536634 100644 --- a/lib/Serialization/ModuleFormat.h +++ b/lib/Serialization/ModuleFormat.h @@ -237,6 +237,8 @@ namespace decls_block { POSTFIX_OPERATOR_DECL, INFIX_OPERATOR_DECL, CLASS_DECL, + ONEOF_DECL, + ONEOF_ELEMENT_DECL, PAREN_PATTERN = 200, TUPLE_PATTERN, @@ -406,6 +408,7 @@ namespace decls_block { using StructLayout = NominalLayout; using ProtocolLayout = NominalLayout; using ClassLayout = NominalLayout; + using OneOfLayout = NominalLayout; using ConstructorLayout = BCRecordLayout< CONSTRUCTOR_DECL, @@ -466,6 +469,15 @@ namespace decls_block { BCFixed<8> // precedence >; + using OneOfElementLayout = BCRecordLayout< + ONEOF_ELEMENT_DECL, + IdentifierIDField, // name + DeclIDField, // context decl + TypeIDField, // argument type + TypeIDField, // constructor type + BCFixed<1> // implicit? + >; + using ParenPatternLayout = BCRecordLayout< PAREN_PATTERN diff --git a/lib/Serialization/Serialization.cpp b/lib/Serialization/Serialization.cpp index 66f9fe44eba..fe95764a95d 100644 --- a/lib/Serialization/Serialization.cpp +++ b/lib/Serialization/Serialization.cpp @@ -424,6 +424,8 @@ void Serializer::writeBlockInfoBlock() { RECORD(decls_block, POSTFIX_OPERATOR_DECL); RECORD(decls_block, INFIX_OPERATOR_DECL); RECORD(decls_block, CLASS_DECL); + RECORD(decls_block, ONEOF_DECL); + RECORD(decls_block, ONEOF_ELEMENT_DECL); RECORD(decls_block, PAREN_PATTERN); RECORD(decls_block, TUPLE_PATTERN); @@ -888,8 +890,31 @@ bool Serializer::writeDecl(const Decl *D) { return true; } - case DeclKind::OneOf: - return false; + case DeclKind::OneOf: { + auto oneOf = cast(D); + + // FIXME: Handle attributes. + if (!oneOf->getAttrs().empty()) + return false; + + const Decl *DC = getDeclForContext(oneOf->getDeclContext()); + + SmallVector inherited; + for (auto parent : oneOf->getInherited()) + inherited.push_back(addTypeRef(parent.getType())); + + unsigned abbrCode = DeclTypeAbbrCodes[OneOfLayout::Code]; + OneOfLayout::emitRecord(Out, ScratchRecord, abbrCode, + addIdentifierRef(oneOf->getName()), + addDeclRef(DC), + oneOf->isImplicit(), + inherited); + + writeGenericParams(oneOf->getGenericParams()); + writeConformances(oneOf->getConformances()); + writeMembers(oneOf); + return true; + } case DeclKind::Class: { auto theClass = cast(D); @@ -1006,7 +1031,25 @@ bool Serializer::writeDecl(const Decl *D) { return true; } - case DeclKind::OneOfElement: + case DeclKind::OneOfElement: { + auto elem = cast(D); + + // FIXME: Handle attributes. + if (!elem->getAttrs().empty()) + return false; + + const Decl *DC = getDeclForContext(elem->getDeclContext()); + + unsigned abbrCode = DeclTypeAbbrCodes[OneOfElementLayout::Code]; + OneOfElementLayout::emitRecord(Out, ScratchRecord, abbrCode, + addIdentifierRef(elem->getName()), + addDeclRef(DC), + addTypeRef(elem->getArgumentType()), + addTypeRef(elem->getType()), + elem->isImplicit()); + return true; + } + case DeclKind::Subscript: return false; @@ -1370,6 +1413,8 @@ void Serializer::writeAllDeclsAndTypes() { registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); + registerDeclTypeAbbr(); + registerDeclTypeAbbr(); registerDeclTypeAbbr(); registerDeclTypeAbbr(); diff --git a/test/Serialization/Inputs/def_oneof.swift b/test/Serialization/Inputs/def_oneof.swift new file mode 100644 index 00000000000..d3afb843137 --- /dev/null +++ b/test/Serialization/Inputs/def_oneof.swift @@ -0,0 +1,30 @@ +oneof Basic { + Untyped, + HasType : Int + + constructor() { + this = .Untyped + } + func doSomething() {} +} + +oneof Generic { + Left : A, + Right : A +} + + +protocol Computable { + func compute() +} + +oneof Lazy : Computable { + Thunk : () -> T, + Value : T + + func compute() { +// if (this ~= .Thunk(var fn)) { +// this = .Value(fn()) +// } + } +} diff --git a/test/Serialization/oneof.swift b/test/Serialization/oneof.swift new file mode 100644 index 00000000000..2cff408e368 --- /dev/null +++ b/test/Serialization/oneof.swift @@ -0,0 +1,23 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: %swift -emit-module -o %t/def_oneof.swiftmodule %S/Inputs/def_oneof.swift +// RUN: llvm-bcanalyzer %t/def_oneof.swiftmodule | FileCheck %s +// RUN: %swift -parse -I=%t %s -o /dev/null + +// CHECK-NOT: FALL_BACK_TO_TRANSLATION_UNIT + +import def_oneof + +var a : Basic +a = .Untyped +a.doSomething() +a = .HasType(4) +a.doSomething() + +var g = Generic.Left(false) +g = .Right(true) + +var lazy = Lazy.Thunk({ 42 }) +var comp : Computable = lazy +comp.compute() +lazy.compute()