Skip to content

Commit b148e24

Browse files
Merge pull request swiftlang#32027 from aschwaighofer/type_substitute_objc_generics
Type substitution: When substituting SILFunctionTypes we substitute u…
2 parents df7cf79 + 532f0cb commit b148e24

File tree

7 files changed

+47
-20
lines changed

7 files changed

+47
-20
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3569,6 +3569,8 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
35693569
/// initializer.
35703570
bool hasDefaultInitializer() const;
35713571

3572+
bool isTypeErasedGenericClass() const;
3573+
35723574
/// Retrieves the synthesized zero parameter default initializer for this
35733575
/// declaration, or \c nullptr if it doesn't have one.
35743576
ConstructorDecl *getDefaultInitializer() const;

include/swift/AST/Type.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ class CanType : public Type {
386386
static bool isExistentialTypeImpl(CanType type);
387387
static bool isAnyExistentialTypeImpl(CanType type);
388388
static bool isObjCExistentialTypeImpl(CanType type);
389+
static bool isTypeErasedGenericClassTypeImpl(CanType type);
389390
static CanType getOptionalObjectTypeImpl(CanType type);
390391
static CanType getReferenceStorageReferentImpl(CanType type);
391392
static CanType getWithoutSpecifierTypeImpl(CanType type);
@@ -472,6 +473,11 @@ class CanType : public Type {
472473
return isObjCExistentialTypeImpl(*this);
473474
}
474475

476+
// Is this an ObjC generic class.
477+
bool isTypeErasedGenericClassType() const {
478+
return isTypeErasedGenericClassTypeImpl(*this);
479+
}
480+
475481
ClassDecl *getClassOrBoundGenericClass() const; // in Types.h
476482
StructDecl *getStructOrBoundGenericStruct() const; // in Types.h
477483
EnumDecl *getEnumOrBoundGenericEnum() const; // in Types.h

lib/AST/Decl.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4094,6 +4094,14 @@ bool NominalTypeDecl::hasDefaultInitializer() const {
40944094
false);
40954095
}
40964096

