@@ -1967,16 +1967,30 @@ llvm::Value *irgen::emitDynamicTypeOfHeapObject(IRGenFunction &IGF,
1967
1967
llvm::Value *object,
1968
1968
MetatypeRepresentation repr,
1969
1969
SILType objectType,
1970
- bool suppressCast) {
1971
- // If it is known to have swift metadata, just load. A swift class is both
1972
- // heap metadata and type metadata.
1973
- if (hasKnownSwiftMetadata (IGF.IGM , objectType.getASTType ())) {
1974
- return emitLoadOfHeapMetadataRef (IGF, object,
1975
- getIsaEncodingForType (IGF.IGM , objectType.getASTType ()),
1976
- suppressCast);
1970
+ bool allowArtificialSubclasses){
1971
+ switch (auto isaEncoding =
1972
+ getIsaEncodingForType (IGF.IGM , objectType.getASTType ())) {
1973
+ case IsaEncoding::Pointer:
1974
+ // Directly load the isa pointer from a pure Swift class.
1975
+ return emitLoadOfHeapMetadataRef (IGF, object, isaEncoding,
1976
+ /* suppressCast*/ false );
1977
+ case IsaEncoding::ObjC:
1978
+ // A class defined in Swift that inherits from an Objective-C class may
1979
+ // end up dynamically subclassed by ObjC runtime hackery. The artificial
1980
+ // subclass isn't a formal Swift type, so isn't appropriate as the result
1981
+ // of `type(of:)`, but is still a physical subtype of the real class object,
1982
+ // so can be used for some purposes like satisfying type parameters in
1983
+ // generic signatures.
1984
+ if (allowArtificialSubclasses
1985
+ && hasKnownSwiftMetadata (IGF.IGM , objectType.getASTType ()))
1986
+ return emitLoadOfHeapMetadataRef (IGF, object, isaEncoding,
1987
+ /* suppressCast*/ false );
1988
+
1989
+ // Ask the Swift runtime to find the dynamic type. This will look through
1990
+ // dynamic subclasses of Swift classes, and use the -class message for
1991
+ // ObjC classes.
1992
+ return emitDynamicTypeOfOpaqueHeapObject (IGF, object, repr);
1977
1993
}
1978
-
1979
- return emitDynamicTypeOfOpaqueHeapObject (IGF, object, repr);
1980
1994
}
1981
1995
1982
1996
static ClassDecl *getRootClass (ClassDecl *theClass) {
@@ -2001,6 +2015,11 @@ IsaEncoding irgen::getIsaEncodingForType(IRGenModule &IGM,
2001
2015
// For ObjC or mixed classes, we need to use object_getClass.
2002
2016
return IsaEncoding::ObjC;
2003
2017
}
2018
+
2019
+ // Existentials use the encoding of the enclosed dynamic type.
2020
+ if (type->isAnyExistentialType ()) {
2021
+ return getIsaEncodingForType (IGM, ArchetypeType::getOpened (type));
2022
+ }
2004
2023
2005
2024
if (auto archetype = dyn_cast<ArchetypeType>(type)) {
2006
2025
// If we have a concrete superclass constraint, just recurse.
@@ -2013,9 +2032,6 @@ IsaEncoding irgen::getIsaEncodingForType(IRGenModule &IGM,
2013
2032
return IsaEncoding::ObjC;
2014
2033
}
2015
2034
2016
- // We should never be working with an unopened existential type here.
2017
- assert (!type->isAnyExistentialType ());
2018
-
2019
2035
// Non-class heap objects should be pure Swift, so we can access their isas
2020
2036
// directly.
2021
2037
return IsaEncoding::Pointer;
0 commit comments