[serialization] Handle PolymorphicFunctionTypes more carefully.

PolymorphicFunctionTypes are built on GenericParamLists, which are
owned by decls that introduce generic parameters. This made deserializing
them a pain, because they /cannot/ be recreated in isolation -- the decl
provides some context. Rather than try to come up with a very generic way
to serialize these, this patch just records the GenericParamList of every
decl, allowing the type to be serialized with a reference to the decl
instead of to the param list. Deserialization can then just pluck the list
back out of the decl.

According to Doug and Joe, PolymorphicFunctionType's due for a refresh
anyway, so this kind of hackery / kludgery is acceptable.

With this change, we can now handle generic structs and generic functions
inside generic structs.

Swift SVN r6032
This commit is contained in:
Jordan Rose
2013-07-06 00:20:04 +00:00
parent d8414ee000
commit aa2d1b2a64
3 changed files with 128 additions and 42 deletions

View File

@@ -462,19 +462,6 @@ static void lookupImmediateDecls(DeclContext *DC, Identifier name,
}
}
/// Creates a polymorphic function type based on the given (monomorphic) type.
PolymorphicFunctionType *
getPolymorphicFunctionType(ASTContext &Ctx, FunctionType *originalTy,
GenericParamList *paramList) {
assert(paramList && "cannot have a polymorphic function type without params");
return PolymorphicFunctionType::get(originalTy->getInput(),
originalTy->getResult(),
paramList,
originalTy->isThin(),
originalTy->getAbstractCC(),
Ctx);
}
Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
if (DID == 0)
return nullptr;
@@ -621,13 +608,10 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
assert(args && "missing arguments for constructor");
ctor->setArguments(args);
Type signature = getType(signatureID);
if (auto contextGenericParams = ctor->getGenericParamsOfContext()) {
signature = getPolymorphicFunctionType(ctx,
signature->castTo<FunctionType>(),
contextGenericParams);
}
ctor->setType(signature);
// This must be set after recording the constructor in the map.
// A polymorphic constructor type needs to refer to the constructor to get
// its generic parameters.
ctor->setType(getType(signatureID));
if (isImplicit)
ctor->setImplicit();
@@ -700,27 +684,23 @@ Decl *ModuleFile::getDecl(DeclID DID, Optional<DeclContext *> ForcedContext) {
// DeclContext for now.
GenericParamList *genericParams = maybeReadGenericParams(DC);
auto fn = new (ctx) FuncDecl(SourceLoc(), SourceLoc(),
getIdentifier(nameID), SourceLoc(),
genericParams, /*type=*/nullptr,
/*body=*/nullptr, DC);
declOrOffset = fn;
AnyFunctionType *signature;
{
BCOffsetRAII restoreOffset(DeclTypeCursor);
signature = getType(signatureID)->castTo<FunctionType>();
signature = getType(signatureID)->castTo<AnyFunctionType>();
auto contextGenericParams = genericParams;
if (!genericParams)
genericParams = DC->getGenericParamsOfContext();
if (contextGenericParams)
signature = getPolymorphicFunctionType(ctx,
cast<FunctionType>(signature),
contextGenericParams);
// This must be set after recording the constructor in the map.
// A polymorphic constructor type needs to refer to the constructor to get
// its generic parameters.
fn->setType(signature);
}
auto fn = new (ctx) FuncDecl(SourceLoc(), SourceLoc(),
getIdentifier(nameID), SourceLoc(),
genericParams, signature,
/*body=*/nullptr, DC);
declOrOffset = fn;
SmallVector<Pattern *, 16> patternBuf;
while (Pattern *pattern = maybeReadPattern())
patternBuf.push_back(pattern);
@@ -1260,6 +1240,55 @@ Type ModuleFile::getType(TypeID TID) {
break;
}
case decls_block::POLYMORPHIC_FUNCTION_TYPE: {
TypeID inputID;
TypeID resultID;
DeclID genericContextID;
uint8_t rawCallingConvention;
bool thin;
decls_block::PolymorphicFunctionTypeLayout::readRecord(scratch,
inputID,
resultID,
genericContextID,
rawCallingConvention,
thin);
auto callingConvention = getActualCC(rawCallingConvention);
if (!callingConvention.hasValue()) {
error();
return nullptr;
}
Decl *genericContext = getDecl(genericContextID);
assert(genericContext && "loading PolymorphicFunctionType before its decl");
GenericParamList *paramList = nullptr;
switch (genericContext->getKind()) {
case DeclKind::Constructor:
paramList = cast<ConstructorDecl>(genericContext)->getGenericParams();
break;
case DeclKind::Func:
paramList = cast<FuncDecl>(genericContext)->getGenericParams();
break;
case DeclKind::Class:
case DeclKind::Struct:
case DeclKind::OneOf:
paramList = cast<NominalTypeDecl>(genericContext)->getGenericParams();
break;
default:
break;
}
assert(paramList && "missing generic params for polymorphic function");
typeOrOffset = PolymorphicFunctionType::get(getType(inputID),
getType(resultID),
paramList,
thin,
callingConvention.getValue(),
ctx);
break;
}
default:
// We don't know how to deserialize this kind of type.
error();