4097+
bool NominalTypeDecl::isTypeErasedGenericClass() const {
4098+
// ObjC classes are type erased.
4099+
// TODO: Unless they have magic methods...
4100+
if (auto clas = dyn_cast<ClassDecl>(this))
4101+
return clas->hasClangNode() && clas->isGenericContext();
4102+
return false;
4103+
}
4104+
40974105
ConstructorDecl *NominalTypeDecl::getDefaultInitializer() const {
40984106
if (!hasDefaultInitializer())
40994107
return nullptr;

lib/AST/Type.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,12 @@ bool CanType::isObjCExistentialTypeImpl(CanType type) {
343343
return type.getExistentialLayout().isObjC();
344344
}
345345

346+
bool CanType::isTypeErasedGenericClassTypeImpl(CanType type) {
347+
if (auto nom = type->getAnyNominal())
348+
return nom->isTypeErasedGenericClass();
349+
return false;
350+
}
351+
346352
bool TypeBase::isSpecialized() {
347353
Type t = getCanonicalType();
348354

@@ -4280,9 +4286,13 @@ case TypeKind::Id:
42804286
SmallVector<Type, 4> newReplacements;
42814287
for (Type type : subs.getReplacementTypes()) {
42824288
auto transformed = type.transformRec(fn);
4283-
assert((type->isEqual(transformed)
4284-
|| (type->hasTypeParameter() && transformed->hasTypeParameter()))
4285-
&& "Substituted SILFunctionType can't be transformed into a concrete type");
4289+
assert((type->isEqual(transformed) ||
4290+
(type->hasTypeParameter() && transformed->hasTypeParameter()) ||
4291+
(type->getCanonicalType().isTypeErasedGenericClassType() &&
4292+
transformed->getCanonicalType()
4293+
.isTypeErasedGenericClassType())) &&
4294+
"Substituted SILFunctionType can't be transformed into a "
4295+
"concrete type");
42864296
newReplacements.push_back(transformed->getCanonicalType());
42874297
if (!type->isEqual(transformed))
42884298
changed = true;

lib/IRGen/MetadataRequest.cpp

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -441,26 +441,12 @@ static llvm::Value *emitObjCMetadataRef(IRGenFunction &IGF,
441441
return emitObjCMetadataRefForMetadata(IGF, classPtr);
442442
}
443443

444-
static bool isTypeErasedGenericClass(NominalTypeDecl *ntd) {
445-
// ObjC classes are type erased.
446-
// TODO: Unless they have magic methods...
447-
if (auto clas = dyn_cast<ClassDecl>(ntd))
448-
return clas->hasClangNode() && clas->isGenericContext();
449-
return false;
450-
}
451-
452-
static bool isTypeErasedGenericClassType(CanType type) {
453-
if (auto nom = type->getAnyNominal())
454-
return isTypeErasedGenericClass(nom);
455-
return false;
456-
}
457-
458444
// Get the type that exists at runtime to represent a compile-time type.
459445
CanType IRGenModule::getRuntimeReifiedType(CanType type) {
460446
// Leave type-erased ObjC generics with their generic arguments unbound, since
461447
// the arguments do not exist at runtime.
462448
return CanType(type.transform([&](Type t) -> Type {
463-
if (isTypeErasedGenericClassType(CanType(t))) {
449+
if (CanType(t).isTypeErasedGenericClassType()) {
464450
return t->getAnyNominal()->getDeclaredType()->getCanonicalType();
465451
}
466452
return t;
@@ -2132,7 +2118,7 @@ static llvm::Function *getAccessFunctionPrototype(IRGenModule &IGM,
21322118
ForDefinition_t forDefinition) {
21332119
assert(!type->hasArchetype());
21342120
// Type should be bound unless it's type erased.
2135-
assert(isTypeErasedGenericClassType(type)
2121+
assert(type.isTypeErasedGenericClassType()
21362122
? !isa<BoundGenericType>(type)
21372123
: !isa<UnboundGenericType>(type));
21382124

@@ -2220,7 +2206,7 @@ irgen::getGenericTypeMetadataAccessFunction(IRGenModule &IGM,
22202206
NominalTypeDecl *nominal,
22212207
ForDefinition_t shouldDefine) {
22222208
assert(nominal->isGenericContext());
2223-
assert(!isTypeErasedGenericClass(nominal));
2209+
assert(!nominal->isTypeErasedGenericClass());
22242210

22252211
GenericArguments genericArgs;
22262212
genericArgs.collectTypes(IGM, nominal);

test/IRGen/Inputs/usr/include/Gizmo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,6 @@ __attribute__((swift_name("OuterType.InnerType")))
163163
@protocol P
164164
- (oneway void)stuff;
165165
@end
166+
167+
@interface ObjcGenericClass<__covariant SectionType>
168+
@end

test/IRGen/generic_classes_objc.sil

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,15 @@ protocol P2 { }
7272
// CHECK-SAME: i16 3, i16 3, i16 5, i16 0
7373
class Generic3WithReqs<T: P1, U: P2, V: P2> { }
7474
sil_vtable Generic3WithReqs { }
75+
76+
77+
class SomeClass{}
78+
sil_vtable SomeClass {}
79+
80+
// This used to assert.
81+
sil @repo : $@convention(thin) (@guaranteed Optional< @callee_guaranteed @substituted <τ_0_1> (@in_guaranteed Result<τ_0_1, Error>) -> () for <ObjcGenericClass<SomeClass>>>) -> () {
82+
bb0(%0 : $Optional< @callee_guaranteed @substituted <τ_0_1> (@in_guaranteed Result<τ_0_1, Error>) -> () for <ObjcGenericClass<SomeClass>> >):
83+
debug_value %0 : $Optional<@callee_guaranteed @substituted <τ_0_1> (@in_guaranteed Result<τ_0_1, Error>) -> () for <ObjcGenericClass<SomeClass>>>, let, name "completion", argno 1
84+
%2 = tuple ()
85+
return %2 : $()
86+
}

0 commit comments

Comments
 (0)