Skip to content

Commit 1a1df7e

Browse files
committed
[Sema] Apply import restriction in TypeAccessScopeChecker's AccessScope
This cleans up the logic and allows using `private` imported declarations in `fileprivate` declarations.
1 parent fca9a91 commit 1a1df7e

5 files changed

+37
-76
lines changed

lib/Sema/TypeAccessScopeChecker.h

+4-25
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ class TypeAccessScopeChecker {
3131
bool TreatUsableFromInlineAsPublic;
3232

3333
llvm::Optional<AccessScope> Scope = AccessScope::getPublic();
34-
ImportAccessLevel ImportRestriction = llvm::None;
3534

3635
TypeAccessScopeChecker(const DeclContext *useDC,
3736
bool treatUsableFromInlineAsPublic)
@@ -44,41 +43,22 @@ class TypeAccessScopeChecker {
4443

4544
auto AS = VD->getFormalAccessScope(File, TreatUsableFromInlineAsPublic);
4645
Scope = Scope->intersectWith(AS);
47-
48-
auto targetModule = VD->getDeclContext()->getParentModule();
49-
if (targetModule != File->getParentModule()) {
50-
auto localImportRestriction = File->getImportAccessLevel(targetModule);
51-
52-
if (localImportRestriction.has_value() &&
53-
(!ImportRestriction.has_value() ||
54-
localImportRestriction.value().accessLevel <
55-
ImportRestriction.value().accessLevel)) {
56-
ImportRestriction = localImportRestriction;
57-
}
58-
}
59-
6046
return Scope.has_value();
6147
}
6248

6349
public:
6450

65-
struct Result {
66-
llvm::Optional<AccessScope> Scope;
67-
ImportAccessLevel Import;
68-
};
69-
70-
static Result
51+
static llvm::Optional<AccessScope>
7152
getAccessScope(TypeRepr *TR, const DeclContext *useDC,
7253
bool treatUsableFromInlineAsPublic = false) {
7354
TypeAccessScopeChecker checker(useDC, treatUsableFromInlineAsPublic);
7455
TR->walk(TypeReprIdentFinder([&](const IdentTypeRepr *typeRepr) {
7556
return checker.visitDecl(typeRepr->getBoundDecl());
7657
}));
77-
return {checker.Scope,
78-
checker.ImportRestriction};
58+
return checker.Scope;
7959
}
8060

81-
static Result
61+
static llvm::Optional<AccessScope>
8262
getAccessScope(Type T, const DeclContext *useDC,
8363
bool treatUsableFromInlineAsPublic = false) {
8464
TypeAccessScopeChecker checker(useDC, treatUsableFromInlineAsPublic);
@@ -88,8 +68,7 @@ class TypeAccessScopeChecker {
8868
return TypeWalker::Action::Stop;
8969
}));
9070

91-
return {checker.Scope,
92-
checker.ImportRestriction};
71+
return checker.Scope;
9372
}
9473
};
9574

lib/Sema/TypeCheckAccess.cpp

