Skip to content

Commit fb9f953

Browse files
committed
Integrate fileprivate
The majority of changes here are just plumbing needed to get the compiler to look at the (new!) FilePrivate as the (old!) Private and the (new!) Private as an even more closed-off form the of (old!) Private. The interesting changes are in `lib/AST/NameLookup.cpp` where (new!) private is defined as a declaration where our declcontext and their declcontext have to match or nest. (new!) Private predictably causes quite a lot more dead code elimination to fire in places which has lead to some interesting bugs that I will see about patches for (or at least SRs).
1 parent c4a0c00 commit fb9f953

File tree

93 files changed

+460
-401
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+460
-401
lines changed

docs/AccessControl.rst

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,18 @@ The general guiding principle of Swift access control:
77
**No entity can be defined in terms of another entity that has a lower
88
access level.**
99

10-
There are three levels of access: "private", "internal", and "public".
11-
Private entities can only be accessed from within the source file where they
12-
are defined. Internal entities can be accessed anywhere within the module they
13-
are defined. Public entities can be accessed from anywhere within the module
14-
and from any other context that imports the current module.
10+
There are four levels of access: "private", "fileprivate", "internal", and
11+
"public". Private entities can only be accessed from within the current
12+
declaration where they are defined. FilePrivate entities can only be accessed
13+
from within the source file where they are defined. Internal entities can be
14+
accessed anywhere within the module they are defined. Public entities can be
15+
accessed from anywhere within the module and from any other context that imports
16+
the current module.
1517

1618
The names ``public`` and ``private`` have precedent in many languages;
17-
``internal`` comes from C#. In the future, ``public`` may be used for both API
18-
and SPI, at which point we may design additional annotations to distinguish the
19-
two.
19+
``internal`` comes from C# and ``fileprivate`` from the Swift community. In the
20+
future, ``public`` may be used for both API and SPI, at which point we may
21+
design additional annotations to distinguish the two.
2022

2123
By default, most entities in a source file have ``internal`` access.
2224
This optimizes for the most common case—a single-target application

docs/OptimizationTips.rst

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -134,17 +134,17 @@ in the following ``C.array1`` and ``D.array1`` will be accessed directly
134134
d.array2[i] = ... // Will access D.array2 through dynamic dispatch.
135135
}
136136

137-
Advice: Use 'private' when declaration does not need to be accessed outside of file
138-
-----------------------------------------------------------------------------------
139-
140-
Applying the ``private`` keyword to a declaration restricts the visibility of
141-
the declaration to the file in which it is declared. This allows the compiler to
142-
be able to ascertain all other potentially overriding declarations. Thus the
143-
absence of any such declarations enables the compiler to infer the ``final``
144-
keyword automatically and remove indirect calls for methods and field accesses
145-
accordingly. For instance in the following, ``e.doSomething()`` and
146-
``f.myPrivateVar``, will be able to be accessed directly assuming ``E``, ``F``
147-
do not have any overriding declarations in the same file:
137+
Advice: Use 'private' and 'fileprivate' when declaration does not need to be accessed outside of file
138+
-----------------------------------------------------------------------------------------------------
139+
140+
Applying the ``private`` or ``fileprivate`` keywords to a declaration restricts
141+
the visibility of the declaration to the file in which it is declared. This
142+
allows the compiler to be able to ascertain all other potentially overriding
143+
declarations. Thus the absence of any such declarations enables the compiler to
144+
infer the ``final`` keyword automatically and remove indirect calls for methods
145+
and field accesses accordingly. For instance in the following,
146+
``e.doSomething()`` and ``f.myPrivateVar``, will be able to be accessed directly
147+
assuming ``E``, ``F`` do not have any overriding declarations in the same file:
148148

149149
::
150150

include/swift/AST/Attr.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ DECL_ATTR(private, Accessibility,
192192
OnClass | OnProtocol | OnVar | OnSubscript | OnConstructor |
193193
DeclModifier | NotSerialized,
194194
/* Not serialized */ 46)
195+
DECL_ATTR_ALIAS(fileprivate, Accessibility)
195196
DECL_ATTR_ALIAS(internal, Accessibility)
196197
DECL_ATTR_ALIAS(public, Accessibility)
197198

