Skip to content

Commit 883fc5b

Browse files
committed
Check access control for the generic requirements of typealiases.
Also oops. This one was a little more involved because the requirements on a generic typealias don't always carry a Type anymore; sometimes all you have is the TypeRepr. That should still be okay in practice as long as we don't start doing that for var/let, which can have part of a type be inferred but not all of it.
1 parent b4e476e commit 883fc5b

File tree

4 files changed

+32
-19
lines changed

4 files changed

+32
-19
lines changed

lib/Sema/TypeCheckAccess.cpp

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -162,29 +162,30 @@ void AccessControlCheckerBase::checkTypeAccessImpl(
162162
llvm::function_ref<CheckTypeAccessCallback> diagnose) {
163163
if (TC.Context.isAccessControlDisabled())
164164
return;
165-
if (!type)
166-
return;
167165
// Don't spend time checking local declarations; this is always valid by the
168166
// time we get to this point.
169167
if (!contextAccessScope.isPublic() &&
170168
contextAccessScope.getDeclContext()->isLocalContext())
171169
return;
172170

173-
Optional<AccessScope> typeAccessScope =
174-
TypeAccessScopeChecker::getAccessScope(type, useDC,
175-
checkUsableFromInline);
176-
auto downgradeToWarning = DowngradeToWarning::No;
171+
AccessScope problematicAccessScope = AccessScope::getPublic();
172+
if (type) {
173+
Optional<AccessScope> typeAccessScope =
174+
TypeAccessScopeChecker::getAccessScope(type, useDC,
175+
checkUsableFromInline);
177176

178-
// Note: This means that the type itself is invalid for this particular
179-
// context, because it references declarations from two incompatible scopes.
180-
// In this case we should have diagnosed the bad reference already.
181-
if (!typeAccessScope.hasValue())
182-
return;
177+
// Note: This means that the type itself is invalid for this particular
178+
// context, because it references declarations from two incompatible scopes.
179+
// In this case we should have diagnosed the bad reference already.
180+
if (!typeAccessScope.hasValue())
181+
return;
182+
problematicAccessScope = *typeAccessScope;
183+
}
183184

184-
AccessScope problematicAccessScope = *typeAccessScope;
185+
auto downgradeToWarning = DowngradeToWarning::No;
185186

186-
if (contextAccessScope.hasEqualDeclContextWith(*typeAccessScope) ||
187-
contextAccessScope.isChildOf(*typeAccessScope)) {
187+
if (contextAccessScope.hasEqualDeclContextWith(problematicAccessScope) ||
188+
contextAccessScope.isChildOf(problematicAccessScope)) {
188189

189190
// /Also/ check the TypeRepr, if present. This can be important when we're
190191
// unable to preserve typealias sugar that's present in the TypeRepr.
@@ -194,7 +195,9 @@ void AccessControlCheckerBase::checkTypeAccessImpl(
194195
Optional<AccessScope> typeReprAccessScope =
195196
TypeReprAccessScopeChecker::getAccessScope(typeRepr, useDC,
196197
checkUsableFromInline);
197-
assert(typeReprAccessScope && "valid Type but not valid TypeRepr?");
198+
if (!typeReprAccessScope.hasValue())
199+
return;
200+
198201
if (contextAccessScope.hasEqualDeclContextWith(*typeReprAccessScope) ||
199202
contextAccessScope.isChildOf(*typeReprAccessScope)) {
200203
// Only if both the Type and the TypeRepr follow the access rules can
@@ -365,8 +368,8 @@ void AccessControlCheckerBase::checkGenericParamAccess(
365368
if (minAccessScope.isPublic())
366369
return;
367370

368-
// FIXME: Promote this to an error in the next -swift-version break.
369-
if (isa<SubscriptDecl>(owner))
371+
// FIXME: Promote these to an error in the next -swift-version break.
372+
if (isa<SubscriptDecl>(owner) || isa<TypeAliasDecl>(owner))
370373
downgradeToWarning = DowngradeToWarning::Yes;
371374

372375
if (checkUsableFromInline) {
@@ -542,6 +545,8 @@ class AccessControlChecker : public AccessControlCheckerBase,
542545
}
543546

544547
void visitTypeAliasDecl(TypeAliasDecl *TAD) {
548+
checkGenericParamAccess(TAD->getGenericParams(), TAD);
549+
545550
checkTypeAccess(TAD->getUnderlyingTypeLoc(), TAD, /*mayBeInferred*/false,
546551
[&](AccessScope typeAccessScope,
547552
const TypeRepr *complainRepr,
@@ -1128,6 +1133,8 @@ class UsableFromInlineChecker : public AccessControlCheckerBase,
11281133
}
11291134

11301135
void visitTypeAliasDecl(TypeAliasDecl *TAD) {
1136+
checkGenericParamAccess(TAD->getGenericParams(), TAD);
1137+
11311138
checkTypeAccess(TAD->getUnderlyingTypeLoc(), TAD, /*mayBeInferred*/false,
11321139
[&](AccessScope typeAccessScope,
11331140
const TypeRepr *complainRepr,

test/IDE/print_ast_tc_decls.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,5 +1375,5 @@ public typealias MyPairI<B> = MyPair<Int, B>
13751375
// PASS_PRINT_AST: public typealias MyPairI<B> = MyPair<Int, B>
13761376
public typealias MyPairAlias<T, U> = MyPair<T, U>
13771377
// PASS_PRINT_AST: public typealias MyPairAlias<T, U> = MyPair<T, U>
1378-
public typealias MyPairAlias2<T: FooProtocol, U> = MyPair<T, U> where U: BarProtocol
1379-
// PASS_PRINT_AST: public typealias MyPairAlias2<T, U> = MyPair<T, U> where T : FooProtocol, U : BarProtocol
1378+
typealias MyPairAlias2<T: FooProtocol, U> = MyPair<T, U> where U: BarProtocol
1379+
// PASS_PRINT_AST: typealias MyPairAlias2<T, U> = MyPair<T, U> where T : FooProtocol, U : BarProtocol

test/Sema/accessibility.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -876,3 +876,6 @@ public struct TestGenericSubscripts {
876876
public subscript<T: PrivateProto>(_: T) -> Int { return 0 } // expected-warning {{subscript should not be declared public because its generic parameter uses a private type}} {{none}}
877877
public subscript<T>(where _: T) -> Int where T: PrivateProto { return 0 } // expected-warning {{subscript should not be declared public because its generic requirement uses a private type}} {{none}}
878878
}
879+
880+
public typealias TestGenericAlias<T: PrivateProto> = T // expected-warning {{type alias should not be declared public because its generic parameter uses a private type}}
881+
public typealias TestGenericAliasWhereClause<T> = T where T: PrivateProto // expected-warning {{type alias should not be declared public because its generic requirement uses a private type}}

test/attr/attr_usableFromInline.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,6 @@ public struct TestGenericSubscripts {
152152
@usableFromInline subscript<T: InternalProtocol>(_: T) -> Int { return 0 } // expected-warning {{type referenced from a generic parameter of a '@usableFromInline' subscript should be '@usableFromInline' or public}}
153153
@usableFromInline subscript<T>(where _: T) -> Int where T: InternalProtocol { return 0 } // expected-warning {{type referenced from a generic requirement of a '@usableFromInline' subscript should be '@usableFromInline' or public}}
154154
}
155+
156+
@usableFromInline typealias TestGenericAlias<T: InternalProtocol> = T // expected-warning {{type referenced from a generic parameter of a '@usableFromInline' type alias should be '@usableFromInline' or public}}
157+
@usableFromInline typealias TestGenericAliasWhereClause<T> = T where T: InternalProtocol // expected-warning {{type referenced from a generic requirement of a '@usableFromInline' type alias should be '@usableFromInline' or public}}

0 commit comments

Comments
 (0)