@@ -732,14 +732,14 @@ namespace {
732
732
llvm::SmallPtrSet<ValueDecl *, 2 > Diagnosed;
733
733
// / The AbstractClosureExpr or AbstractFunctionDecl being analyzed.
734
734
AnyFunctionRef AFR;
735
- bool &capturesTypes ;
735
+ SourceLoc &TypeCapturingLoc ;
736
736
public:
737
737
FindCapturedVars (TypeChecker &tc,
738
738
SmallVectorImpl<CapturedValue> &captureList,
739
- bool &capturesTypes ,
739
+ SourceLoc &typeCapturingLoc ,
740
740
AnyFunctionRef AFR)
741
741
: TC(tc), captureList(captureList), AFR(AFR),
742
- capturesTypes (capturesTypes ) {
742
+ TypeCapturingLoc (typeCapturingLoc ) {
743
743
if (auto AFD = AFR.getAbstractFunctionDecl ())
744
744
CaptureLoc = AFD->getLoc ();
745
745
else {
@@ -758,22 +758,25 @@ namespace {
758
758
// / FIXME: SILGen doesn't currently allow local generic functions to
759
759
// / capture generic parameters from an outer context. Once it does, we
760
760
// / will need to distinguish outer and inner type parameters here.
761
- void checkType (Type type) {
761
+ void checkType (Type type, SourceLoc loc ) {
762
762
// Nothing to do if the type is concrete.
763
763
if (!type || !type->hasArchetype ())
764
764
return ;
765
765
766
766
// Walk the type to see if we have any archetypes that are *not* open
767
767
// existentials and that aren't type-erased.
768
768
class CapturesTypeWalker final : public TypeWalker {
769
- bool &CapturesTypes;
769
+ SourceLoc &TypeCapturingLoc;
770
+ SourceLoc CurLoc;
770
771
771
772
public:
772
- CapturesTypeWalker (bool &capturesTypes) : CapturesTypes(capturesTypes){}
773
+ CapturesTypeWalker (SourceLoc &capturingLoc, SourceLoc curLoc)
774
+ : TypeCapturingLoc(capturingLoc), CurLoc(curLoc) {}
773
775
774
776
Action walkToTypePre (Type t) override {
775
777
if (t->is <ArchetypeType>() && !t->isOpenedExistential ()) {
776
- CapturesTypes = true ;
778
+ if (TypeCapturingLoc.isInvalid ())
779
+ TypeCapturingLoc = CurLoc;
777
780
return Action::Stop;
778
781
}
779
782
@@ -789,7 +792,7 @@ namespace {
789
792
}
790
793
};
791
794
792
- type.walk (CapturesTypeWalker (capturesTypes ));
795
+ type.walk (CapturesTypeWalker (TypeCapturingLoc, loc ));
793
796
}
794
797
795
798
// / Add the specified capture to the closure's capture list, diagnosing it
@@ -812,12 +815,12 @@ namespace {
812
815
captureList[entryNumber-1 ] = capture;
813
816
}
814
817
815
- // Visit the type of the capture. If we capture 'self' via a 'super' call,
816
- // and the superclass is not generic, there might not be any generic
817
- // parameter types in the closure body, so we have to account for them
818
- // here.
819
- if ( VD->hasType ( ))
820
- checkType (VD->getType ());
818
+ // Visit the type of the capture, if it isn't a class reference, since
819
+ // we'd need the metadata to do so.
820
+ if (VD-> hasType ()
821
+ && (!AFR. isObjC ()
822
+ || ! VD->getType ()-> hasRetainablePointerRepresentation () ))
823
+ checkType (VD->getType (), VD-> getLoc () );
821
824
822
825
// If VD is a noescape decl, then the closure we're computing this for
823
826
// must also be noescape.
@@ -999,7 +1002,7 @@ namespace {
999
1002
}
1000
1003
1001
1004
if (innerClosure.getCaptureInfo ().hasGenericParamCaptures ())
1002
- capturesTypes = true ;
1005
+ TypeCapturingLoc = innerClosure. getLoc () ;
1003
1006
}
1004
1007
1005
1008
bool walkToDeclPre (Decl *D) override {
@@ -1018,12 +1021,131 @@ namespace {
1018
1021
1019
1022
return true ;
1020
1023
}
1024
+
1025
+ bool usesTypeMetadataOfFormalType (Expr *E) {
1026
+ // For non-ObjC closures, assume the type metadata is always used.
1027
+ if (!AFR.isObjC ())
1028
+ return true ;
1029
+
1030
+ if (!E->getType () || E->getType ()->is <ErrorType>())
1031
+ return false ;
1032
+
1033
+ // We can use Objective-C generics in limited ways without reifying
1034
+ // their type metadata, meaning we don't need to capture their generic
1035
+ // params.
1036
+
1037
+ // Look through one layer of optionality when considering the class-
1038
+
1039
+ // Referring to a class-constrained generic or metatype
1040
+ // doesn't require its type metadata.
1041
+ if (auto declRef = dyn_cast<DeclRefExpr>(E))
1042
+ return !declRef->getDecl ()->isObjC ()
1043
+ && !E->getType ()->hasRetainablePointerRepresentation ()
1044
+ && !E->getType ()->is <AnyMetatypeType>();
1045
+
1046
+ // Loading classes or metatypes doesn't require their metadata.
1047
+ if (isa<LoadExpr>(E))
1048
+ return !E->getType ()->hasRetainablePointerRepresentation ()
1049
+ && !E->getType ()->is <AnyMetatypeType>();
1050
+
1051
+ // Accessing @objc members doesn't require type metadata.
1052
+ if (auto memberRef = dyn_cast<MemberRefExpr>(E))
1053
+ return !memberRef->getMember ().getDecl ()->hasClangNode ();
1054
+
1055
+ if (auto applyExpr = dyn_cast<ApplyExpr>(E)) {
1056
+ if (auto methodApply = dyn_cast<ApplyExpr>(applyExpr->getFn ())) {
1057
+ if (auto callee = dyn_cast<DeclRefExpr>(methodApply->getFn ())) {
1058
+ return !callee->getDecl ()->isObjC ();
1059
+ }
1060
+ }
1061
+ if (auto callee = dyn_cast<DeclRefExpr>(applyExpr->getFn ())) {
1062
+ return !callee->getDecl ()->isObjC ();
1063
+ }
1064
+ }
1065
+
1066
+ if (auto subscriptExpr = dyn_cast<SubscriptExpr>(E)) {
1067
+ return !subscriptExpr->getDecl ().getDecl ()->isObjC ();
1068
+ }
1069
+
1070
+ // Getting the dynamic type of a class doesn't require type metadata.
1071
+ if (isa<DynamicTypeExpr>(E))
1072
+ return !E->getType ()->castTo <AnyMetatypeType>()->getInstanceType ()
1073
+ ->hasRetainablePointerRepresentation ();
1074
+
1075
+ // Building a fixed-size tuple doesn't require type metadata.
1076
+ // Approximate this for the purposes of being able to invoke @objc methods
1077
+ // by considering tuples of ObjC-representable types to not use metadata.
1078
+ if (auto tuple = dyn_cast<TupleExpr>(E)) {
1079
+ for (auto elt : tuple->getType ()->castTo <TupleType>()->getElements ()) {
1080
+ if (!elt.getType ()->isRepresentableIn (ForeignLanguage::ObjectiveC,
1081
+ AFR.getAsDeclContext ()))
1082
+ return true ;
1083
+ }
1084
+ return false ;
1085
+ }
1086
+
1087
+ // Coercion by itself is a no-op.
1088
+ if (isa<CoerceExpr>(E))
1089
+ return false ;
1090
+
1091
+ // Upcasting doesn't require type metadata.
1092
+ if (isa<DerivedToBaseExpr>(E))
1093
+ return false ;
1094
+ if (isa<ArchetypeToSuperExpr>(E))
1095
+ return false ;
1096
+ if (isa<CovariantReturnConversionExpr>(E))
1097
+ return false ;
1098
+ if (isa<MetatypeConversionExpr>(E))
1099
+ return false ;
1100
+
1101
+ // Identity expressions are no-ops.
1102
+ if (isa<IdentityExpr>(E))
1103
+ return false ;
1104
+
1105
+ // Discarding an assignment is a no-op.
1106
+ if (isa<DiscardAssignmentExpr>(E))
1107
+ return false ;
1108
+
1109
+ // Opening an @objc existential or metatype is a no-op.
1110
+ if (auto open = dyn_cast<OpenExistentialExpr>(E))
1111
+ return !open->getSubExpr ()->getType ()->isObjCExistentialType ()
1112
+ && !open->getSubExpr ()->getType ()->is <AnyMetatypeType>();
1113
+
1114
+ // Erasure to an ObjC existential or between metatypes doesn't require
1115
+ // type metadata.
1116
+ if (auto erasure = dyn_cast<ErasureExpr>(E)) {
1117
+ if (E->getType ()->isObjCExistentialType ()
1118
+ || E->getType ()->is <AnyMetatypeType>())
1119
+ return false ;
1120
+ // Erasure to a Swift protocol always captures the type metadata from
1121
+ // its subexpression.
1122
+ checkType (erasure->getSubExpr ()->getType (),
1123
+ erasure->getSubExpr ()->getLoc ());
1124
+ return true ;
1125
+ }
1126
+
1127
+ // Converting an @objc metatype to AnyObject doesn't require type
1128
+ // metadata.
1129
+ if (isa<ClassMetatypeToObjectExpr>(E)
1130
+ || isa<ExistentialMetatypeToObjectExpr>(E))
1131
+ return false ;
1132
+
1133
+ return true ;
1134
+ }
1021
1135
1022
1136
std::pair<bool , Expr *> walkToExprPre (Expr *E) override {
1023
- checkType (E->getType ());
1137
+ if (usesTypeMetadataOfFormalType (E)) {
1138
+ checkType (E->getType (), E->getLoc ());
1139
+ }
1140
+
1141
+ // Some kinds of expression don't really evaluate their subexpression,
1142
+ // so we don't need to traverse.
1143
+ if (isa<ObjCSelectorExpr>(E)) {
1144
+ return { false , E };
1145
+ }
1024
1146
1025
1147
if (auto *ECE = dyn_cast<ExplicitCastExpr>(E)) {
1026
- checkType (ECE->getCastTypeLoc ().getType ());
1148
+ checkType (ECE->getCastTypeLoc ().getType (), ECE-> getLoc () );
1027
1149
return { true , E };
1028
1150
}
1029
1151
@@ -1038,7 +1160,7 @@ namespace {
1038
1160
return { false , superE };
1039
1161
}
1040
1162
1041
- // Don't recurse into child closures. They should already have a capture
1163
+ // Don't recur into child closures. They should already have a capture
1042
1164
// list computed; we just propagate it, filtering out stuff that they
1043
1165
// capture from us.
1044
1166
if (auto *SubCE = dyn_cast<AbstractClosureExpr>(E)) {
@@ -1074,12 +1196,29 @@ void TypeChecker::computeCaptures(AnyFunctionRef AFR) {
1074
1196
return ;
1075
1197
1076
1198
SmallVector<CapturedValue, 4 > Captures;
1077
- bool GenericParamCaptures = false ;
1078
- FindCapturedVars finder (*this , Captures, GenericParamCaptures , AFR);
1199
+ SourceLoc GenericParamCaptureLoc ;
1200
+ FindCapturedVars finder (*this , Captures, GenericParamCaptureLoc , AFR);
1079
1201
AFR.getBody ()->walk (finder);
1080
1202
1081
- if (AFR.hasType ())
1082
- finder.checkType (AFR.getType ());
1203
+ if (AFR.hasType () && !AFR.isObjC ()) {
1204
+ finder.checkType (AFR.getType (), AFR.getLoc ());
1205
+ /*
1206
+ for (auto paramList : AFR.getParameterLists()) {
1207
+ for (auto param : *paramList) {
1208
+ // Passing parameters of class type doesn't require their metadata.
1209
+ if (param->hasType()
1210
+ && !param->getType()->is<MetatypeType>()
1211
+ && !param->getType()->hasRetainablePointerRepresentation())
1212
+ finder.checkType(param->getType(), param->getLoc());
1213
+ }
1214
+ }
1215
+
1216
+ if (AFR.getBodyResultType()
1217
+ && !AFR.getBodyResultType()->is<MetatypeType>()
1218
+ && !AFR.getBodyResultType()->hasRetainablePointerRepresentation())
1219
+ finder.checkType(AFR.getBodyResultType(), AFR.getLoc());
1220
+ */
1221
+ }
1083
1222
1084
1223
// If this is an init(), explicitly walk the initializer values for members of
1085
1224
// the type. They will be implicitly emitted by SILGen into the generated
@@ -1111,7 +1250,8 @@ void TypeChecker::computeCaptures(AnyFunctionRef AFR) {
1111
1250
if (!AFD ||
1112
1251
(!AFD->getGenericParams () &&
1113
1252
AFD->getDeclContext ()->isLocalContext ())) {
1114
- AFR.getCaptureInfo ().setGenericParamCaptures (GenericParamCaptures);
1253
+ AFR.getCaptureInfo ()
1254
+ .setGenericParamCaptures (GenericParamCaptureLoc.isValid ());
1115
1255
}
1116
1256
1117
1257
if (Captures.empty ())
@@ -1121,11 +1261,14 @@ void TypeChecker::computeCaptures(AnyFunctionRef AFR) {
1121
1261
1122
1262
// Extensions of generic ObjC functions can't use generic parameters from
1123
1263
// their context.
1124
- if (AFD && GenericParamCaptures ) {
1264
+ if (AFD && GenericParamCaptureLoc. isValid () ) {
1125
1265
if (auto Clas = AFD->getParent ()->getAsClassOrClassExtensionContext ()) {
1126
- if (Clas->isGenericContext () && Clas->hasClangNode ())
1266
+ if (Clas->isGenericContext () && Clas->hasClangNode ()) {
1127
1267
diagnose (AFD->getLoc (),
1128
1268
diag::objc_generic_extension_using_type_parameter);
1269
+ diagnose (GenericParamCaptureLoc,
1270
+ diag::objc_generic_extension_using_type_parameter_here);
1271
+ }
1129
1272
}
1130
1273
}
1131
1274
0 commit comments