Skip to content

Commit a2724fa

Browse files
committed
Sema: Dynamic casts to ObjC generic classes don't use the type metadata of the parameters.
We can't check the generic parameters dynamically.
1 parent fdbad84 commit a2724fa

File tree

2 files changed

+65
-5
lines changed

2 files changed

+65
-5
lines changed

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,29 @@ class FindCapturedVars : public ASTWalker {
7575

7676
// We want to look through type aliases here.
7777
type = type->getCanonicalType();
78-
78+
79+
class TypeCaptureWalker : public TypeWalker {
80+
AnyFunctionRef AFR;
81+
llvm::function_ref<void(Type)> Callback;
82+
public:
83+
explicit TypeCaptureWalker(AnyFunctionRef AFR,
84+
llvm::function_ref<void(Type)> callback)
85+
: AFR(AFR), Callback(callback) {}
86+
87+
Action walkToTypePre(Type ty) override {
88+
Callback(ty);
89+
// Pseudogeneric classes don't use their generic parameters so we
90+
// don't need to visit them.
91+
if (AFR.isObjC()) {
92+
if (auto clas = dyn_cast_or_null<ClassDecl>(ty->getAnyNominal())) {
93+
if (clas->usesObjCGenericsModel()) {
94+
return Action::SkipChildren;
95+
}
96+
}
97+
}
98+
return Action::Continue;
99+
}
100+
};
79101
// If the type contains dynamic 'Self', conservatively assume we will
80102
// need 'Self' metadata at runtime. We could generalize the analysis
81103
// used below for usages of generic parameters in Objective-C
@@ -88,14 +110,14 @@ class FindCapturedVars : public ASTWalker {
88110
// retainable pointer. Similarly stored property access does not
89111
// need it, etc.
90112
if (type->hasDynamicSelfType()) {
91-
type.visit([&](Type t) {
113+
type.walk(TypeCaptureWalker(AFR, [&](Type t) {
92114
if (auto *dynamicSelf = t->getAs<DynamicSelfType>()) {
93115
if (DynamicSelfCaptureLoc.isInvalid()) {
94116
DynamicSelfCaptureLoc = loc;
95117
DynamicSelf = dynamicSelf;
96118
}
97119
}
98-
});
120+
}));
99121
}
100122

101123
// Similar to dynamic 'Self', IRGen doesn't really need type metadata
@@ -106,13 +128,13 @@ class FindCapturedVars : public ASTWalker {
106128
// instead, but even there we don't really have enough information to
107129
// perform it accurately.
108130
if (type->hasArchetype()) {
109-
type.visit([&](Type t) {
131+
type.walk(TypeCaptureWalker(AFR, [&](Type t) {
110132
if (t->is<ArchetypeType>() &&
111133
!t->isOpenedExistential() &&
112134
GenericParamCaptureLoc.isInvalid()) {
113135
GenericParamCaptureLoc = loc;
114136
}
115-
});
137+
}));
116138
}
117139
}
118140

@@ -499,6 +521,17 @@ class FindCapturedVars : public ASTWalker {
499521
|| isa<ExistentialMetatypeToObjectExpr>(E))
500522
return false;
501523

524+
// Casting to an ObjC class doesn't require the metadata of its type
525+
// parameters, if any.
526+
if (auto cast = dyn_cast<CheckedCastExpr>(E)) {
527+
if (auto clas = dyn_cast_or_null<ClassDecl>(
528+
cast->getCastTypeLoc().getType()->getAnyNominal())) {
529+
if (clas->usesObjCGenericsModel()) {
530+
return false;
531+
}
532+
}
533+
}
534+
502535
// Assigning an object doesn't require type metadata.
503536
if (auto assignment = dyn_cast<AssignExpr>(E))
504537
return !assignment->getSrc()->getType()

test/ClangModules/objc_bridging_generics.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,33 @@ extension AnimalContainer {
221221
_ = x
222222
}
223223

224+
// Doesn't use 'T', since dynamic casting to an ObjC generic class doesn't
225+
// check its generic parameters
226+
func doesntUseGenericParam7() {
227+
_ = (self as AnyObject) as! GenericClass<T>
228+
_ = (self as AnyObject) as? GenericClass<T>
229+
_ = (self as AnyObject) as! AnimalContainer<T>
230+
_ = (self as AnyObject) as? AnimalContainer<T>
231+
_ = (self as AnyObject) is AnimalContainer<T>
232+
_ = (self as AnyObject) is AnimalContainer<T>
233+
}
234+
235+
// Dynamic casting to the generic parameter would require its generic params,
236+
// though
237+
// expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}}
238+
func usesGenericParamZ1() {
239+
_ = (self as AnyObject) as! T //expected-note{{here}}
240+
}
241+
// expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}}
242+
func usesGenericParamZ2() {
243+
_ = (self as AnyObject) as? T //expected-note{{here}}
244+
}
245+
// expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}}
246+
func usesGenericParamZ3() {
247+
_ = (self as AnyObject) is T //expected-note{{here}}
248+
}
249+
250+
224251
// expected-error@+1{{extension of a generic Objective-C class cannot access the class's generic parameters}}
225252
func usesGenericParamA(_ x: T) {
226253
_ = T(noise: x) // expected-note{{used here}}

0 commit comments

Comments
 (0)