@@ -1145,7 +1145,7 @@ class AccessScopeChecker {
1145
1145
Cache(caches[File]),
1146
1146
Scope(AccessScope::getPublic()) {}
1147
1147
1148
- bool visitDecl (ValueDecl *VD) {
1148
+ bool visitDecl (ValueDecl *VD, bool isInParameter = false ) {
1149
1149
if (!VD || isa<GenericTypeParamDecl>(VD))
1150
1150
return true ;
1151
1151
@@ -1156,11 +1156,22 @@ class AccessScopeChecker {
1156
1156
return true ;
1157
1157
}
1158
1158
1159
- // Simulation for Swift 3 bug.
1160
- if (isa<TypeAliasDecl>(VD) &&
1161
- VD->getInterfaceType ()->hasTypeParameter () &&
1162
- Context.isSwiftVersion3 ())
1163
- return true ;
1159
+ // Simulation for Swift 3 bugs where typealiases got canonicalized away and
1160
+ // thus a reference to a private typealias would not be diagnosed.
1161
+ if (auto *TAD = dyn_cast<TypeAliasDecl>(VD)) {
1162
+ if (Context.isSwiftVersion3 ()) {
1163
+ // - If the typealias was a dependent type, Swift 3 resolved it down to
1164
+ // its underlying type.
1165
+ if (VD->getInterfaceType ()->hasTypeParameter ())
1166
+ return true ;
1167
+ // - If the typealias was a function type in parameter position, Swift 3
1168
+ // would rebuild the type to mark it non-escaping, losing the sugar.
1169
+ if (isInParameter &&
1170
+ TAD->getDeclaredInterfaceType ()->getAs <AnyFunctionType>()) {
1171
+ return true ;
1172
+ }
1173
+ }
1174
+ }
1164
1175
1165
1176
auto cached = Cache.find (VD);
1166
1177
if (cached != Cache.end ()) {
@@ -1179,27 +1190,52 @@ class AccessScopeChecker {
1179
1190
};
1180
1191
1181
1192
class TypeReprAccessScopeChecker : private ASTWalker , AccessScopeChecker {
1193
+ SmallVector<const TypeRepr *, 4 > ParamParents;
1194
+
1182
1195
TypeReprAccessScopeChecker (const DeclContext *useDC,
1183
- decltype (TypeChecker::TypeAccessScopeCache) &caches)
1184
- : AccessScopeChecker(useDC, caches) {}
1196
+ decltype (TypeChecker::TypeAccessScopeCache) &caches,
1197
+ bool isParameter)
1198
+ : AccessScopeChecker(useDC, caches) {
1199
+ if (isParameter)
1200
+ ParamParents.push_back (nullptr );
1201
+ }
1202
+
1203
+ bool isParamParent (const TypeRepr *TR) const {
1204
+ return !ParamParents.empty () && ParamParents.back () == TR;
1205
+ }
1185
1206
1186
1207
bool walkToTypeReprPre (TypeRepr *TR) override {
1187
- auto CITR = dyn_cast<ComponentIdentTypeRepr>(TR);
1188
- if (!CITR)
1189
- return true ;
1208
+ if (auto CITR = dyn_cast<ComponentIdentTypeRepr>(TR)) {
1209
+ return visitDecl (CITR->getBoundDecl (),
1210
+ isParamParent (Parent.getAsTypeRepr ()));
1211
+ }
1212
+
1213
+ auto parentTR = Parent.getAsTypeRepr ();
1214
+ if (auto parentFn = dyn_cast_or_null<FunctionTypeRepr>(parentTR)) {
1215
+ // The argument tuple for a function is a parent of parameter TRs.
1216
+ if (parentFn->getArgsTypeRepr () == TR)
1217
+ ParamParents.push_back (TR);
1218
+ } else if (isa<CompoundIdentTypeRepr>(TR) && isParamParent (parentTR)) {
1219
+ // Compound TRs that would have been parameter TRs contain parameter
1220
+ // TRs.
1221
+ ParamParents.push_back (TR);
1222
+ }
1190
1223
1191
- return visitDecl (CITR-> getBoundDecl ()) ;
1224
+ return true ;
1192
1225
}
1193
1226
1194
1227
bool walkToTypeReprPost (TypeRepr *TR) override {
1228
+ if (isParamParent (TR))
1229
+ ParamParents.pop_back ();
1195
1230
return Scope.hasValue ();
1196
1231
}
1197
1232
1198
1233
public:
1199
1234
static Optional<AccessScope>
1200
1235
getAccessScope (TypeRepr *TR, const DeclContext *useDC,
1201
- decltype (TypeChecker::TypeAccessScopeCache) &caches) {
1202
- TypeReprAccessScopeChecker checker (useDC, caches);
1236
+ decltype (TypeChecker::TypeAccessScopeCache) &caches,
1237
+ bool isParameter) {
1238
+ TypeReprAccessScopeChecker checker (useDC, caches, isParameter);
1203
1239
TR->walk (checker);
1204
1240
return checker.Scope ;
1205
1241
}
@@ -1262,7 +1298,8 @@ void TypeChecker::computeDefaultAccessibility(ExtensionDecl *ED) {
1262
1298
auto accessScope =
1263
1299
TypeReprAccessScopeChecker::getAccessScope (TL.getTypeRepr (),
1264
1300
ED->getDeclContext (),
1265
- TypeAccessScopeCache);
1301
+ TypeAccessScopeCache,
1302
+ /* isParameter*/ false );
1266
1303
// This is an error case and will be diagnosed elsewhere.
1267
1304
if (!accessScope.hasValue ())
1268
1305
return Accessibility::Public;
@@ -1475,7 +1512,7 @@ enum class DowngradeToWarning: bool {
1475
1512
// / is never null.
1476
1513
static void checkTypeAccessibilityImpl (
1477
1514
TypeChecker &TC, TypeLoc TL, AccessScope contextAccessScope,
1478
- const DeclContext *useDC,
1515
+ const DeclContext *useDC, bool isParameter,
1479
1516
llvm::function_ref<void (AccessScope, const TypeRepr *)> diagnose) {
1480
1517
if (!TC.getLangOpts ().EnableAccessControl )
1481
1518
return ;
@@ -1493,7 +1530,8 @@ static void checkTypeAccessibilityImpl(
1493
1530
auto typeAccessScope =
1494
1531
(TL.getTypeRepr ()
1495
1532
? TypeReprAccessScopeChecker::getAccessScope (TL.getTypeRepr (), useDC,
1496
- TC.TypeAccessScopeCache )
1533
+ TC.TypeAccessScopeCache ,
1534
+ isParameter)
1497
1535
: TypeAccessScopeChecker::getAccessScope (TL.getType (), useDC,
1498
1536
TC.TypeAccessScopeCache ));
1499
1537
@@ -1528,9 +1566,18 @@ static void checkTypeAccessibility(
1528
1566
TypeChecker &TC, TypeLoc TL, const ValueDecl *context,
1529
1567
llvm::function_ref<void (AccessScope, const TypeRepr *,
1530
1568
DowngradeToWarning)> diagnose) {
1569
+ const DeclContext *DC = context->getDeclContext ();
1570
+ bool isParam = false ;
1571
+ if (auto *param = dyn_cast<ParamDecl>(context)) {
1572
+ isParam = true ;
1573
+ context = dyn_cast<AbstractFunctionDecl>(DC);
1574
+ if (!context)
1575
+ context = cast<SubscriptDecl>(DC);
1576
+ DC = context->getDeclContext ();
1577
+ }
1578
+
1531
1579
AccessScope contextAccessScope = context->getFormalAccessScope ();
1532
- checkTypeAccessibilityImpl (TC, TL, contextAccessScope,
1533
- context->getDeclContext (),
1580
+ checkTypeAccessibilityImpl (TC, TL, contextAccessScope, DC, isParam,
1534
1581
[=](AccessScope requiredAccessScope,
1535
1582
const TypeRepr *offendingTR) {
1536
1583
auto downgradeToWarning = DowngradeToWarning::No;
@@ -1591,6 +1638,7 @@ static void checkGenericParamAccessibility(TypeChecker &TC,
1591
1638
assert (param->getInherited ().size () == 1 );
1592
1639
checkTypeAccessibilityImpl (TC, param->getInherited ().front (), accessScope,
1593
1640
owner->getDeclContext (),
1641
+ /* isParameter*/ false ,
1594
1642
[&](AccessScope typeAccessScope,
1595
1643
const TypeRepr *thisComplainRepr) {
1596
1644
if (typeAccessScope.isChildOf (minAccessScope) ||
@@ -1618,18 +1666,18 @@ static void checkGenericParamAccessibility(TypeChecker &TC,
1618
1666
case RequirementReprKind::TypeConstraint:
1619
1667
checkTypeAccessibilityImpl (TC, requirement.getSubjectLoc (),
1620
1668
accessScope, owner->getDeclContext (),
1621
- callback);
1669
+ /* isParameter */ false , callback);
1622
1670
checkTypeAccessibilityImpl (TC, requirement.getConstraintLoc (),
1623
1671
accessScope, owner->getDeclContext (),
1624
- callback);
1672
+ /* isParameter */ false , callback);
1625
1673
break ;
1626
1674
case RequirementReprKind::SameType:
1627
1675
checkTypeAccessibilityImpl (TC, requirement.getFirstTypeLoc (),
1628
1676
accessScope, owner->getDeclContext (),
1629
- callback);
1677
+ /* isParameter */ false , callback);
1630
1678
checkTypeAccessibilityImpl (TC, requirement.getSecondTypeLoc (),
1631
1679
accessScope, owner->getDeclContext (),
1632
- callback);
1680
+ /* isParameter */ false , callback);
1633
1681
break ;
1634
1682
}
1635
1683
}
@@ -1975,7 +2023,7 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
1975
2023
bool problemIsElement = false ;
1976
2024
1977
2025
for (auto &P : *SD->getIndices ()) {
1978
- checkTypeAccessibility (TC, P->getTypeLoc (), SD ,
2026
+ checkTypeAccessibility (TC, P->getTypeLoc (), P ,
1979
2027
[&](AccessScope typeAccessScope,
1980
2028
const TypeRepr *thisComplainRepr,
1981
2029
DowngradeToWarning downgradeDiag) {
@@ -2047,7 +2095,7 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
2047
2095
2048
2096
for (auto *PL : fn->getParameterLists ().slice (isTypeContext)) {
2049
2097
for (auto &P : *PL) {
2050
- checkTypeAccessibility (TC, P->getTypeLoc (), fn ,
2098
+ checkTypeAccessibility (TC, P->getTypeLoc (), P ,
2051
2099
[&](AccessScope typeAccessScope,
2052
2100
const TypeRepr *thisComplainRepr,
2053
2101
DowngradeToWarning downgradeDiag) {
0 commit comments