mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #59507 from CodaFi/metastability
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user