Merge pull request #59507 from CodaFi/metastability

This commit is contained in:
Robert Widmann
2022-06-16 20:37:13 -06:00
committed by GitHub
5 changed files with 47 additions and 6 deletions

View File

@@ -850,7 +850,7 @@ void irgen::emitScalarExistentialDowncast(IRGenFunction &IGF,
/// that the actual value isn't changed in any way, thus preserving its
/// reference identity.
///
/// These restrictions are set by canUseScalarCheckedCastInstructions.
/// These restrictions are set by \c canSILUseScalarCheckedCastInstructions.
/// Essentially, both the source and target types must be one of:
/// - a (possibly generic) concrete class type,
/// - a class-bounded archetype,

View File

@@ -1311,6 +1311,14 @@ bool swift::canSILUseScalarCheckedCastInstructions(SILModule &M,
bool swift::canIRGenUseScalarCheckedCastInstructions(SILModule &M,
CanType sourceFormalType,
CanType targetFormalType) {
// If the cast involves any kind of generalized existential we
// need to use the indirect-cast path to handle checking the extra
// constraints there as the scalar path does not (yet) know how to do it.
if (sourceFormalType->hasParameterizedExistential() ||
targetFormalType->hasParameterizedExistential()) {
return false;
}
// Look through one level of optionality on the source.
auto objectType = sourceFormalType;
if (auto type = objectType.getOptionalObjectType())

View File

@@ -444,7 +444,11 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
return proto_list;
}
case MetadataKind::ExtendedExistential: {
swift_unreachable("Extended existentials not supported");
// FIXME: Implement this by demangling the extended existential and
// substituting the generalization arguments into the demangle tree.
// For now, unconditional casts will report '<<< invalid type >>>' when
// they fail.
return nullptr;
}
case MetadataKind::ExistentialMetatype: {
auto metatype = static_cast<const ExistentialMetatypeMetadata *>(type);

View File

@@ -1781,6 +1781,37 @@ static DynamicCastResult tryCastToExtendedExistential(
auto *destExistentialShape = destExistentialType->Shape;
const unsigned shapeArgumentCount =
destExistentialShape->getGenSigArgumentLayoutSizeInWords();
const Metadata *selfType = srcType;
// If we have a type expression to look into, unwrap as much metatype
// structure as possible so we can reach the type metadata for the 'Self'
// parameter.
if (destExistentialShape->Flags.hasTypeExpression()) {
Demangler dem;
auto *node = dem.demangleType(destExistentialShape->getTypeExpression()->name.get());
if (!node)
return DynamicCastResult::Failure;
while (node->getKind() == Demangle::Node::Kind::Type &&
node->getNumChildren() &&
node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype &&
node->getChild(0)->getNumChildren()) {
auto *metatypeMetadata = dyn_cast<MetatypeMetadata>(selfType);
if (!metatypeMetadata)
return DynamicCastResult::Failure;
selfType = metatypeMetadata->InstanceType;
node = node->getChild(0)->getChild(0);
}
// Make sure the thing we've pulled out at the end is a dependent
// generic parameter.
if (!(node->getKind() == Demangle::Node::Kind::Type &&
node->getNumChildren() &&
node->getChild(0)->getKind() ==
Demangle::Node::Kind::DependentGenericParamType))
return DynamicCastResult::Failure;
}
llvm::SmallVector<const void *, 8> allGenericArgsVec;
unsigned witnessesMark = 0;
@@ -1789,7 +1820,7 @@ static DynamicCastResult tryCastToExtendedExistential(
auto genArgs = destExistentialType->getGeneralizationArguments();
allGenericArgsVec.append(genArgs, genArgs + shapeArgumentCount);
// Tack on the `Self` argument.
allGenericArgsVec.push_back((const void *)srcType);
allGenericArgsVec.push_back((const void *)selfType);
// Mark the point where the generic arguments end.
// _checkGenericRequirements is going to fill in a set of witness tables
// after that.

View File

@@ -82,9 +82,7 @@ tests.test("Parameterized existential casting basics work") {
expectNil(d)
}
tests.test("Metatype existential casting basics work")
.xfail(.custom({ true }, reason: "IRGen peepholes these casts"))
.code {
tests.test("Metatype existential casting basics work") {
let a = GenericHolder<Int>.self as any Holder<Int>.Type
let b = GenericHolder<Int>.self as! any Holder<Int>.Type
expectTrue(a == b)