include/swift/AST/AttrKind.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ enum class UnaryOperatorKind : uint8_t {
4848
/// Access control levels.
4949
// These are used in diagnostics, so please do not reorder existing values.
5050
enum class Accessibility : uint8_t {
51-
/// Private access is limited to the current file.
51+
/// Private access is limited to the current declaration.
5252
Private = 0,
53+
/// FilePrivate access is limited to the current file.
54+
FilePrivate,
5355
/// Internal access is limited to the current module.
5456
Internal,
5557
/// Public access is not limited.

include/swift/AST/Decl.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ class alignas(1 << DeclAlignInBits) Decl {
544544
/// This is encoded as (1 << maxAccess) | (1 << defaultAccess), which
545545
/// works because the maximum is always greater than or equal to the
546546
/// default. 0 represents an uncomputed value.
547-
unsigned DefaultAndMaxAccessLevel : 3;
547+
unsigned DefaultAndMaxAccessLevel : 4;
548548

549549
/// Whether there is an active conformance loader for this
550550
/// extension.
@@ -1701,6 +1701,9 @@ class ExtensionDecl final : public Decl, public DeclContext,
17011701
if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
17021702
(1 << static_cast<unsigned>(Accessibility::Private)))
17031703
return Accessibility::Private;
1704+
if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
1705+
(1 << static_cast<unsigned>(Accessibility::FilePrivate)))
1706+
return Accessibility::FilePrivate;
17041707
if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
17051708
(1 << static_cast<unsigned>(Accessibility::Internal)))
17061709
return Accessibility::Internal;
@@ -1715,6 +1718,9 @@ class ExtensionDecl final : public Decl, public DeclContext,
17151718
if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
17161719
(1 << static_cast<unsigned>(Accessibility::Internal)))
17171720
return Accessibility::Internal;
1721+
if (ExtensionDeclBits.DefaultAndMaxAccessLevel &
1722+
(1 << static_cast<unsigned>(Accessibility::FilePrivate)))
1723+
return Accessibility::FilePrivate;
17181724
return Accessibility::Private;
17191725
}
17201726