+8-25
Original file line numberDiff line numberDiff line change
@@ -196,62 +196,46 @@ void AccessControlCheckerBase::checkTypeAccessImpl(
196196
ImportAccessLevel problematicImport = llvm::None;
197197

198198
if (type) {
199-
auto scopeAndImport =
199+
llvm::Optional<AccessScope> typeAccessScope =
200200
TypeAccessScopeChecker::getAccessScope(type, useDC,
201201
checkUsableFromInline);
202202

203203
// Note: This means that the type itself is invalid for this particular
204204
// context, because it references declarations from two incompatible scopes.
205205
// In this case we should have diagnosed the bad reference already.
206-
llvm::Optional<AccessScope> typeAccessScope = scopeAndImport.Scope;
207206
if (!typeAccessScope.has_value())
208207
return;
209208

210-
problematicImport = scopeAndImport.Import;
211209
problematicAccessScope = *typeAccessScope;
212210
}
213211

214212
auto downgradeToWarning = DowngradeToWarning::No;
215213

216-
AccessLevel importAccessLevel = AccessLevel::Public;
217-
if (problematicImport.has_value())
218-
importAccessLevel = problematicImport->accessLevel;
219-
220214
// Check if type can be referenced in this context.
221215
// - hasEqualDeclContextWith checks for matching scopes (public to public,
222-
// internal to the same module, private to same scope, etc.)
216+
// internal to the same module, private to same scope, etc.)
223217
// - isChildOf checks for use of public in internal, etc.
224-
// - Comparison to importAccessLevel ensures the type access scope isn't
225-
// restricted by an access-level on an import.
226-
if ((contextAccessScope.hasEqualDeclContextWith(problematicAccessScope) ||
227-
contextAccessScope.isChildOf(problematicAccessScope)) &&
228-
contextAccessScope.accessLevelForDiagnostics() <= importAccessLevel) {
218+
if (contextAccessScope.hasEqualDeclContextWith(problematicAccessScope) ||
219+
contextAccessScope.isChildOf(problematicAccessScope)) {
229220

230221
// /Also/ check the TypeRepr, if present. This can be important when we're
231222
// unable to preserve typealias sugar that's present in the TypeRepr.
232223
if (!typeRepr)
233224
return;
234225

235-
auto typeReprAccessScopeAndImport =
226+
auto typeReprAccessScope =
236227
TypeAccessScopeChecker::getAccessScope(typeRepr, useDC,
237228
checkUsableFromInline);
238-
auto typeReprAccessScope = typeReprAccessScopeAndImport.Scope;
239229
if (!typeReprAccessScope.has_value())
240230
return;
241231

242-
if (typeReprAccessScopeAndImport.Import.has_value())
243-
importAccessLevel = typeReprAccessScopeAndImport.Import->accessLevel;
244-
245-
if ((contextAccessScope.hasEqualDeclContextWith(*typeReprAccessScope) ||
246-
contextAccessScope.isChildOf(*typeReprAccessScope)) &&
247-
contextAccessScope.accessLevelForDiagnostics() <= importAccessLevel) {
232+
if (contextAccessScope.hasEqualDeclContextWith(*typeReprAccessScope) ||
233+
contextAccessScope.isChildOf(*typeReprAccessScope)) {
248234
// Only if both the Type and the TypeRepr follow the access rules can
249235
// we exit; otherwise we have to emit a diagnostic.
250236
return;
251237
}
252238
problematicAccessScope = *typeReprAccessScope;
253-
if (typeReprAccessScopeAndImport.Import.has_value())
254-
problematicImport = typeReprAccessScopeAndImport.Import;
255239
} else {
256240
// The type violates the rules of access control (with or without taking the
257241
// TypeRepr into account).
@@ -268,8 +252,7 @@ void AccessControlCheckerBase::checkTypeAccessImpl(
268252
// Downgrade the error to a warning in this case for source compatibility.
269253
llvm::Optional<AccessScope> typeReprAccessScope =
270254
TypeAccessScopeChecker::getAccessScope(typeRepr, useDC,
271-
checkUsableFromInline)
272-
.Scope;
255+
checkUsableFromInline);
273256
assert(typeReprAccessScope && "valid Type but not valid TypeRepr?");
274257
if (contextAccessScope.hasEqualDeclContextWith(*typeReprAccessScope) ||
275258
contextAccessScope.isChildOf(*typeReprAccessScope)) {

lib/Sema/TypeCheckProtocol.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -3430,8 +3430,7 @@ void ConformanceChecker::recordTypeWitness(AssociatedTypeDecl *assocType,
34303430
// non-resilient modules.
34313431
llvm::Optional<AccessScope> underlyingTypeScope =
34323432
TypeAccessScopeChecker::getAccessScope(type, DC,
3433-
/*usableFromInline*/ false)
3434-
.Scope;
3433+
/*usableFromInline*/ false);
34353434
assert(underlyingTypeScope.has_value() &&
34363435
"the type is already invalid and we shouldn't have gotten here");
34373436

test/Sema/access-level-import-diag-priority.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/// Report the most restricted types when many types are problematic.
22

33
// RUN: %empty-directory(%t)
4-
// RUN: split-file %s %t
4+
// RUN: split-file --leading-lines %s %t
55

66
/// Build the libraries.
77
// RUN: %target-swift-frontend -emit-module %t/PublicLib.swift -o %t
@@ -37,11 +37,11 @@ public struct PrivateImportType {}
3737
public import PublicLib
3838
package import PackageLib // expected-note {{struct 'PackageImportType' imported as 'package' from 'PackageLib' here}}
3939
internal import InternalLib // expected-note {{struct 'InternalImportType' imported as 'internal' from 'InternalLib' here}}
40-
fileprivate import FileprivateLib // expected-note 2 {{struct 'FileprivateImportType' imported as 'fileprivate' from 'FileprivateLib' here}}
41-
private import PrivateLib // expected-note 2 {{struct 'PrivateImportType' imported as 'private' from 'PrivateLib' here}}
40+
fileprivate import FileprivateLib // expected-note 3 {{struct 'FileprivateImportType' imported as 'fileprivate' from 'FileprivateLib' here}}
41+
private import PrivateLib // expected-note 1 {{struct 'PrivateImportType' imported as 'private' from 'PrivateLib' here}}
4242

4343
/// Simple ordering
44-
public func publicFuncUsesPrivate(_ a: PublicImportType, b: PackageImportType, c: InternalImportType, d: FileprivateImportType, e: PrivateImportType) { // expected-error {{function cannot be declared public because its parameter uses a private type}}
44+
public func publicFuncUsesPrivate(_ a: PublicImportType, b: PackageImportType, c: InternalImportType, d: FileprivateImportType, e: PrivateImportType) { // expected-error {{function cannot be declared public because its parameter uses a fileprivate type}}
4545
var _: PrivateImportType
4646
}
4747
public func publicFuncUsesFileprivate(_ a: PublicImportType, b: PackageImportType, c: InternalImportType, d: FileprivateImportType) { // expected-error {{function cannot be declared public because its parameter uses a fileprivate type}}

test/Sema/access-level-import-exportability.swift

+20-20
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: split-file %s %t
2+
// RUN: split-file --leading-lines %s %t
33

44
/// Build the libraries.
55
// RUN: %target-swift-frontend -emit-module %t/PublicLib.swift -o %t \
@@ -129,7 +129,7 @@ public func PublicFuncUsesInternal(_: InternalImportType) { // expected-error {{
129129
var _: InternalImportType
130130
}
131131

132-
public class PublicSubclassFilepriovate : FileprivateImportClass {} // expected-error {{class cannot be declared public because its superclass is fileprivate}}
132+
public class PublicSubclassFileprivate : FileprivateImportClass {} // expected-error {{class cannot be declared public because its superclass is fileprivate}}
133133

134134
/// More complete test.
135135
//--- CompletenessClient.swift
@@ -207,7 +207,7 @@ fileprivate func FileprivateFuncUsesInternal(_: InternalImportType) {
207207
fileprivate func FileprivateFuncUsesFileprivate(_: FileprivateImportType) {
208208
var _: FileprivateImportType
209209
}
210-
fileprivate func FileprivateFuncUsesPrivate(_: PrivateImportType) { // expected-error {{function cannot be declared fileprivate because its parameter uses a private type}}
210+
fileprivate func FileprivateFuncUsesPrivate(_: PrivateImportType) {
211211
var _: PrivateImportType
212212
}
213213

@@ -291,7 +291,7 @@ fileprivate func FileprivateFuncReturnUsesInternal() -> InternalImportType {
291291
fileprivate func FileprivateFuncReturnUsesFileprivate() -> FileprivateImportType {
292292
fatalError()
293293
}
294-
fileprivate func FileprivateFuncReturnUsesPrivate() -> PrivateImportType { // expected-error {{function cannot be declared fileprivate because its result uses a private type}}
294+
fileprivate func FileprivateFuncReturnUsesPrivate() -> PrivateImportType {
295295
fatalError()
296296
}
297297

@@ -415,7 +415,7 @@ fileprivate struct FileprivateSubscriptUsesFileprivate {
415415
}
416416
}
417417
fileprivate struct FileprivateSubscriptUsesPrivate {
418-
fileprivate subscript(index: PrivateImportType) -> PrivateImportType { // expected-error {{subscript cannot be declared fileprivate because its index uses a private type}}
418+
fileprivate subscript(index: PrivateImportType) -> PrivateImportType {
419419
fatalError()
420420
}
421421
}
@@ -462,7 +462,7 @@ public protocol PublicProtoRefinesPrivate: PrivateImportProto {} // expected-err
462462
public class PublicSubclassPublic : PublicImportClass {}
463463
public class PublicSubclassPackage : PackageImportClass {} // expected-error {{class cannot be declared public because its superclass is package}}
464464
public class PublicSubclassInternal : InternalImportClass {} // expected-error {{class cannot be declared public because its superclass is internal}}
465-
public class PublicSubclassFilepriovate : FileprivateImportClass {} // expected-error {{class cannot be declared public because its superclass is fileprivate}}
465+
public class PublicSubclassFileprivate : FileprivateImportClass {} // expected-error {{class cannot be declared public because its superclass is fileprivate}}
466466
public class PublicSubclassPrivate : PrivateImportClass {} // expected-error {{class cannot be declared public because its superclass is private}}
467467

468468

@@ -481,7 +481,7 @@ package protocol PackageProtoRefinesPrivate: PrivateImportProto {} // expected-e
481481
package class PackageSubclassPublic : PublicImportClass {}
482482
package class PackageSubclassPackage : PackageImportClass {}
483483
package class PackageSubclassInternal : InternalImportClass {} // expected-error {{class cannot be declared package because its superclass is internal}}
484-
package class PackageSubclassFilepriovate : FileprivateImportClass {} // expected-error {{class cannot be declared package because its superclass is fileprivate}}
484+
package class PackageSubclassFileprivate : FileprivateImportClass {} // expected-error {{class cannot be declared package because its superclass is fileprivate}}
485485
package class PackageSubclassPrivate : PrivateImportClass {} // expected-error {{class cannot be declared package because its superclass is private}}
486486

487487

@@ -500,27 +500,27 @@ internal protocol InternalProtoRefinesPrivate: PrivateImportProto {} // expected
500500
internal class InternalSubclassPublic : PublicImportClass {}
501501
internal class InternalSubclassPackage : PackageImportClass {}
502502
internal class InternalSubclassInternal : InternalImportClass {}
503-
internal class InternalSubclassFilepriovate : FileprivateImportClass {} // expected-error {{class cannot be declared internal because its superclass is fileprivate}}
503+
internal class InternalSubclassFileprivate : FileprivateImportClass {} // expected-error {{class cannot be declared internal because its superclass is fileprivate}}
504504
internal class InternalSubclassPrivate : PrivateImportClass {} // expected-error {{class cannot be declared internal because its superclass is private}}
505505

506506

507507
fileprivate protocol FileprivateProtoUsesPublic: PublicImportProto where T == PublicImportType {}
508508
fileprivate protocol FileprivateProtoWherePackage: PublicImportProto where T == PackageImportType {}
509509
fileprivate protocol FileprivateProtoWhereInternal: PublicImportProto where T == InternalImportType {}
510510
fileprivate protocol FileprivateProtoWhereFileprivate: PublicImportProto where T == FileprivateImportType {}
511-
fileprivate protocol FileprivateProtoWherePrivate: PublicImportProto where T == PrivateImportType {} // expected-error {{fileprivate protocol's 'where' clause cannot use a private struct}}
511+
fileprivate protocol FileprivateProtoWherePrivate: PublicImportProto where T == PrivateImportType {}
512512

513513
fileprivate protocol FileprivateProtoRefinesPublic: PublicImportProto {}
514514
fileprivate protocol FileprivateProtoRefinesPackage: PackageImportProto {}
515515
fileprivate protocol FileprivateProtoRefinesInternal: InternalImportProto {}
516516
fileprivate protocol FileprivateProtoRefinesFileprivate: FileprivateImportProto {}
517-
fileprivate protocol FileprivateProtoRefinesPrivate: PrivateImportProto {} // expected-error {{fileprivate protocol cannot refine a private protocol}}
517+
fileprivate protocol FileprivateProtoRefinesPrivate: PrivateImportProto {}
518518

519519
fileprivate class FileprivateSubclassPublic : PublicImportClass {}
520520
fileprivate class FileprivateSubclassPackage : PackageImportClass {}
521521
fileprivate class FileprivateSubclassInternal : InternalImportClass {}
522-
fileprivate class FileprivateSubclassFilepriovate : FileprivateImportClass {}
523-
fileprivate class FileprivateSubclassPrivate : PrivateImportClass {} // expected-error {{class cannot be declared fileprivate because its superclass is private}}
522+
fileprivate class FileprivateSubclassFileprivate : FileprivateImportClass {}
523+
fileprivate class FileprivateSubclassPrivate : PrivateImportClass {}
524524

525525

526526
private protocol PrivateProtoUsesPublic: PublicImportProto where T == PublicImportType {}
@@ -538,7 +538,7 @@ private protocol PrivateProtoRefinesPrivate: PrivateImportProto {}
538538
private class PrivateSubclassPublic : PublicImportClass {}
539539
private class PrivateSubclassPackage : PackageImportClass {}
540540
private class PrivateSubclassInternal : InternalImportClass {}
541-
private class PrivateSubclassFilepriovate : FileprivateImportClass {}
541+
private class PrivateSubclassFileprivate : FileprivateImportClass {}
542542
private class PrivateSubclassPrivate : PrivateImportClass {}
543543

544544
public struct PublicTypeAliasUses {
@@ -570,7 +570,7 @@ fileprivate struct FileprivateTypeAliasUses {
570570
fileprivate typealias TAPackage = PackageImportProto
571571
fileprivate typealias TAInternal = InternalImportProto
572572
fileprivate typealias TAFileprivate = FileprivateImportProto
573-
fileprivate typealias TAPrivate = PrivateImportProto // expected-error {{type alias cannot be declared fileprivate because its underlying type uses a private type}}
573+
fileprivate typealias TAPrivate = PrivateImportProto
574574
}
575575

576576
private struct PrivateTypeAliasUses {
@@ -629,13 +629,13 @@ fileprivate protocol FileprivateProtocol {
629629
associatedtype ATDefaultInternal = InternalImportProto
630630
associatedtype ATDefaultFileprivate = FileprivateImportProto
631631
// Accocciated type have a minimum formal access level at internal.
632-
associatedtype ATDefaultPrivate = PrivateImportProto // expected-error {{associated type in an internal protocol uses a private type in its default definition}}
632+
associatedtype ATDefaultPrivate = PrivateImportProto
633633

634634
associatedtype ATRequirePublic: PublicImportProto
635635
associatedtype ATRequirePackage: PackageImportProto
636636
associatedtype ATRequireInternal: InternalImportProto
637637
associatedtype ATRequireFileprivate: FileprivateImportProto
638-
associatedtype ATRequirePrivate: PrivateImportProto // expected-error {{associated type in an internal protocol uses a private type in its requirement}}
638+
associatedtype ATRequirePrivate: PrivateImportProto
639639
}
640640

641641
private protocol PrivateProtocol {
@@ -732,7 +732,7 @@ fileprivate struct FileprivateVars {
732732
fileprivate var b: PackageImportType
733733
fileprivate var c: InternalImportType
734734
fileprivate var d: FileprivateImportType
735-
fileprivate var e: PrivateImportType // expected-error {{property cannot be declared fileprivate because its type uses a private type}}
735+
fileprivate var e: PrivateImportType
736736

737737
@PublicLibWrapper
738738
fileprivate var f: PublicImportType
@@ -743,13 +743,13 @@ fileprivate struct FileprivateVars {
743743
@FileprivateLibWrapper
744744
fileprivate var i: PublicImportType
745745
@PrivateLibWrapper
746-
fileprivate var j: PublicImportType // expected-error {{property cannot be declared fileprivate because its property wrapper type uses a private type}}
746+
fileprivate var j: PublicImportType
747747

748748
fileprivate var k = PublicImportType()
749749
fileprivate var l = PackageImportType()
750750
fileprivate var m = InternalImportType()
751751
fileprivate var n = FileprivateImportType()
752-
fileprivate var o = PrivateImportType() // expected-error {{property cannot be declared fileprivate because its type 'PrivateImportType' uses a private type}}
752+
fileprivate var o = PrivateImportType()
753753
}
754754

755755
private struct PrivateVars {
@@ -799,7 +799,7 @@ fileprivate struct FileprivateGenericUsesPublic<A: PublicImportProto> {}
799799
fileprivate struct FileprivateGenericUsesPackage<A: PackageImportProto> {}
800800
fileprivate struct FileprivateGenericUsesInternal<A: InternalImportProto> {}
801801
fileprivate struct FileprivateGenericUsesFileprivate<A: FileprivateImportProto> {}
802-
fileprivate struct FileprivateGenericUsesPrivate<A: PrivateImportProto> {} // expected-error {{generic struct cannot be declared fileprivate because its generic parameter uses a private type}}
802+
fileprivate struct FileprivateGenericUsesPrivate<A: PrivateImportProto> {}
803803

804804
private struct PrivateGenericUsesPublic<A: PublicImportProto> {}
805805
private struct PrivateGenericUsesPackage<A: PackageImportProto> {}

0 commit comments

Comments
 (0)