Canonicalize the components of a GenericFunctionType in the context of the generic signature.

This is obviously the right thing to do in terms of ensuring
that two different expressions of the same signature always result
in the same type.  It also has the pleasant side-effect of causing
the canonical function type to never be expressed in terms of type
parameters which have been equated with concrete types, which means
that various consumers that work primarily with canonical types
(such as SILGen and IRGen) no longer have to worry about such types,
at least when decomposing a generic function signature.
This commit is contained in:
John McCall
2016-06-10 15:19:30 -07:00
parent efb4b54bad
commit fdd25a3c0c
7 changed files with 102 additions and 29 deletions

View File

@@ -3050,14 +3050,23 @@ GenericFunctionType::get(GenericSignature *sig,
// Do we already have this generic function type?
void *insertPos;
if (auto result
= ctx.Impl.GenericFunctionTypes.FindNodeOrInsertPos(id, insertPos))
= ctx.Impl.GenericFunctionTypes.FindNodeOrInsertPos(id, insertPos)) {
return result;
}
// We have to construct this generic function type. Determine whether
// it's canonical.
// it's canonical. Unfortunately, isCanonicalTypeInContext can cause
// new GenericFunctionTypes to be created and thus invalidate our insertion
// point.
auto &moduleForCanonicality = *ctx.TheBuiltinModule;
bool isCanonical = sig->isCanonical()
&& input->isCanonical()
&& output->isCanonical();
&& sig->isCanonicalTypeInContext(input, moduleForCanonicality)
&& sig->isCanonicalTypeInContext(output, moduleForCanonicality);
if (auto result
= ctx.Impl.GenericFunctionTypes.FindNodeOrInsertPos(id, insertPos)) {
return result;
}
// Allocate storage for the object.
void *mem = ctx.Allocate(sizeof(GenericFunctionType),
@@ -3067,6 +3076,7 @@ GenericFunctionType::get(GenericSignature *sig,
auto result = new (mem) GenericFunctionType(sig, input, output, info,
isCanonical ? &ctx : nullptr,
properties);
ctx.Impl.GenericFunctionTypes.InsertNode(result, insertPos);
return result;
}