mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Refactor _gatherWrittenGenericParameters
Fix some bugs
This commit is contained in:
@@ -266,25 +266,6 @@ _buildDemanglingForMetadataPack(MetadataPackPointer pack, size_t count,
|
||||
return node;
|
||||
}
|
||||
|
||||
/// Demangle the given type name to a generic parameter reference, which
|
||||
/// will be returned as (depth, index).
|
||||
static llvm::Optional<std::pair<unsigned, unsigned>>
|
||||
demangleToGenericParamRef(StringRef typeName) {
|
||||
StackAllocatedDemangler<1024> demangler;
|
||||
NodePointer node = demangler.demangleType(typeName);
|
||||
if (!node)
|
||||
return llvm::None;
|
||||
|
||||
// Find the flat index that the right-hand side refers to.
|
||||
if (node->getKind() == Demangle::Node::Kind::Type)
|
||||
node = node->getChild(0);
|
||||
if (node->getKind() != Demangle::Node::Kind::DependentGenericParamType)
|
||||
return llvm::None;
|
||||
|
||||
return std::pair<unsigned, unsigned>(node->getChild(0)->getIndex(),
|
||||
node->getChild(1)->getIndex());
|
||||
}
|
||||
|
||||
/// Build an array of demangling trees for each generic argument of the given
|
||||
/// type metadata.
|
||||
///
|
||||
@@ -314,144 +295,74 @@ static bool _buildDemanglingForGenericArgs(
|
||||
return true;
|
||||
|
||||
auto genericArgs = description->getGenericArguments(type);
|
||||
|
||||
auto packHeader = generics->getGenericPackShapeHeader();
|
||||
auto packDescriptors = generics->getGenericPackShapeDescriptors();
|
||||
|
||||
unsigned packIndex = 0;
|
||||
unsigned argIndex = packHeader.NumShapeClasses;
|
||||
llvm::SmallVector<MetadataOrPack> allGenericArgs;
|
||||
|
||||
bool missingWrittenArguments = false;
|
||||
auto numKeyArgs = 0;
|
||||
for (auto param : generics->getGenericParams()) {
|
||||
if (param.hasKeyArgument()) {
|
||||
numKeyArgs += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// _gatherWrittenGenericParameters expects to immediately read key generic
|
||||
// arguments, so skip past the shape classes if we have any.
|
||||
auto nonShapeClassGenericArgs = genericArgs + packHeader.NumShapeClasses;
|
||||
|
||||
llvm::ArrayRef<const void *> genericArgsRef(
|
||||
reinterpret_cast<const void * const *>(nonShapeClassGenericArgs), numKeyArgs);
|
||||
|
||||
if (!_gatherWrittenGenericParameters(description, genericArgsRef,
|
||||
allGenericArgs, Dem)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto argIndex = 0;
|
||||
auto packIndex = 0;
|
||||
|
||||
for (auto param : generics->getGenericParams()) {
|
||||
auto genericArg = allGenericArgs[argIndex];
|
||||
|
||||
switch (param.getKind()) {
|
||||
case GenericParamKind::Type:
|
||||
// The type should have a key argument unless it's been same-typed to
|
||||
// another type.
|
||||
if (param.hasKeyArgument()) {
|
||||
auto genericArg = reinterpret_cast<const Metadata *>(genericArgs[argIndex]);
|
||||
case GenericParamKind::Type: {
|
||||
auto metadata = genericArg.getMetadata();
|
||||
auto genericArgDemangling =
|
||||
_swift_buildDemanglingForMetadata(metadata, Dem);
|
||||
|
||||
auto genericArgDemangling =
|
||||
_swift_buildDemanglingForMetadata(genericArg, Dem);
|
||||
if (!genericArgDemangling)
|
||||
return false;
|
||||
demangledGenerics.push_back(genericArgDemangling);
|
||||
|
||||
++argIndex;
|
||||
} else {
|
||||
// Leave a gap for us to fill in by looking at same-type requirements.
|
||||
demangledGenerics.push_back(nullptr);
|
||||
missingWrittenArguments = true;
|
||||
if (!genericArgDemangling) {
|
||||
return false;
|
||||
}
|
||||
|
||||
demangledGenerics.push_back(genericArgDemangling);
|
||||
break;
|
||||
}
|
||||
|
||||
case GenericParamKind::TypePack:
|
||||
if (param.hasKeyArgument()) {
|
||||
auto packDescriptor = packDescriptors[packIndex];
|
||||
assert(packDescriptor.Kind == GenericPackKind::Metadata);
|
||||
assert(packDescriptor.ShapeClass < packHeader.NumShapeClasses);
|
||||
assert(packDescriptor.Index == argIndex);
|
||||
case GenericParamKind::TypePack: {
|
||||
auto packDescriptor = packDescriptors[packIndex];
|
||||
assert(packDescriptor.Kind == GenericPackKind::Metadata);
|
||||
assert(packDescriptor.ShapeClass < packHeader.NumShapeClasses);
|
||||
assert(packDescriptor.Index == argIndex);
|
||||
|
||||
MetadataPackPointer pack(genericArgs[argIndex]);
|
||||
size_t count = reinterpret_cast<size_t>(genericArgs[packDescriptor.ShapeClass]);
|
||||
MetadataPackPointer pack(genericArg.getMetadataPack());
|
||||
size_t count = reinterpret_cast<size_t>(genericArgs[packDescriptor.ShapeClass]);
|
||||
|
||||
auto genericArgDemangling = _buildDemanglingForMetadataPack(pack, count, Dem);
|
||||
if (genericArgDemangling == nullptr)
|
||||
return false;
|
||||
|
||||
demangledGenerics.push_back(genericArgDemangling);
|
||||
|
||||
++packIndex;
|
||||
++argIndex;
|
||||
} else {
|
||||
// Leave a gap for us to fill in by looking at same-type requirements.
|
||||
demangledGenerics.push_back(nullptr);
|
||||
missingWrittenArguments = true;
|
||||
}
|
||||
auto genericArgDemangling = _buildDemanglingForMetadataPack(pack, count, Dem);
|
||||
if (genericArgDemangling == nullptr)
|
||||
return false;
|
||||
|
||||
demangledGenerics.push_back(genericArgDemangling);
|
||||
packIndex += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// We don't know about this kind of parameter.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no follow-up work to do, we're done.
|
||||
if (!missingWrittenArguments)
|
||||
return true;
|
||||
|
||||
// We have generic arguments that would be written, but have been
|
||||
// canonicalized away. Use same-type requirements to reconstitute them.
|
||||
SubstGenericParametersFromMetadata substitutions(
|
||||
description, reinterpret_cast<const void * const *>(genericArgs));
|
||||
|
||||
// Retrieve the mapping information needed for depth/index -> flat index.
|
||||
llvm::SmallVector<unsigned, 8> genericParamCounts;
|
||||
(void)_gatherGenericParameterCounts(description, genericParamCounts, Dem);
|
||||
|
||||
// Walk through the generic requirements to evaluate same-type
|
||||
// constraints that are needed to fill in missing generic arguments.
|
||||
for (const auto &req : generics->getGenericRequirements()) {
|
||||
// We only care about same-type constraints.
|
||||
if (req.Flags.getKind() != GenericRequirementKind::SameType)
|
||||
continue;
|
||||
|
||||
auto lhsParam = demangleToGenericParamRef(req.getParam());
|
||||
if (!lhsParam)
|
||||
continue;
|
||||
|
||||
assert(!req.Flags.isPackRequirement() &&
|
||||
"Pack requirements not supported here yet");
|
||||
|
||||
// If we don't yet have an argument for this parameter, it's a
|
||||
// same-type-to-concrete constraint.
|
||||
auto lhsFlatIndex =
|
||||
_depthIndexToFlatIndex(lhsParam->first, lhsParam->second,
|
||||
genericParamCounts);
|
||||
if (!lhsFlatIndex || *lhsFlatIndex >= demangledGenerics.size())
|
||||
return false;
|
||||
|
||||
if (!demangledGenerics[*lhsFlatIndex]) {
|
||||
// Substitute into the right-hand side.
|
||||
auto *genericArg =
|
||||
swift_getTypeByMangledName(MetadataState::Abstract,
|
||||
req.getMangledTypeName(),
|
||||
reinterpret_cast<const void * const *>(genericArgs),
|
||||
[&substitutions](unsigned depth, unsigned index) {
|
||||
// FIXME: Variadic generics
|
||||
return substitutions.getMetadata(depth, index).getMetadata();
|
||||
},
|
||||
[&substitutions](const Metadata *type, unsigned index) {
|
||||
return substitutions.getWitnessTable(type, index);
|
||||
}).getType().getMetadata();
|
||||
if (!genericArg)
|
||||
return false;
|
||||
|
||||
demangledGenerics[*lhsFlatIndex] =
|
||||
_swift_buildDemanglingForMetadata(genericArg, Dem);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we do have an argument for this parameter, it might be that
|
||||
// the right-hand side is itself a generic parameter, which means
|
||||
// we have a same-type constraint A == B where A is already filled in.
|
||||
auto rhsParam = demangleToGenericParamRef(req.getMangledTypeName());
|
||||
if (!rhsParam)
|
||||
return false;
|
||||
|
||||
auto rhsFlatIndex =
|
||||
_depthIndexToFlatIndex(rhsParam->first, rhsParam->second,
|
||||
genericParamCounts);
|
||||
if (!rhsFlatIndex || *rhsFlatIndex >= demangledGenerics.size())
|
||||
return false;
|
||||
|
||||
if (demangledGenerics[*rhsFlatIndex] || !demangledGenerics[*lhsFlatIndex])
|
||||
return false;
|
||||
|
||||
demangledGenerics[*rhsFlatIndex] = demangledGenerics[*lhsFlatIndex];
|
||||
argIndex += 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -468,9 +379,14 @@ _buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) {
|
||||
switch (type->getKind()) {
|
||||
case MetadataKind::Class: {
|
||||
auto classType = static_cast<const ClassMetadata *>(type);
|
||||
|
||||
if (!classType->isTypeMetadata()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
// Peek through artificial subclasses.
|
||||
while (classType->isTypeMetadata() && classType->isArtificialSubclass())
|
||||
while (classType->isArtificialSubclass())
|
||||
classType = classType->Superclass;
|
||||
#endif
|
||||
description = classType->getDescription();
|
||||
|
||||
@@ -1196,11 +1196,6 @@ public:
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
static void _gatherWrittenGenericArgs(
|
||||
const Metadata *metadata, const TypeContextDescriptor *description,
|
||||
llvm::SmallVectorImpl<MetadataOrPack> &allGenericArgs,
|
||||
Demangler &BorrowFrom);
|
||||
|
||||
static llvm::Optional<TypeLookupError>
|
||||
_gatherGenericParameters(const ContextDescriptor *context,
|
||||
llvm::ArrayRef<MetadataOrPack> genericArgs,
|
||||
@@ -1278,10 +1273,41 @@ _gatherGenericParameters(const ContextDescriptor *context,
|
||||
// Compute the set of generic arguments "as written".
|
||||
llvm::SmallVector<MetadataOrPack, 8> allGenericArgs;
|
||||
|
||||
// If we have a parent, gather it's generic arguments "as written".
|
||||
if (parent) {
|
||||
_gatherWrittenGenericArgs(parent, parent->getTypeContextDescriptor(),
|
||||
allGenericArgs, demangler);
|
||||
auto generics = context->getGenericContext();
|
||||
assert(generics);
|
||||
|
||||
// If we have a parent, gather it's generic arguments "as written". If our
|
||||
// parent is not generic, there are no generic arguments to add.
|
||||
if (parent && parent->getTypeContextDescriptor() &&
|
||||
parent->getTypeContextDescriptor()->getGenericContext()) {
|
||||
auto parentDescriptor = parent->getTypeContextDescriptor();
|
||||
auto parentGenerics = parentDescriptor->getGenericContext();
|
||||
auto packHeader = parentGenerics->getGenericPackShapeHeader();
|
||||
|
||||
// _gatherWrittenGenericParameters expects to immediately read key generic
|
||||
// arguments, so skip past the shape classes if we have any.
|
||||
auto nonShapeClassGenericArgs = parent->getGenericArgs() + packHeader.NumShapeClasses;
|
||||
|
||||
auto numKeyArgs = 0;
|
||||
for (auto param : parentGenerics->getGenericParams()) {
|
||||
if (param.hasKeyArgument()) {
|
||||
numKeyArgs += 1;
|
||||
}
|
||||
}
|
||||
|
||||
llvm::ArrayRef<const void *> genericArgsRef(
|
||||
reinterpret_cast<const void * const *>(nonShapeClassGenericArgs),
|
||||
numKeyArgs);
|
||||
|
||||
if (!_gatherWrittenGenericParameters(parentDescriptor,
|
||||
genericArgsRef,
|
||||
allGenericArgs, demangler)) {
|
||||
auto commonString = makeCommonErrorStringGetter();
|
||||
return TypeLookupError([=] {
|
||||
return commonString() + "failed to get parent context's written" +
|
||||
" generic arguments";
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add the generic arguments we were given.
|
||||
@@ -1290,8 +1316,6 @@ _gatherGenericParameters(const ContextDescriptor *context,
|
||||
|
||||
// Copy the generic arguments needed for metadata from the generic
|
||||
// arguments "as written".
|
||||
auto generics = context->getGenericContext();
|
||||
assert(generics);
|
||||
{
|
||||
// Add a placeholder length for each shape class.
|
||||
auto packShapeHeader = generics->getGenericPackShapeHeader();
|
||||
@@ -2878,12 +2902,21 @@ const Metadata *swift::_swift_instantiateCheckedGenericMetadata(
|
||||
|
||||
DemanglerForRuntimeTypeResolution<StackAllocatedDemangler<2048>> demangler;
|
||||
|
||||
llvm::ArrayRef<MetadataOrPack> genericArgsRef(
|
||||
reinterpret_cast<const MetadataOrPack *>(genericArgs), genericArgsSize);
|
||||
// _instantiateCheckedGenericMetadata expects generic args to NOT begin with
|
||||
// shape classes.
|
||||
llvm::ArrayRef<const void *> genericArgsRef(genericArgs, genericArgsSize);
|
||||
llvm::SmallVector<MetadataOrPack, 8> writtenGenericArgs;
|
||||
|
||||
// If we fail to fill in all of the generic parameters, just fail.
|
||||
if (!_gatherWrittenGenericParameters(context, genericArgsRef,
|
||||
writtenGenericArgs, demangler)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
llvm::SmallVector<unsigned, 8> genericParamCounts;
|
||||
llvm::SmallVector<const void *, 8> allGenericArgs;
|
||||
|
||||
auto result = _gatherGenericParameters(context, genericArgsRef,
|
||||
auto result = _gatherGenericParameters(context, writtenGenericArgs,
|
||||
/* parent */ nullptr,
|
||||
genericParamCounts, allGenericArgs,
|
||||
demangler);
|
||||
@@ -3232,76 +3265,72 @@ demangleToGenericParamRef(StringRef typeName) {
|
||||
node->getChild(1)->getIndex());
|
||||
}
|
||||
|
||||
static void _gatherWrittenGenericArgs(
|
||||
const Metadata *metadata, const TypeContextDescriptor *description,
|
||||
llvm::SmallVectorImpl<MetadataOrPack> &allGenericArgs,
|
||||
Demangler &BorrowFrom) {
|
||||
if (!description)
|
||||
return;
|
||||
auto generics = description->getGenericContext();
|
||||
if (!generics)
|
||||
return;
|
||||
bool swift::_gatherWrittenGenericParameters(
|
||||
const TypeContextDescriptor *descriptor,
|
||||
llvm::ArrayRef<const void *> keyArgs,
|
||||
llvm::SmallVectorImpl<MetadataOrPack> &genericArgs,
|
||||
Demangle::Demangler &Dem) {
|
||||
if (!descriptor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto genericContext = descriptor->getGenericContext();
|
||||
|
||||
// If the type itself is not generic, then we're done.
|
||||
if (!genericContext) {
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned argIndex = 0;
|
||||
bool missingWrittenArguments = false;
|
||||
auto genericArgs = description->getGenericArguments(metadata);
|
||||
for (auto param : generics->getGenericParams()) {
|
||||
|
||||
for (auto param : genericContext->getGenericParams()) {
|
||||
// The type should have a key argument unless it's been same-typed to
|
||||
// another type.
|
||||
if (param.hasKeyArgument()) {
|
||||
genericArgs.push_back(MetadataOrPack(keyArgs[argIndex]));
|
||||
|
||||
argIndex += 1;
|
||||
} else {
|
||||
// Leave a gap for us to fill in by looking at same-type requirements.
|
||||
genericArgs.push_back(MetadataOrPack());
|
||||
missingWrittenArguments = true;
|
||||
}
|
||||
|
||||
switch (param.getKind()) {
|
||||
case GenericParamKind::Type:
|
||||
// The type should have a key argument unless it's been same-typed to
|
||||
// another type.
|
||||
if (param.hasKeyArgument()) {
|
||||
auto genericArg = *genericArgs++;
|
||||
allGenericArgs.push_back(MetadataOrPack(genericArg));
|
||||
} else {
|
||||
// Leave a gap for us to fill in by looking at same type info.
|
||||
allGenericArgs.push_back(MetadataOrPack());
|
||||
missingWrittenArguments = true;
|
||||
}
|
||||
|
||||
// Already handled by the above.
|
||||
break;
|
||||
|
||||
case GenericParamKind::TypePack:
|
||||
// The type should have a key argument unless it's been same-typed to
|
||||
// another type.
|
||||
if (param.hasKeyArgument()) {
|
||||
auto genericArg = reinterpret_cast<const Metadata * const *>(*genericArgs++);
|
||||
MetadataPackPointer pack(genericArg);
|
||||
allGenericArgs.push_back(MetadataOrPack(pack));
|
||||
} else {
|
||||
// Leave a gap for us to fill in by looking at same type info.
|
||||
allGenericArgs.push_back(MetadataOrPack());
|
||||
missingWrittenArguments = true;
|
||||
}
|
||||
|
||||
// Already handled by the above.
|
||||
break;
|
||||
|
||||
default:
|
||||
// We don't know about this kind of parameter. Create placeholders where
|
||||
// needed.
|
||||
if (param.hasKeyArgument()) {
|
||||
allGenericArgs.push_back(MetadataOrPack());
|
||||
++genericArgs;
|
||||
}
|
||||
|
||||
break;
|
||||
// We don't know about this kind of parameter.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no follow-up work to do, we're done.
|
||||
if (!missingWrittenArguments)
|
||||
return;
|
||||
return true;
|
||||
|
||||
// We have generic arguments that would be written, but have been
|
||||
// canonicalized away. Use same-type requirements to reconstitute them.
|
||||
|
||||
// Retrieve the mapping information needed for depth/index -> flat index.
|
||||
llvm::SmallVector<unsigned, 8> genericParamCounts;
|
||||
(void)_gatherGenericParameterCounts(description, genericParamCounts,
|
||||
BorrowFrom);
|
||||
(void)_gatherGenericParameterCounts(descriptor, genericParamCounts, Dem);
|
||||
|
||||
SubstGenericParametersFromWrittenArgs substitutions(genericArgs,
|
||||
genericParamCounts);
|
||||
|
||||
bool needToCheckAssociatedSameTypes = false;
|
||||
|
||||
// Walk through the generic requirements to evaluate same-type
|
||||
// constraints that are needed to fill in missing generic arguments.
|
||||
for (const auto &req : generics->getGenericRequirements()) {
|
||||
for (const auto &req : genericContext->getGenericRequirements()) {
|
||||
// We only care about same-type constraints.
|
||||
if (req.Flags.getKind() != GenericRequirementKind::SameType)
|
||||
continue;
|
||||
@@ -3318,23 +3347,25 @@ static void _gatherWrittenGenericArgs(
|
||||
auto lhsFlatIndex =
|
||||
_depthIndexToFlatIndex(lhsParam->first, lhsParam->second,
|
||||
genericParamCounts);
|
||||
if (!lhsFlatIndex || *lhsFlatIndex >= allGenericArgs.size())
|
||||
continue;
|
||||
if (!lhsFlatIndex || *lhsFlatIndex >= genericArgs.size())
|
||||
return false;
|
||||
|
||||
if (!allGenericArgs[*lhsFlatIndex]) {
|
||||
if (!genericArgs[*lhsFlatIndex]) {
|
||||
// Substitute into the right-hand side.
|
||||
SubstGenericParametersFromWrittenArgs substitutions(allGenericArgs,
|
||||
genericParamCounts);
|
||||
allGenericArgs[*lhsFlatIndex] =
|
||||
MetadataOrPack(swift_getTypeByMangledName(MetadataState::Abstract,
|
||||
auto *genericArg =
|
||||
swift_getTypeByMangledName(MetadataState::Abstract,
|
||||
req.getMangledTypeName(),
|
||||
(const void * const *)allGenericArgs.data(),
|
||||
keyArgs.data(),
|
||||
[&substitutions](unsigned depth, unsigned index) {
|
||||
return substitutions.getMetadata(depth, index).Ptr;
|
||||
},
|
||||
[&substitutions](const Metadata *type, unsigned index) {
|
||||
return substitutions.getWitnessTable(type, index);
|
||||
}).getType().getMetadata());
|
||||
}).getType().getMetadata();
|
||||
if (!genericArg)
|
||||
return false;
|
||||
|
||||
genericArgs[*lhsFlatIndex] = MetadataOrPack(genericArg);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3342,20 +3373,80 @@ static void _gatherWrittenGenericArgs(
|
||||
// the right-hand side is itself a generic parameter, which means
|
||||
// we have a same-type constraint A == B where A is already filled in.
|
||||
auto rhsParam = demangleToGenericParamRef(req.getMangledTypeName());
|
||||
if (!rhsParam)
|
||||
|
||||
// If the rhs parameter is not a generic parameter itself with
|
||||
// (depth, index), it could potentially be some associated type. Check it
|
||||
// again later once we've found all of the other same types.
|
||||
if (!rhsParam) {
|
||||
needToCheckAssociatedSameTypes = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto rhsFlatIndex =
|
||||
_depthIndexToFlatIndex(rhsParam->first, rhsParam->second,
|
||||
genericParamCounts);
|
||||
if (!rhsFlatIndex || *rhsFlatIndex >= allGenericArgs.size())
|
||||
continue;
|
||||
if (!rhsFlatIndex || *rhsFlatIndex >= genericArgs.size())
|
||||
return false;
|
||||
|
||||
if (allGenericArgs[*rhsFlatIndex] || !allGenericArgs[*lhsFlatIndex])
|
||||
continue;
|
||||
if (genericArgs[*rhsFlatIndex] || !genericArgs[*lhsFlatIndex])
|
||||
return false;
|
||||
|
||||
allGenericArgs[*rhsFlatIndex] = allGenericArgs[*lhsFlatIndex];
|
||||
genericArgs[*rhsFlatIndex] = genericArgs[*lhsFlatIndex];
|
||||
}
|
||||
|
||||
if (!needToCheckAssociatedSameTypes) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Once again, loop through our list and look for same type constraints where
|
||||
// the rhs is an associated type of sorts.
|
||||
for (const auto &req : genericContext->getGenericRequirements()) {
|
||||
// We only care about same-type constraints.
|
||||
if (req.Flags.getKind() != GenericRequirementKind::SameType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto lhsParam = demangleToGenericParamRef(req.getParam());
|
||||
|
||||
if (!lhsParam) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto lhsFlatIndex =
|
||||
_depthIndexToFlatIndex(lhsParam->first, lhsParam->second,
|
||||
genericParamCounts);
|
||||
if (!lhsFlatIndex || *lhsFlatIndex >= genericArgs.size())
|
||||
return false;
|
||||
|
||||
auto rhsParam =
|
||||
swift_getTypeByMangledName(MetadataState::Abstract,
|
||||
req.getMangledTypeName(),
|
||||
keyArgs.data(),
|
||||
[&substitutions](unsigned depth, unsigned index) {
|
||||
return substitutions.getMetadata(depth, index).Ptr;
|
||||
},
|
||||
[&substitutions](const Metadata *type, unsigned index) {
|
||||
return substitutions.getWitnessTable(type, index);
|
||||
}).getType().getMetadata();
|
||||
|
||||
if (!rhsParam) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we already have an argument for the lhs, then just check that it is
|
||||
// indeed == to the rhs type.
|
||||
if (auto genericArg = genericArgs[*lhsFlatIndex]) {
|
||||
if (genericArg.getMetadata() != rhsParam) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// If we don't have a lhs yet, then it's just the rhs.
|
||||
genericArgs[*lhsFlatIndex] = MetadataOrPack(rhsParam);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct InitializeDynamicReplacementLookup {
|
||||
|
||||
@@ -508,6 +508,17 @@ public:
|
||||
unsigned depth, unsigned index,
|
||||
llvm::ArrayRef<unsigned> paramCounts);
|
||||
|
||||
/// Gathers all of the written generic parameters needed for
|
||||
/// '_gatherGenericParameters'. This takes a list of key arguments and fills
|
||||
/// in the generic arguments with all generic arguments.
|
||||
///
|
||||
/// \returns true if the operation succeeded.
|
||||
bool _gatherWrittenGenericParameters(
|
||||
const TypeContextDescriptor *descriptor,
|
||||
llvm::ArrayRef<const void *> keyArgs,
|
||||
llvm::SmallVectorImpl<MetadataOrPack> &genericArgs,
|
||||
Demangle::Demangler &Dem);
|
||||
|
||||
/// Check the given generic requirements using the given set of generic
|
||||
/// arguments, collecting the key arguments (e.g., witness tables) for
|
||||
/// the caller.
|
||||
|
||||
@@ -126,4 +126,149 @@ testSuite.test("_swift_checkedCreateType variadic nested with requirements") {
|
||||
}
|
||||
}
|
||||
|
||||
struct Generic<T> {}
|
||||
struct Generic2<T, U> {}
|
||||
struct Generic3<T, U, V> {}
|
||||
struct Generic4<T, U, V, W> {}
|
||||
struct Generic5<T, U, V, each W> {}
|
||||
|
||||
extension Generic where T == Int {
|
||||
struct Nested {}
|
||||
}
|
||||
|
||||
extension Generic2 where T == U? {
|
||||
struct Nested {}
|
||||
}
|
||||
|
||||
extension Generic3 where T == U, U == V.Element, V: Collection {
|
||||
struct Nested {}
|
||||
}
|
||||
|
||||
extension Generic4 where T == U, U == V.Element, V == W, W: Collection {
|
||||
struct Nested {}
|
||||
}
|
||||
|
||||
extension Generic5 where T== U, U == V.Element, V: Collection, repeat each W: Equatable {
|
||||
struct Nested {}
|
||||
}
|
||||
|
||||
testSuite.test("_swift_instantiateCheckedGenericMetadata concrete generic types (same type conretized)") {
|
||||
let nestedMeta1 = metaPointer(Generic<Int>.Nested.self)
|
||||
let nestedDesc1 = nestedMeta1.load(
|
||||
fromByteOffset: MemoryLayout<Int>.size,
|
||||
as: UnsafeRawPointer.self
|
||||
)
|
||||
|
||||
let genericArgs1: [UnsafeRawPointer?] = []
|
||||
|
||||
genericArgs1.withUnsafeBufferPointer {
|
||||
let nested = _instantiateCheckedGenericMetadata(
|
||||
nestedDesc1,
|
||||
UnsafeRawPointer($0.baseAddress!),
|
||||
UInt($0.count)
|
||||
)
|
||||
|
||||
expectTrue(nested == Generic<Int>.Nested.self)
|
||||
}
|
||||
|
||||
let nestedMeta2 = metaPointer(Generic2<Int?, Int>.Nested.self)
|
||||
let nestedDesc2 = nestedMeta2.load(
|
||||
fromByteOffset: MemoryLayout<Int>.size,
|
||||
as: UnsafeRawPointer.self
|
||||
)
|
||||
|
||||
let genericArgs2 = [metaPointer(String.self)]
|
||||
|
||||
genericArgs2.withUnsafeBufferPointer {
|
||||
let nested = _instantiateCheckedGenericMetadata(
|
||||
nestedDesc2,
|
||||
UnsafeRawPointer($0.baseAddress!),
|
||||
UInt($0.count)
|
||||
)
|
||||
|
||||
expectTrue(nested == Generic2<String?, String>.Nested.self)
|
||||
}
|
||||
|
||||
let nestedMeta3 = metaPointer(Generic3<Int, Int, [Int]>.Nested.self)
|
||||
let nestedDesc3 = nestedMeta3.load(
|
||||
fromByteOffset: MemoryLayout<Int>.size,
|
||||
as: UnsafeRawPointer.self
|
||||
)
|
||||
|
||||
// Fails the constraint `T == V.Element`
|
||||
let genericArgs3a = [metaPointer(String.self), metaPointer([Int].self)]
|
||||
|
||||
genericArgs3a.withUnsafeBufferPointer {
|
||||
let nested = _instantiateCheckedGenericMetadata(
|
||||
nestedDesc3,
|
||||
UnsafeRawPointer($0.baseAddress!),
|
||||
UInt($0.count)
|
||||
)
|
||||
|
||||
expectNil(nested)
|
||||
}
|
||||
|
||||
// T == String (U)
|
||||
// U == V.Element
|
||||
// V: Collection
|
||||
//
|
||||
// T == String == V.Element
|
||||
// V == [String]
|
||||
let genericArgs3b = [metaPointer(String.self), metaPointer([String].self)]
|
||||
|
||||
genericArgs3b.withUnsafeBufferPointer {
|
||||
let nested = _instantiateCheckedGenericMetadata(
|
||||
nestedDesc3,
|
||||
UnsafeRawPointer($0.baseAddress!),
|
||||
UInt($0.count)
|
||||
)
|
||||
|
||||
expectTrue(nested == Generic3<String, String, [String]>.Nested.self)
|
||||
}
|
||||
|
||||
let nestedMeta4 = metaPointer(Generic4<(), (), [()], [()]>.Nested.self)
|
||||
let nestedDesc4 = nestedMeta4.load(
|
||||
fromByteOffset: MemoryLayout<Int>.size,
|
||||
as: UnsafeRawPointer.self
|
||||
)
|
||||
|
||||
let genericArgs4 = [metaPointer(Int.self), metaPointer([Int].self)]
|
||||
|
||||
genericArgs4.withUnsafeBufferPointer {
|
||||
let nested = _instantiateCheckedGenericMetadata(
|
||||
nestedDesc4,
|
||||
UnsafeRawPointer($0.baseAddress!),
|
||||
UInt($0.count)
|
||||
)
|
||||
|
||||
expectTrue(nested == Generic4<Int, Int, [Int], [Int]>.Nested.self)
|
||||
}
|
||||
|
||||
let nestedMeta5 = metaPointer(Generic5<(), (), [()]>.Nested.self)
|
||||
let nestedDesc5 = nestedMeta5.load(
|
||||
fromByteOffset: MemoryLayout<Int>.size,
|
||||
as: UnsafeRawPointer.self
|
||||
)
|
||||
|
||||
let nested5Pack: [Any.Type] = [String.self, Double.self]
|
||||
|
||||
nested5Pack.withUnsafeBufferPointer {
|
||||
let genericArgs5 = [
|
||||
metaPointer(Int.self),
|
||||
metaPointer([Int].self),
|
||||
allocateMetadataPack(UnsafeRawPointer($0.baseAddress!), UInt($0.count))
|
||||
]
|
||||
|
||||
genericArgs5.withUnsafeBufferPointer {
|
||||
let nested = _instantiateCheckedGenericMetadata(
|
||||
nestedDesc5,
|
||||
UnsafeRawPointer($0.baseAddress!),
|
||||
UInt($0.count)
|
||||
)
|
||||
|
||||
expectTrue(nested == Generic5<Int, Int, [Int], String, Double>.Nested.self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runAllTests()
|
||||
|
||||
Reference in New Issue
Block a user