@@ -2084,7 +2090,7 @@ class IfConfigDecl : public Decl {
20842090
class ValueDecl : public Decl {
20852091
DeclName Name;
20862092
SourceLoc NameLoc;
2087-
llvm::PointerIntPair<Type, 2, OptionalEnum<Accessibility>> TypeAndAccess;
2093+
llvm::PointerIntPair<Type, 3, OptionalEnum<Accessibility>> TypeAndAccess;
20882094

20892095
protected:
20902096
ValueDecl(DeclKind K,
@@ -3823,8 +3829,8 @@ class AbstractStorageDecl : public ValueDecl {
38233829
void configureObservingRecord(ObservingRecord *record,
38243830
FuncDecl *willSet, FuncDecl *didSet);
38253831

3826-
llvm::PointerIntPair<GetSetRecord*, 2, OptionalEnum<Accessibility>> GetSetInfo;
3827-
llvm::PointerIntPair<BehaviorRecord*, 2, OptionalEnum<Accessibility>>
3832+
llvm::PointerIntPair<GetSetRecord*, 3, OptionalEnum<Accessibility>> GetSetInfo;
3833+
llvm::PointerIntPair<BehaviorRecord*, 3, OptionalEnum<Accessibility>>
38283834
BehaviorInfo;
38293835

38303836
ObservingRecord &getDidSetInfo() const {
@@ -5926,6 +5932,8 @@ inline Accessibility ValueDecl::getEffectiveAccess() const {
59265932
return Accessibility::Public;
59275933
}
59285934
return Accessibility::Internal;
5935+
case Accessibility::FilePrivate:
5936+
return Accessibility::FilePrivate;
59295937
case Accessibility::Private:
59305938
return Accessibility::Private;
59315939
}

include/swift/AST/DiagnosticsSema.def

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,11 @@ ERROR(could_not_use_member_on_existential,none,
105105
(Type, DeclName))
106106

107107
ERROR(candidate_inaccessible,none,
108-
"%0 is inaccessible due to '%select{private|internal|PUBLIC}1' "
108+
"%0 is inaccessible due to '%select{private|fileprivate|internal|PUBLIC}1' "
109109
"protection level", (DeclName, Accessibility))
110110

111111
ERROR(init_candidate_inaccessible,none,
112-
"%0 initializer is inaccessible due to '%select{private|internal|PUBLIC}1' "
112+
"%0 initializer is inaccessible due to '%select{private|fileprivate|internal|PUBLIC}1' "
113113
"protection level", (Type, Accessibility))
114114

115115

@@ -924,34 +924,34 @@ ERROR(attr_methods_only,none,
924924
ERROR(access_control_in_protocol,none,
925925
"%0 modifier cannot be used in protocols", (DeclAttribute))
926926
ERROR(access_control_setter,none,
927-
"'%select{private|internal|public}0(set)' modifier can only be applied "
927+
"'%select{private|fileprivate|internal|public}0(set)' modifier can only be applied "
928928
"to variables and subscripts",
929929
(Accessibility))
930930
ERROR(access_control_setter_read_only,none,
931-
"'%select{private|internal|public}0(set)' modifier cannot be applied to "
931+
"'%select{private|fileprivate|internal|public}0(set)' modifier cannot be applied to "
932932
"%select{constants|read-only variables|read-only properties"
933933
"|read-only subscripts}1",
934934
(Accessibility, unsigned))
935935
ERROR(access_control_setter_more,none,
936-
"%select{private|internal|PUBLIC}0 "
936+
"%select{private|fileprivate|internal|PUBLIC}0 "
937937
"%select{variable|property|subscript}1 cannot have "
938-
"%select{PRIVATE|an internal|a public}2 setter",
938+
"%select{PRIVATE|a fileprivate|an internal|a public}2 setter",
939939
(Accessibility, unsigned, Accessibility))
940940
WARNING(access_control_member_more,none,
941-
"declaring %select{PRIVATE|an internal|a public}0 %1 for "
942-
"%select{a private|an internal|PUBLIC}2 %3",
941+
"declaring %select{PRIVATE|a fileprivate|an internal|a public}0 %1 for "
942+
"%select{a private|a fileprivate|an internal|PUBLIC}2 %3",
943943
(Accessibility, DescriptiveDeclKind, Accessibility, DescriptiveDeclKind))
944944
WARNING(access_control_ext_member_more,none,
945-
"declaring %select{PRIVATE|an internal|a public}0 %1 in "
946-
"%select{a private|an internal|PUBLIC}2 extension",
945+
"declaring %select{PRIVATE|a fileprivate|an internal|a public}0 %1 in "
946+
"%select{a private|a fileprivate|an internal|PUBLIC}2 extension",
947947
(Accessibility, DescriptiveDeclKind, Accessibility))
948948
ERROR(access_control_ext_requirement_member_more,none,
949-
"cannot declare %select{PRIVATE|an internal|a public}0 %1 in "
950-
"an extension with %select{private|internal|PUBLIC}2 requirements",
949+
"cannot declare %select{PRIVATE|a fileprivate|an internal|a public}0 %1 in "
950+
"an extension with %select{private|fileprivate|internal|PUBLIC}2 requirements",
951951
(Accessibility, DescriptiveDeclKind, Accessibility))
952952
ERROR(access_control_extension_more,none,
953-
"extension of %select{private|internal|PUBLIC}0 %1 cannot be "
954-
"declared %select{PRIVATE|internal|public}2",
953+
"extension of %select{private|fileprivate|internal|PUBLIC}0 %1 cannot be "
954+
"declared %select{PRIVATE|fileprivate|internal|public}2",
955955
(Accessibility, DescriptiveDeclKind, Accessibility))
956956

957957
ERROR(invalid_decl_attribute_simple,none,
@@ -1039,15 +1039,15 @@ ERROR(static_requires_initializer,none,
10391039
"expression or getter/setter specifier", (StaticSpellingKind))
10401040
ERROR(pattern_type_access,none,
10411041
"%select{%select{variable|constant}0|property}1 "
1042-
"%select{must be declared %select{private|internal|PUBLIC}4"
1043-
"|cannot be declared %select{PRIVATE|internal|public}3}2 because its "
1044-
"type uses %select{a private|an internal|PUBLIC}4 type",
1042+
"%select{must be declared %select{private|fileprivate|internal|PUBLIC}4"
1043+
"|cannot be declared %select{PRIVATE|fileprivate|internal|public}3}2 because its "
1044+
"type uses %select{a private|a fileprivate|an internal|PUBLIC}4 type",
10451045
(bool, bool, bool, Accessibility, Accessibility))
10461046
ERROR(pattern_type_access_inferred,none,
10471047
"%select{%select{variable|constant}0|property}1 "
1048-
"%select{must be declared %select{private|internal|PUBLIC}4"
1049-
"|cannot be declared %select{PRIVATE|internal|public}3}2 because its "
1050-
"type %5 uses %select{a private|an internal|PUBLIC}4 type",
1048+
"%select{must be declared %select{private|fileprivate|internal|PUBLIC}4"
1049+
"|cannot be declared %select{PRIVATE|fileprivate|internal|public}3}2 because its "
1050+
"type %5 uses %select{a private|a fileprivate|an internal|PUBLIC}4 type",
10511051
(bool, bool, bool, Accessibility, Accessibility, Type))
10521052
ERROR(pattern_binds_no_variables,none,
10531053
"%select{property|global variable}0 declaration does not bind any "
@@ -1070,26 +1070,26 @@ ERROR(unsupported_type_nested_in_generic_function,none,
10701070
ERROR(circular_type_alias,none,
10711071
"type alias %0 circularly references itself", (Identifier))
10721072
ERROR(type_alias_underlying_type_access,none,
1073-
"type alias %select{must be declared %select{private|internal|PUBLIC}2"
1074-
"|cannot be declared %select{PRIVATE|internal|public}1}0 because its "
1075-
"underlying type uses %select{a private|an internal|PUBLIC}2 type",
1073+
"type alias %select{must be declared %select{private|fileprivate|internal|PUBLIC}2"
1074+
"|cannot be declared %select{PRIVATE|fileprivate|internal|public}1}0 because its "
1075+
"underlying type uses %select{a private|a fileprivate|an internal|PUBLIC}2 type",
10761076
(bool, Accessibility, Accessibility))
10771077

10781078
// Subscripts
10791079
ERROR(subscript_type_access,none,
1080-
"subscript %select{must be declared %select{private|internal|PUBLIC}2"
1081-
"|cannot be declared %select{PRIVATE|internal|public}1}0 because its "
1080+
"subscript %select{must be declared %select{private|fileprivate|internal|PUBLIC}2"
1081+
"|cannot be declared %select{PRIVATE|fileprivate|internal|public}1}0 because its "
10821082
"%select{index|element type}3 uses "
1083-
"%select{a private|an internal|PUBLIC}2 type",
1083+
"%select{a private|a fileprivate|an internal|PUBLIC}2 type",
10841084
(bool, Accessibility, Accessibility, bool))
10851085

10861086
// Functions
10871087
ERROR(function_type_access,none,
10881088
"%select{function|method|initializer}3 "
1089-
"%select{must be declared %select{private|internal|PUBLIC}2"
1090-
"|cannot be declared %select{PRIVATE|internal|public}1}0 because its "
1089+
"%select{must be declared %select{private|fileprivate|internal|PUBLIC}2"
1090+
"|cannot be declared %select{PRIVATE|fileprivate|internal|public}1}0 because its "
10911091
"%select{parameter|result}4 uses "
1092-
"%select{a private|an internal|PUBLIC}2 type",
1092+
"%select{a private|a fileprivate|an internal|PUBLIC}2 type",
10931093
(bool, Accessibility, Accessibility, unsigned, bool))
10941094
WARNING(non_trailing_closure_before_default_args,none,
10951095
"closure parameter prior to parameters with default arguments will "
@@ -1191,28 +1191,28 @@ ERROR(witness_requires_dynamic_self,none,
11911191
ERROR(witness_not_accessible_proto,none,
11921192
"%select{initializer %1|method %1|%select{|setter for }2property %1"
11931193
"|subscript%select{| setter}2}0 must be declared "
1194-
"%select{PRIVATE|internal|public}3 because it matches a requirement "
1195-
"in %select{PRIVATE|internal|public}3 protocol %4",
1194+
"%select{PRIVATE|fileprivate|internal|public}3 because it matches a requirement "
1195+
"in %select{PRIVATE|fileprivate|internal|public}3 protocol %4",
11961196
(RequirementKind, DeclName, bool, Accessibility, DeclName))
11971197
ERROR(witness_not_accessible_type,none,
11981198
"%select{initializer %1|method %1|%select{|setter for }2property %1"
11991199
"|subscript%select{| setter}2}0 must be as accessible as its enclosing "
12001200
"type because it matches a requirement in protocol %4",
12011201
(RequirementKind, DeclName, bool, Accessibility, DeclName))
12021202
ERROR(type_witness_not_accessible_proto,none,
1203-
"%0 %1 must be declared %select{PRIVATE|internal|public}2 because it "
1204-
"matches a requirement in %select{PRIVATE|internal|public}2 protocol %3",
1203+
"%0 %1 must be declared %select{PRIVATE|fileprivate|internal|public}2 because it "
1204+
"matches a requirement in %select{PRIVATE|fileprivate|internal|public}2 protocol %3",
12051205
(DescriptiveDeclKind, DeclName, Accessibility, DeclName))
12061206
ERROR(type_witness_not_accessible_type,none,
12071207
"%0 %1 must be as accessible as its enclosing type because it "
12081208
"matches a requirement in protocol %3",
12091209
(DescriptiveDeclKind, DeclName, Accessibility, DeclName))
12101210

12111211
ERROR(protocol_refine_access,none,
1212-
"%select{protocol must be declared %select{private|internal|PUBLIC}2 "
1212+
"%select{protocol must be declared %select{private|fileprivate|internal|PUBLIC}2 "
12131213
"because it refines"
1214-
"|%select{PRIVATE|internal|public}1 protocol cannot refine}0 "
1215-
"%select{a private|an internal|PUBLIC}2 protocol",
1214+
"|%select{PRIVATE|fileprivate|internal|public}1 protocol cannot refine}0 "
1215+
"%select{a private|a fileprivate|an internal|PUBLIC}2 protocol",
12161216
(bool, Accessibility, Accessibility))
12171217
ERROR(protocol_property_must_be_computed_var,none,
12181218
"immutable property requirement must be declared as 'var' with a "
@@ -1240,8 +1240,8 @@ NOTE(default_associated_type_req_fail,none,
12401240
"does not conform to %3",
12411241
(Type, DeclName, Type, Type))
12421242
ERROR(associated_type_access,none,
1243-
"associated type in %select{PRIVATE|an internal|a public}0 protocol "
1244-
"uses %select{a private|an internal|PUBLIC}1 type in its "
1243+
"associated type in %select{PRIVATE|a fileprivate|an internal|a public}0 protocol "
1244+
"uses %select{a private|a fileprivate|an internal|PUBLIC}1 type in its "
12451245
"%select{default definition|requirement}2 ",
12461246
(Accessibility, Accessibility, unsigned))
12471247

@@ -1345,7 +1345,7 @@ NOTE(optional_req_near_match_move,none,
13451345
NOTE(optional_req_near_match_nonobjc,none,
13461346
"add '@nonobjc' to silence this %select{warning|error}0", (bool))
13471347
NOTE(optional_req_near_match_accessibility,none,
1348-
"make %0 %select{ERROR|private|private or internal}1 to silence this "
1348+
"make %0 %select{ERROR|ERROR|fileprivate|fileprivate or internal}1 to silence this "
13491349
"warning", (DeclName, Accessibility))
13501350

13511351
// Protocols and existentials
@@ -1397,10 +1397,10 @@ ERROR(requires_generic_param_same_type_does_not_conform,none,
13971397
(Type, Identifier))
13981398

13991399
ERROR(generic_param_access,none,
1400-
"%0 %select{must be declared %select{private|internal|PUBLIC}3"
1401-
"|cannot be declared %select{PRIVATE|internal|public}2}1 because its "
1400+
"%0 %select{must be declared %select{private|fileprivate|internal|PUBLIC}3"
1401+
"|cannot be declared %select{PRIVATE|fileprivate|internal|public}2}1 because its "
14021402
"generic %select{parameter|requirement}4 uses "
1403-
"%select{a private|an internal|PUBLIC}3 type",
1403+
"%select{a private|a fileprivate|an internal|PUBLIC}3 type",
14041404
(DescriptiveDeclKind, bool, Accessibility, Accessibility, bool))
14051405

14061406
ERROR(override_multiple_decls_base,none,
@@ -1576,8 +1576,8 @@ ERROR(inheritance_from_objc_runtime_visible_class,none,
15761576

15771577
// Enums
15781578
ERROR(enum_case_access,none,
1579-
"enum case in %select{PRIVATE|an internal|a public}0 enum uses "
1580-
"%select{a private|an internal|PUBLIC}1 type",
1579+
"enum case in %select{PRIVATE|a fileprivate|an internal|a public}0 enum uses "
1580+
"%select{a private|a fileprivate|an internal|PUBLIC}1 type",
15811581
(Accessibility, Accessibility))
15821582
ERROR(enum_stored_property,none,
15831583
"enums may not contain stored properties", ())
@@ -1596,9 +1596,9 @@ ERROR(enum_raw_type_not_equatable,none,
15961596
"RawRepresentable 'init' cannot be synthesized because raw type %0 is not "
15971597
"Equatable", (Type))
15981598
ERROR(enum_raw_type_access,none,
1599-
"enum %select{must be declared %select{private|internal|PUBLIC}2"
1600-
"|cannot be declared %select{PRIVATE|internal|public}1}0 because its "
1601-
"raw type uses %select{a private|an internal|PUBLIC}2 type",
1599+
"enum %select{must be declared %select{private|fileprivate|internal|PUBLIC}2"
1600+
"|cannot be declared %select{PRIVATE|fileprivate|internal|public}1}0 because its "
1601+
"raw type uses %select{a private|a fileprivate|an internal|PUBLIC}2 type",
16021602
(bool, Accessibility, Accessibility))
16031603

16041604
NOTE(enum_here,none,
@@ -2490,9 +2490,9 @@ ERROR(self_in_nominal,none,
24902490
"'Self' is only available in a protocol or as the result of a "
24912491
"method in a class; did you mean %0?", (Identifier))
24922492
ERROR(class_super_access,none,
2493-
"class %select{must be declared %select{private|internal|PUBLIC}2"
2494-
"|cannot be declared %select{PRIVATE|internal|public}1}0 because its "
2495-
"superclass is %select{private|internal|PUBLIC}2",
2493+
"class %select{must be declared %select{private|fileprivate|internal|PUBLIC}2"
2494+
"|cannot be declared %select{PRIVATE|fileprivate|internal|public}1}0 because its "
2495+
"superclass is %select{private|fileprivate|internal|PUBLIC}2",
24962496
(bool, Accessibility, Accessibility))
24972497
ERROR(dot_protocol_on_non_existential,none,
24982498
"cannot use 'Protocol' with non-protocol type %0", (Type))

0 commit comments

Comments
 (0)