@@ -1134,67 +1134,96 @@ static void configureImplicitSelf(TypeChecker &tc,
1134
1134
1135
1135
namespace {
1136
1136
1137
- class TypeAccessScopeChecker : private TypeWalker {
1138
- using TypeAccessScopeCacheMap = TypeChecker::TypeAccessScopeCacheMap;
1139
- TypeAccessScopeCacheMap &Cache;
1137
+ class AccessScopeChecker {
1140
1138
const SourceFile *File;
1141
- SmallVector<Optional<AccessScope>, 8 > RawScopeStack ;
1139
+ TypeChecker::TypeAccessScopeCacheMap &Cache ;
1142
1140
1143
- explicit TypeAccessScopeChecker (TypeAccessScopeCacheMap &cache,
1144
- const SourceFile *file)
1145
- : Cache(cache), File(file) {
1146
- // Always have something on the stack.
1147
- RawScopeStack.push_back (None);
1148
- }
1141
+ protected:
1142
+ Optional<AccessScope> Scope;
1143
+
1144
+ AccessScopeChecker (const DeclContext *useDC,
1145
+ decltype (TypeChecker::TypeAccessScopeCache) &caches)
1146
+ : File(useDC->getParentSourceFile ()), Cache(caches[File]),
1147
+ Scope(AccessScope::getPublic()) {}
1149
1148
1150
- bool shouldVisitOriginalSubstitutedType () override { return true ; }
1149
+ bool visitDecl (ValueDecl *VD) {
1150
+ if (!VD || isa<GenericTypeParamDecl>(VD))
1151
+ return true ;
1151
1152
1152
- Action walkToTypePre (Type ty) override {
1153
- // Assume failure until we post-visit this node.
1154
- // This will be correct as long as we don't ever have self-referential
1155
- // Types.
1156
- auto cached = Cache.find (ty);
1153
+ // FIXME: Figure out why AssociatedTypeDecls don't always have
1154
+ // accessibility here.
1155
+ if (!VD->hasAccessibility ()) {
1156
+ if (isa<AssociatedTypeDecl>(VD))
1157
+ return true ;
1158
+ }
1159
+
1160
+ auto cached = Cache.find (VD);
1157
1161
if (cached != Cache.end ()) {
1158
- Optional<AccessScope> &last = RawScopeStack.back ();
1159
- if (last.hasValue ())
1160
- last = last.getValue ().intersectWith (cached->second );
1161
- return Action::SkipChildren;
1162
+ Scope = Scope->intersectWith (cached->second );
1163
+ return Scope.hasValue ();
1162
1164
}
1163
1165
1164
- auto AS = AccessScope::getPublic ();
1165
- if (auto alias = dyn_cast<NameAliasType>(ty.getPointer ()))
1166
- AS = alias->getDecl ()->getFormalAccessScope (File);
1167
- else if (auto nominal = ty->getAnyNominal ())
1168
- AS = nominal->getFormalAccessScope (File);
1169
- RawScopeStack.push_back (AS);
1166
+ auto AS = VD->getFormalAccessScope (File);
1167
+ auto result = Cache.insert (std::make_pair (VD, AS));
1168
+ assert (result.second );
1169
+ (void ) result;
1170
1170
1171
- return Action::Continue;
1171
+ Scope = Scope->intersectWith (AS);
1172
+ return Scope.hasValue ();
1172
1173
}
1174
+ };
1173
1175
1174
- Action walkToTypePost (Type ty) override {
1175
- Optional<AccessScope> last = RawScopeStack. pop_back_val ();
1176
- if (last. hasValue ()) {
1177
- Cache. insert ( std::make_pair (ty, *last));
1176
+ class TypeReprAccessScopeChecker : private ASTWalker , AccessScopeChecker {
1177
+ TypeReprAccessScopeChecker ( const DeclContext *useDC,
1178
+ decltype (TypeChecker::TypeAccessScopeCache) &caches)
1179
+ : AccessScopeChecker(useDC, caches) {}
1178
1180
1179
- Optional<AccessScope> &prev = RawScopeStack.back ();
1180
- if (prev.hasValue ())
1181
- prev = prev.getValue ().intersectWith (*last);
1182
- }
1181
+ bool walkToTypeReprPre (TypeRepr *TR) override {
1182
+ auto CITR = dyn_cast<ComponentIdentTypeRepr>(TR);
1183
+ if (!CITR)
1184
+ return true ;
1185
+
1186
+ return visitDecl (CITR->getBoundDecl ());
1187
+ }
1183
1188
1184
- return Action::Continue;
1189
+ bool walkToTypeReprPost (TypeRepr *TR) override {
1190
+ return Scope.hasValue ();
1185
1191
}
1186
1192
1187
1193
public:
1188
1194
static Optional<AccessScope>
1189
- getAccessScope (Type ty , const DeclContext *useDC,
1195
+ getAccessScope (TypeRepr *TR , const DeclContext *useDC,
1190
1196
decltype (TypeChecker::TypeAccessScopeCache) &caches) {
1191
- const SourceFile *file = useDC->getParentSourceFile ();
1192
- auto &cache = caches[file];
1193
- ty.walk (TypeAccessScopeChecker (cache, file));
1194
- auto iter = cache.find (ty);
1195
- if (iter == cache.end ())
1196
- return None;
1197
- return iter->second ;
1197
+ TypeReprAccessScopeChecker checker (useDC, caches);
1198
+ TR->walk (checker);
1199
+ return checker.Scope ;
1200
+ }
1201
+ };
1202
+
1203
+ class TypeAccessScopeChecker : private TypeWalker , AccessScopeChecker {
1204
+ TypeAccessScopeChecker (const DeclContext *useDC,
1205
+ decltype (TypeChecker::TypeAccessScopeCache) &caches)
1206
+ : AccessScopeChecker(useDC, caches) {}
1207
+
1208
+ Action walkToTypePre (Type T) {
1209
+ ValueDecl *VD;
1210
+ if (auto *TAD = dyn_cast<NameAliasType>(T.getPointer ()))
1211
+ VD = TAD->getDecl ();
1212
+ else if (auto *NTD = T->getAnyNominal ())
1213
+ VD = NTD;
1214
+ else
1215
+ VD = nullptr ;
1216
+
1217
+ return visitDecl (VD) ? Action::Continue : Action::Stop;
1218
+ }
1219
+
1220
+ public:
1221
+ static Optional<AccessScope>
1222
+ getAccessScope (Type T, const DeclContext *useDC,
1223
+ decltype (TypeChecker::TypeAccessScopeCache) &caches) {
1224
+ TypeAccessScopeChecker checker (useDC, caches);
1225
+ T.walk (checker);
1226
+ return checker.Scope ;
1198
1227
}
1199
1228
};
1200
1229
@@ -1223,9 +1252,9 @@ void TypeChecker::computeDefaultAccessibility(ExtensionDecl *ED) {
1223
1252
if (!TL.getType ())
1224
1253
return Accessibility::Public;
1225
1254
auto accessScope =
1226
- TypeAccessScopeChecker ::getAccessScope (TL.getType (),
1227
- ED->getDeclContext (),
1228
- TypeAccessScopeCache);
1255
+ TypeReprAccessScopeChecker ::getAccessScope (TL.getTypeRepr (),
1256
+ ED->getDeclContext (),
1257
+ TypeAccessScopeCache);
1229
1258
// This is an error case and will be diagnosed elsewhere.
1230
1259
if (!accessScope.hasValue ())
1231
1260
return Accessibility::Public;
@@ -1406,6 +1435,8 @@ class TypeAccessScopeDiagnoser : private ASTWalker {
1406
1435
const DeclContext *useDC) {
1407
1436
assert (!accessScope.isPublic () &&
1408
1437
" why would we need to find a public access scope?" );
1438
+ if (TR == nullptr )
1439
+ return nullptr ;
1409
1440
TypeAccessScopeDiagnoser diagnoser (accessScope, useDC);
1410
1441
TR->walk (diagnoser);
1411
1442
return diagnoser.offendingType ;
@@ -1446,9 +1477,15 @@ static void checkTypeAccessibilityImpl(
1446
1477
contextAccessScope.getDeclContext ()->isLocalContext ())
1447
1478
return ;
1448
1479
1480
+ // TypeRepr checking is more accurate, but we must also look at TypeLocs
1481
+ // without a TypeRepr, for example for 'var' declarations with an inferred
1482
+ // type.
1449
1483
auto typeAccessScope =
1450
- TypeAccessScopeChecker::getAccessScope (TL.getType (), useDC,
1451
- TC.TypeAccessScopeCache );
1484
+ (TL.getTypeRepr ()
1485
+ ? TypeReprAccessScopeChecker::getAccessScope (TL.getTypeRepr (), useDC,
1486
+ TC.TypeAccessScopeCache )
1487
+ : TypeAccessScopeChecker::getAccessScope (TL.getType (), useDC,
1488
+ TC.TypeAccessScopeCache ));
1452
1489
1453
1490
// Note: This means that the type itself is invalid for this particular
1454
1491
// context, because it references declarations from two incompatible scopes.
@@ -1461,12 +1498,11 @@ static void checkTypeAccessibilityImpl(
1461
1498
contextAccessScope.isChildOf (*typeAccessScope))
1462
1499
return ;
1463
1500
1464
- const TypeRepr *complainRepr = nullptr ;
1465
- if (TypeRepr *TR = TL.getTypeRepr ()) {
1466
- complainRepr =
1467
- TypeAccessScopeDiagnoser::findTypeWithScope (TR, *typeAccessScope,
1468
- useDC);
1469
- }
1501
+ const TypeRepr *complainRepr =
1502
+ TypeAccessScopeDiagnoser::findTypeWithScope (
1503
+ TL.getTypeRepr (),
1504
+ *typeAccessScope,
1505
+ useDC);
1470
1506
diagnose (*typeAccessScope, complainRepr);
1471
1507
}
1472
1508
0 commit comments