@@ -1145,7 +1145,7 @@ class AccessScopeChecker {
11451145 Cache(caches[File]),
11461146 Scope(AccessScope::getPublic()) {}
11471147
1148- bool visitDecl (ValueDecl *VD) {
1148+ bool visitDecl (ValueDecl *VD, bool isInParameter = false ) {
11491149 if (!VD || isa<GenericTypeParamDecl>(VD))
11501150 return true ;
11511151
@@ -1156,11 +1156,22 @@ class AccessScopeChecker {
11561156 return true ;
11571157 }
11581158
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+ }
11641175
11651176 auto cached = Cache.find (VD);
11661177 if (cached != Cache.end ()) {
@@ -1179,27 +1190,52 @@ class AccessScopeChecker {
11791190};
11801191
11811192class TypeReprAccessScopeChecker : private ASTWalker , AccessScopeChecker {
1193+ SmallVector<const TypeRepr *, 4 > ParamParents;
1194+
11821195 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+ }
11851206
11861207 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+ }
11901223
1191- return visitDecl (CITR-> getBoundDecl ()) ;
1224+ return true ;
11921225 }
11931226
11941227 bool walkToTypeReprPost (TypeRepr *TR) override {
1228+ if (isParamParent (TR))
1229+ ParamParents.pop_back ();
11951230 return Scope.hasValue ();
11961231 }
11971232
11981233public:
11991234 static Optional<AccessScope>
12001235 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);
12031239 TR->walk (checker);
12041240 return checker.Scope ;
12051241 }
@@ -1262,7 +1298,8 @@ void TypeChecker::computeDefaultAccessibility(ExtensionDecl *ED) {
12621298 auto accessScope =
12631299 TypeReprAccessScopeChecker::getAccessScope (TL.getTypeRepr (),
12641300 ED->getDeclContext (),
1265- TypeAccessScopeCache);
1301+ TypeAccessScopeCache,
1302+ /* isParameter*/ false );
12661303 // This is an error case and will be diagnosed elsewhere.
12671304 if (!accessScope.hasValue ())
12681305 return Accessibility::Public;
@@ -1475,7 +1512,7 @@ enum class DowngradeToWarning: bool {
14751512// / is never null.
14761513static void checkTypeAccessibilityImpl (
14771514 TypeChecker &TC, TypeLoc TL, AccessScope contextAccessScope,
1478- const DeclContext *useDC,
1515+ const DeclContext *useDC, bool isParameter,
14791516 llvm::function_ref<void (AccessScope, const TypeRepr *)> diagnose) {
14801517 if (!TC.getLangOpts ().EnableAccessControl )
14811518 return ;
@@ -1493,7 +1530,8 @@ static void checkTypeAccessibilityImpl(
14931530 auto typeAccessScope =
14941531 (TL.getTypeRepr ()
14951532 ? TypeReprAccessScopeChecker::getAccessScope (TL.getTypeRepr (), useDC,
1496- TC.TypeAccessScopeCache )
1533+ TC.TypeAccessScopeCache ,
1534+ isParameter)
14971535 : TypeAccessScopeChecker::getAccessScope (TL.getType (), useDC,
14981536 TC.TypeAccessScopeCache ));
14991537
@@ -1528,9 +1566,18 @@ static void checkTypeAccessibility(
15281566 TypeChecker &TC, TypeLoc TL, const ValueDecl *context,
15291567 llvm::function_ref<void (AccessScope, const TypeRepr *,
15301568 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+
15311579 AccessScope contextAccessScope = context->getFormalAccessScope ();
1532- checkTypeAccessibilityImpl (TC, TL, contextAccessScope,
1533- context->getDeclContext (),
1580+ checkTypeAccessibilityImpl (TC, TL, contextAccessScope, DC, isParam,
15341581 [=](AccessScope requiredAccessScope,
15351582 const TypeRepr *offendingTR) {
15361583 auto downgradeToWarning = DowngradeToWarning::No;
@@ -1591,6 +1638,7 @@ static void checkGenericParamAccessibility(TypeChecker &TC,
15911638 assert (param->getInherited ().size () == 1 );
15921639 checkTypeAccessibilityImpl (TC, param->getInherited ().front (), accessScope,
15931640 owner->getDeclContext (),
1641+ /* isParameter*/ false ,
15941642 [&](AccessScope typeAccessScope,
15951643 const TypeRepr *thisComplainRepr) {
15961644 if (typeAccessScope.isChildOf (minAccessScope) ||
@@ -1618,18 +1666,18 @@ static void checkGenericParamAccessibility(TypeChecker &TC,
16181666 case RequirementReprKind::TypeConstraint:
16191667 checkTypeAccessibilityImpl (TC, requirement.getSubjectLoc (),
16201668 accessScope, owner->getDeclContext (),
1621- callback);
1669+ /* isParameter */ false , callback);
16221670 checkTypeAccessibilityImpl (TC, requirement.getConstraintLoc (),
16231671 accessScope, owner->getDeclContext (),
1624- callback);
1672+ /* isParameter */ false , callback);
16251673 break ;
16261674 case RequirementReprKind::SameType:
16271675 checkTypeAccessibilityImpl (TC, requirement.getFirstTypeLoc (),
16281676 accessScope, owner->getDeclContext (),
1629- callback);
1677+ /* isParameter */ false , callback);
16301678 checkTypeAccessibilityImpl (TC, requirement.getSecondTypeLoc (),
16311679 accessScope, owner->getDeclContext (),
1632- callback);
1680+ /* isParameter */ false , callback);
16331681 break ;
16341682 }
16351683 }
@@ -1975,7 +2023,7 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
19752023 bool problemIsElement = false ;
19762024
19772025 for (auto &P : *SD->getIndices ()) {
1978- checkTypeAccessibility (TC, P->getTypeLoc (), SD ,
2026+ checkTypeAccessibility (TC, P->getTypeLoc (), P ,
19792027 [&](AccessScope typeAccessScope,
19802028 const TypeRepr *thisComplainRepr,
19812029 DowngradeToWarning downgradeDiag) {
@@ -2047,7 +2095,7 @@ static void checkAccessibility(TypeChecker &TC, const Decl *D) {
20472095
20482096 for (auto *PL : fn->getParameterLists ().slice (isTypeContext)) {
20492097 for (auto &P : *PL) {
2050- checkTypeAccessibility (TC, P->getTypeLoc (), fn ,
2098+ checkTypeAccessibility (TC, P->getTypeLoc (), P ,
20512099 [&](AccessScope typeAccessScope,
20522100 const TypeRepr *thisComplainRepr,
20532101 DowngradeToWarning downgradeDiag) {
0 commit comments