Skip to content

Commit 541aa8d

Browse files
authored
Merge pull request #59507 from CodaFi/metastability
2 parents 922e230 + 824fa48 commit 541aa8d

File tree

5 files changed

+47
-6
lines changed

5 files changed

+47
-6
lines changed

lib/IRGen/GenCast.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -850,7 +850,7 @@ void irgen::emitScalarExistentialDowncast(IRGenFunction &IGF,
850850
/// that the actual value isn't changed in any way, thus preserving its
851851
/// reference identity.
852852
///
853-
/// These restrictions are set by canUseScalarCheckedCastInstructions.
853+
/// These restrictions are set by \c canSILUseScalarCheckedCastInstructions.
854854
/// Essentially, both the source and target types must be one of:
855855
/// - a (possibly generic) concrete class type,
856856
/// - a class-bounded archetype,

lib/SIL/Utils/DynamicCasts.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,6 +1311,14 @@ bool swift::canSILUseScalarCheckedCastInstructions(SILModule &M,
13111311
bool swift::canIRGenUseScalarCheckedCastInstructions(SILModule &M,
13121312
CanType sourceFormalType,
13131313
CanType targetFormalType) {
1314+
// If the cast involves any kind of generalized existential we
1315+
// need to use the indirect-cast path to handle checking the extra
1316+
// constraints there as the scalar path does not (yet) know how to do it.
1317+
if (sourceFormalType->hasParameterizedExistential() ||
1318+
targetFormalType->hasParameterizedExistential()) {
1319+
return false;
1320+
}
1321+
13141322
// Look through one level of optionality on the source.
13151323
auto objectType = sourceFormalType;
13161324
if (auto type = objectType.getOptionalObjectType())

stdlib/public/runtime/Demangle.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,11 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
444444
return proto_list;
445445
}
446446
case MetadataKind::ExtendedExistential: {
447-
swift_unreachable("Extended existentials not supported");
447+
// FIXME: Implement this by demangling the extended existential and
448+
// substituting the generalization arguments into the demangle tree.
449+
// For now, unconditional casts will report '<<< invalid type >>>' when
450+
// they fail.
451+
return nullptr;
448452
}
449453
case MetadataKind::ExistentialMetatype: {
450454
auto metatype = static_cast<const ExistentialMetatypeMetadata *>(type);

stdlib/public/runtime/DynamicCast.cpp

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1781,6 +1781,37 @@ static DynamicCastResult tryCastToExtendedExistential(
17811781
auto *destExistentialShape = destExistentialType->Shape;
17821782
const unsigned shapeArgumentCount =
17831783
destExistentialShape->getGenSigArgumentLayoutSizeInWords();
1784+
const Metadata *selfType = srcType;
1785+
1786+
// If we have a type expression to look into, unwrap as much metatype
1787+
// structure as possible so we can reach the type metadata for the 'Self'
1788+
// parameter.
1789+
if (destExistentialShape->Flags.hasTypeExpression()) {
1790+
Demangler dem;
1791+
auto *node = dem.demangleType(destExistentialShape->getTypeExpression()->name.get());
1792+
if (!node)
1793+
return DynamicCastResult::Failure;
1794+
1795+
while (node->getKind() == Demangle::Node::Kind::Type &&
1796+
node->getNumChildren() &&
1797+
node->getChild(0)->getKind() == Demangle::Node::Kind::Metatype &&
1798+
node->getChild(0)->getNumChildren()) {
1799+
auto *metatypeMetadata = dyn_cast<MetatypeMetadata>(selfType);
1800+
if (!metatypeMetadata)
1801+
return DynamicCastResult::Failure;
1802+
1803+
selfType = metatypeMetadata->InstanceType;
1804+
node = node->getChild(0)->getChild(0);
1805+
}
1806+
1807+
// Make sure the thing we've pulled out at the end is a dependent
1808+
// generic parameter.
1809+
if (!(node->getKind() == Demangle::Node::Kind::Type &&
1810+
node->getNumChildren() &&
1811+
node->getChild(0)->getKind() ==
1812+
Demangle::Node::Kind::DependentGenericParamType))
1813+
return DynamicCastResult::Failure;
1814+
}
17841815

17851816
llvm::SmallVector<const void *, 8> allGenericArgsVec;
17861817
unsigned witnessesMark = 0;
@@ -1789,7 +1820,7 @@ static DynamicCastResult tryCastToExtendedExistential(
17891820
auto genArgs = destExistentialType->getGeneralizationArguments();
17901821
allGenericArgsVec.append(genArgs, genArgs + shapeArgumentCount);
17911822
// Tack on the `Self` argument.
1792-
allGenericArgsVec.push_back((const void *)srcType);
1823+
allGenericArgsVec.push_back((const void *)selfType);
17931824
// Mark the point where the generic arguments end.
17941825
// _checkGenericRequirements is going to fill in a set of witness tables
17951826
// after that.

test/Casting/ParameterizedExistentials.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,7 @@ tests.test("Parameterized existential casting basics work") {
8282
expectNil(d)
8383
}
8484

85-
tests.test("Metatype existential casting basics work")
86-
.xfail(.custom({ true }, reason: "IRGen peepholes these casts"))
87-
.code {
85+
tests.test("Metatype existential casting basics work") {
8886
let a = GenericHolder<Int>.self as any Holder<Int>.Type
8987
let b = GenericHolder<Int>.self as! any Holder<Int>.Type
9088
expectTrue(a == b)

0 commit comments

Comments
 (0)