Skip to content

Commit 1c012c8

Browse files
authored
Merge pull request #73161 from apple/elsh/pkg-export
[Sema] Handle package exportability.
2 parents ef5aae1 + c4251d2 commit 1c012c8

17 files changed

+607
-177
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2290,32 +2290,32 @@ ERROR(pattern_type_not_usable_from_inline,none,
22902290
"type referenced from a '@usableFromInline' "
22912291
"%select{%select{variable|constant}0|property}1 "
22922292
"must be '@usableFromInline' or public",
2293-
(bool, bool))
2293+
(bool, bool, /*ignored*/bool))
22942294
WARNING(pattern_type_not_usable_from_inline_warn,none,
22952295
"type referenced from a '@usableFromInline' "
22962296
"%select{%select{variable|constant}0|property}1 "
22972297
"should be '@usableFromInline' or public",
2298-
(bool, bool))
2298+
(bool, bool, /*ignored*/bool))
22992299
ERROR(pattern_type_not_usable_from_inline_frozen,none,
2300-
"type referenced from a stored property in a '@frozen' struct must "
2301-
"be '@usableFromInline' or public",
2302-
(/*ignored*/bool, /*ignored*/bool))
2300+
"type referenced from a stored property in a '@frozen%select{| package}2' struct must "
2301+
"be '@usableFromInline'%select{ or public|, public, or package}2",
2302+
(/*ignored*/bool, /*ignored*/bool, bool))
23032303
ERROR(pattern_type_not_usable_from_inline_inferred,none,
23042304
"type referenced from a '@usableFromInline' "
23052305
"%select{%select{variable|constant}0|property}1 "
23062306
"with inferred type %2 "
23072307
"must be '@usableFromInline' or public",
2308-
(bool, bool, Type))
2308+
(bool, bool, Type, /*ignored*/bool))
23092309
WARNING(pattern_type_not_usable_from_inline_inferred_warn,none,
23102310
"type referenced from a '@usableFromInline' "
23112311
"%select{%select{variable|constant}0|property}1 "
23122312
"with inferred type %2 "
23132313
"should be '@usableFromInline' or public",
2314-
(bool, bool, Type))
2314+
(bool, bool, Type, /*ignored*/bool))
23152315
ERROR(pattern_type_not_usable_from_inline_inferred_frozen,none,
23162316
"type referenced from a stored property with inferred type %2 in a "
2317-
"'@frozen' struct must be '@usableFromInline' or public",
2318-
(/*ignored*/bool, /*ignored*/bool, Type))
2317+
"'@frozen%select{| package}3' struct must be '@usableFromInline'%select{ or public|, public, or package}3",
2318+
(/*ignored*/bool, /*ignored*/bool, Type, bool))
23192319

23202320
ERROR(pattern_binds_no_variables,none,
23212321
"%select{property|global variable}0 declaration does not bind any "
@@ -3630,14 +3630,18 @@ ERROR(decl_from_hidden_module,none,
36303630
"cannot use %kind0 %select{here|as property wrapper here|"
36313631
"as result builder here|"
36323632
"in an extension with public or '@usableFromInline' members|"
3633+
"in an extension with conditional conformances|"
3634+
"in an extension with public, package, or '@usableFromInline' members|"
36333635
"in an extension with conditional conformances}1; "
36343636
"%select{%2 has been imported as implementation-only|"
36353637
"it is an SPI imported from %2|"
36363638
"it is SPI|"
36373639
"%2 was imported for SPI only|"
36383640
"%2 was not imported by this file|"
36393641
"C++ types from imported module %2 do not support library evolution|"
3640-
"%2 was not imported publicly}3",
3642+
"%2 was not imported publicly|"
3643+
"%2 was imported as package}3"
3644+
"%select{||||| or as package| or as package}1",
36413645
(const Decl *, unsigned, Identifier, unsigned))
36423646
ERROR(typealias_desugars_to_type_from_hidden_module,none,
36433647
"%0 aliases '%1.%2' and cannot be used %select{here|"
@@ -3651,7 +3655,8 @@ ERROR(typealias_desugars_to_type_from_hidden_module,none,
36513655
"%4 was imported for SPI only|"
36523656
"%4 was not imported by this file|"
36533657
"C++ types from imported module %4 do not support library evolution|"
3654-
"%4 was not imported publicly}5",
3658+
"%4 was not imported publicly|"
3659+
"%4 was imported as package}5",
36553660
(const TypeAliasDecl *, StringRef, StringRef, unsigned, Identifier, unsigned))
36563661
ERROR(conformance_from_implementation_only_module,none,
36573662
"cannot use conformance of %0 to %1 %select{here|as property wrapper here|"
@@ -3664,7 +3669,8 @@ ERROR(conformance_from_implementation_only_module,none,
36643669
"%3 was imported for SPI only|"
36653670
"%3 was not imported by this file|"
36663671
"C++ types from imported module %3 do not support library evolution|"
3667-
"%3 was not imported publicly}4",
3672+
"%3 was not imported publicly|"
3673+
"%3 was imported as package}4",
36683674
(Type, Identifier, unsigned, Identifier, unsigned))
36693675
NOTE(assoc_conformance_from_implementation_only_module,none,
36703676
"in associated type %0 (inferred as %1)", (Type, Type))
@@ -6888,7 +6894,8 @@ ERROR(inlinable_decl_ref_from_hidden_module,
68886894
"%2 was imported for SPI only|"
68896895
"%2 was not imported by this file|"
68906896
"C++ APIs from imported module %2 do not support library evolution|"
6891-
"%2 was not imported publicly}3",
6897+
"%2 was not imported publicly|"
6898+
"%2 was imported as package}3",
68926899
(const ValueDecl *, unsigned, Identifier, unsigned))
68936900

68946901
WARNING(inlinable_decl_ref_from_hidden_module_warn,
@@ -6906,7 +6913,8 @@ ERROR(inlinable_typealias_desugars_to_type_from_hidden_module,
69066913
"%4 was imported for SPI only|"
69076914
"%4 was not imported by this file|"
69086915
"C++ types from imported module %4 do not support library evolution|"
6909-
"%4 was not imported publicly}5",
6916+
"%4 was not imported publicly|"
6917+
"%4 was imported as package}5",
69106918
(const TypeAliasDecl *, StringRef, StringRef, unsigned, Identifier, unsigned))
69116919

69126920
NOTE(missing_import_inserted,
@@ -6920,8 +6928,8 @@ ERROR(availability_macro_in_inlinable, none,
69206928
#undef FRAGILE_FUNC_KIND
69216929

69226930
NOTE(resilience_decl_declared_here,
6923-
none, "%kind0 is not '@usableFromInline' or public",
6924-
(const ValueDecl *))
6931+
none, "%kind0 is not '@usableFromInline'%select{ or public|, public, or package}1",
6932+
(const ValueDecl *, bool))
69256933

69266934
ERROR(class_designated_init_inlinable_resilient,none,
69276935
"initializer for class %0 is "

include/swift/AST/SourceFile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,10 @@ class SourceFile final : public FileUnit {
431431
void setImportUsedPreconcurrency(
432432
AttributedImport<ImportedModule> import);
433433

434+
/// True if the highest access level of the declarations referencing
435+
/// this import in signature or inlinable code is internal or less.
436+
bool isMaxAccessLevelUsingImportInternal(AttributedImport<ImportedModule> import) const;
437+
434438
/// Return the highest access level of the declarations referencing
435439
/// this import in signature or inlinable code.
436440
AccessLevel

lib/AST/Decl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,7 +2324,7 @@ bool VarDecl::isLayoutExposedToClients() const {
23242324
auto nominalAccess =
23252325
parent->getFormalAccessScope(/*useDC=*/nullptr,
23262326
/*treatUsableFromInlineAsPublic=*/true);
2327-
if (!nominalAccess.isPublic()) return false;
2327+
if (!nominalAccess.isPublicOrPackage()) return false;
23282328

23292329
if (!parent->getAttrs().hasAttribute<FrozenAttr>() &&
23302330
!parent->getAttrs().hasAttribute<FixedLayoutAttr>())
@@ -4571,8 +4571,10 @@ bool ValueDecl::isMoreVisibleThan(ValueDecl *other) const {
45714571

45724572
if (scope.isPublic())
45734573
return !otherScope.isPublic();
4574+
else if (scope.isPackage())
4575+
return !otherScope.isPublicOrPackage();
45744576
else if (scope.isInternal())
4575-
return !otherScope.isPublic() && !otherScope.isInternal();
4577+
return !otherScope.isPublicOrPackage() && !otherScope.isInternal();
45764578
else
45774579
return false;
45784580
}

lib/AST/DeclContext.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
467467
auto effectiveAccess =
468468
VD->getFormalAccessScope(/*useDC=*/nullptr,
469469
/*treatUsableFromInlineAsPublic=*/true);
470-
if (effectiveAccess.isPublic()) {
470+
if (effectiveAccess.isPublicOrPackage()) {
471471
return {FragileFunctionKind::DefaultArgument};
472472
}
473473

@@ -499,7 +499,7 @@ swift::FragileFunctionKindRequest::evaluate(Evaluator &evaluator,
499499

500500
// If the function is not externally visible, we will not be serializing
501501
// its body.
502-
if (!funcAccess.isPublic()) {
502+
if (!funcAccess.isPublicOrPackage()) {
503503
return {FragileFunctionKind::None};
504504
}
505505

lib/AST/Module.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2650,6 +2650,12 @@ void SourceFile::setImportUsedPreconcurrency(
26502650
PreconcurrencyImportsUsed.insert(import);
26512651
}
26522652

2653+
bool SourceFile::isMaxAccessLevelUsingImportInternal(
2654+
AttributedImport<ImportedModule> import) const {
2655+
auto maxLevel = getMaxAccessLevelUsingImport(import.module.importedModule);
2656+
return maxLevel < AccessLevel::Package;
2657+
}
2658+
26532659
AccessLevel
26542660
SourceFile::getMaxAccessLevelUsingImport(
26552661
const ModuleDecl *mod) const {

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 86 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,22 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
6666
ImportAccessLevel problematicImport = D->getImportAccessFrom(DC);
6767
if (problematicImport.has_value()) {
6868
auto SF = DC->getParentSourceFile();
69-
if (SF)
70-
SF->registerAccessLevelUsingImport(problematicImport.value(),
71-
AccessLevel::Public);
72-
73-
if (Context.LangOpts.EnableModuleApiImportRemarks) {
74-
ModuleDecl *importedVia = problematicImport->module.importedModule,
75-
*sourceModule = D->getModuleContext();
76-
Context.Diags.diagnose(loc, diag::module_api_import,
77-
D, importedVia, sourceModule,
78-
importedVia == sourceModule,
79-
/*isImplicit*/false);
69+
if (SF) {
70+
// The max used access level previously registered might be Package,
71+
// in which case, don't reset it to Public here; this ensures proper
72+
// diags between public and package.
73+
if (SF->isMaxAccessLevelUsingImportInternal(problematicImport.value()))
74+
SF->registerAccessLevelUsingImport(problematicImport.value(),
75+
AccessLevel::Public);
76+
77+
if (Context.LangOpts.EnableModuleApiImportRemarks) {
78+
ModuleDecl *importedVia = problematicImport->module.importedModule,
79+
*sourceModule = D->getModuleContext();
80+
Context.Diags.diagnose(loc, diag::module_api_import,
81+
D, importedVia, sourceModule,
82+
importedVia == sourceModule,
83+
/*isImplicit*/false);
84+
}
8085
}
8186
}
8287

@@ -100,6 +105,16 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
100105
}
101106

102107
DowngradeToWarning downgradeToWarning = DowngradeToWarning::No;
108+
// Don't change the order of the getDisallowedOriginKind call;
109+
// it can reset downgradeToWarning to NO so needs to be called here.
110+
auto originKind = getDisallowedOriginKind(D, where, downgradeToWarning);
111+
// For a default argument or property initializer, package type is
112+
// allowed at the use site with package access scope.
113+
auto allowedForPkgCtx = false;
114+
if (originKind == DisallowedOriginKind::None ||
115+
originKind == DisallowedOriginKind::PackageImport) {
116+
allowedForPkgCtx = where.isPackage() && declAccessScope.isPackage();
117+
}
103118

104119
// Swift 4.2 did not perform any checks for type aliases.
105120
if (isa<TypeAliasDecl>(D)) {
@@ -119,15 +134,17 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
119134
if (isa<TypeAliasDecl>(DC) && !Context.isSwiftVersionAtLeast(6))
120135
downgradeToWarning = DowngradeToWarning::Yes;
121136

122-
auto diagID = diag::resilience_decl_unavailable;
123-
if (downgradeToWarning == DowngradeToWarning::Yes)
124-
diagID = diag::resilience_decl_unavailable_warn;
137+
if (!allowedForPkgCtx) {
138+
auto diagID = diag::resilience_decl_unavailable;
139+
if (downgradeToWarning == DowngradeToWarning::Yes)
140+
diagID = diag::resilience_decl_unavailable_warn;
125141

126-
AccessLevel diagAccessLevel = declAccessScope.accessLevelForDiagnostics();
127-
Context.Diags.diagnose(loc, diagID, D, diagAccessLevel,
128-
fragileKind.getSelector());
142+
AccessLevel diagAccessLevel = declAccessScope.accessLevelForDiagnostics();
143+
Context.Diags.diagnose(loc, diagID, D, diagAccessLevel,
144+
fragileKind.getSelector());
129145

130-
Context.Diags.diagnose(D, diag::resilience_decl_declared_here, D);
146+
Context.Diags.diagnose(D, diag::resilience_decl_declared_here, D, allowedForPkgCtx);
147+
}
131148

132149
if (problematicImport.has_value() &&
133150
problematicImport->accessLevel < D->getFormalAccess()) {
@@ -156,10 +173,14 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc,
156173
where.getDeclContext());
157174
if (problematicImport.has_value()) {
158175
auto SF = where.getDeclContext()->getParentSourceFile();
159-
if (SF)
160-
SF->registerAccessLevelUsingImport(problematicImport.value(),
161-
AccessLevel::Public);
162-
176+
if (SF) {
177+
// The max used access level previously registered might be Package,
178+
// in which case, don't reset it to Public here; this ensures proper
179+
// diags between public and package.
180+
if (SF->isMaxAccessLevelUsingImportInternal(problematicImport.value()))
181+
SF->registerAccessLevelUsingImport(problematicImport.value(),
182+
AccessLevel::Public);
183+
}
163184
if (ctx.LangOpts.EnableModuleApiImportRemarks) {
164185
ModuleDecl *importedVia = problematicImport->module.importedModule,
165186
*sourceModule = D->getModuleContext();
@@ -186,7 +207,8 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc,
186207
auto definingModule = D->getModuleContext();
187208
auto fragileKind = where.getFragileFunctionKind();
188209
bool warnPreSwift6 = originKind != DisallowedOriginKind::SPIOnly &&
189-
originKind != DisallowedOriginKind::NonPublicImport;
210+
originKind != DisallowedOriginKind::PackageImport &&
211+
originKind != DisallowedOriginKind::InternalOrLessImport;
190212
if (fragileKind.kind == FragileFunctionKind::None) {
191213
auto reason = where.getExportabilityReason();
192214
ctx.Diags
@@ -211,7 +233,8 @@ static bool diagnoseTypeAliasDeclRefExportability(SourceLoc loc,
211233
addMissingImport(loc, D, where);
212234

213235
// If limited by an import, note which one.
214-
if (originKind == DisallowedOriginKind::NonPublicImport) {
236+
if (originKind == DisallowedOriginKind::InternalOrLessImport ||
237+
originKind == DisallowedOriginKind::PackageImport) {
215238
const DeclContext *DC = where.getDeclContext();
216239
ImportAccessLevel limitImport = D->getImportAccessFrom(DC);
217240
assert(limitImport.has_value() &&
@@ -242,22 +265,31 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
242265
ImportAccessLevel import = D->getImportAccessFrom(DC);
243266
if (import.has_value() && reason.has_value()) {
244267
auto SF = DC->getParentSourceFile();
245-
if (SF)
246-
SF->registerAccessLevelUsingImport(import.value(),
247-
AccessLevel::Public);
268+
if (SF) {
269+
// The max used access level previously registered might be Package,
270+
// in which case, don't reset it to Public here; this ensures proper
271+
// diags between public and package.
272+
if (SF->isMaxAccessLevelUsingImportInternal(import.value()))
273+
SF->registerAccessLevelUsingImport(import.value(),
274+
AccessLevel::Public);
275+
}
248276
}
249277

250278
// Access levels from imports are reported with the others access levels.
251279
// Except for extensions, we report them here.
252-
if (originKind == DisallowedOriginKind::NonPublicImport &&
253-
reason != ExportabilityReason::ExtensionWithPublicMembers &&
254-
reason != ExportabilityReason::ExtensionWithConditionalConformances)
255-
return false;
280+
if (originKind == DisallowedOriginKind::InternalOrLessImport ||
281+
originKind == DisallowedOriginKind::PackageImport) {
282+
if (reason != ExportabilityReason::ExtensionWithPublicMembers &&
283+
reason != ExportabilityReason::ExtensionWithPackageMembers &&
284+
reason != ExportabilityReason::ExtensionWithConditionalConformances &&
285+
reason != ExportabilityReason::ExtensionWithPackageConditionalConformances)
286+
return false;
287+
}
256288

257289
if (ctx.LangOpts.EnableModuleApiImportRemarks &&
258290
import.has_value() && where.isExported() &&
259291
reason != ExportabilityReason::General &&
260-
originKind != DisallowedOriginKind::NonPublicImport) {
292+
originKind != DisallowedOriginKind::InternalOrLessImport) {
261293
// These may be reported twice, for the Type and for the TypeRepr.
262294
ModuleDecl *importedVia = import->module.importedModule,
263295
*sourceModule = D->getModuleContext();
@@ -270,6 +302,14 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
270302
if (originKind == DisallowedOriginKind::None)
271303
return false;
272304

305+
// No diags needed for extensions with package members or
306+
// conformance to types with package access scope.
307+
if (originKind == DisallowedOriginKind::PackageImport) {
308+
if (reason == ExportabilityReason::ExtensionWithPackageMembers ||
309+
reason == ExportabilityReason::ExtensionWithPackageConditionalConformances)
310+
return false;
311+
}
312+
273313
auto diagName = D->getName();
274314
if (auto accessor = dyn_cast<AccessorDecl>(D)) {
275315
// Only diagnose accessors if their disallowed origin kind differs from
@@ -313,7 +353,8 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
313353
}
314354

315355
// If limited by an import, note which one.
316-
if (originKind == DisallowedOriginKind::NonPublicImport) {
356+
if (originKind == DisallowedOriginKind::InternalOrLessImport ||
357+
originKind == DisallowedOriginKind::PackageImport) {
317358
assert(import.has_value() &&
318359
import->accessLevel < AccessLevel::Public &&
319360
"The import should still be non-public");
@@ -362,10 +403,14 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
362403
ImportAccessLevel problematicImport = ext->getImportAccessFrom(where.getDeclContext());
363404
if (problematicImport.has_value()) {
364405
auto SF = where.getDeclContext()->getParentSourceFile();
365-
if (SF)
366-
SF->registerAccessLevelUsingImport(problematicImport.value(),
367-
AccessLevel::Public);
368-
406+
if (SF) {
407+
// The max used access level previously registered might be Package,
408+
// in which case, don't reset it to Public here; this ensures proper
409+
// diags between public and package.
410+
if (SF->isMaxAccessLevelUsingImportInternal(problematicImport.value()))
411+
SF->registerAccessLevelUsingImport(problematicImport.value(),
412+
AccessLevel::Public);
413+
}
369414
if (ctx.LangOpts.EnableModuleApiImportRemarks) {
370415
ModuleDecl *importedVia = problematicImport->module.importedModule,
371416
*sourceModule = ext->getModuleContext();
@@ -392,7 +437,8 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
392437
static_cast<unsigned>(originKind))
393438
.warnUntilSwiftVersionIf((warnIfConformanceUnavailablePreSwift6 &&
394439
originKind != DisallowedOriginKind::SPIOnly &&
395-
originKind != DisallowedOriginKind::NonPublicImport) ||
440+
originKind != DisallowedOriginKind::PackageImport &&
441+
originKind != DisallowedOriginKind::InternalOrLessImport) ||
396442
originKind == DisallowedOriginKind::MissingImport,
397443
6);
398444

@@ -401,7 +447,8 @@ TypeChecker::diagnoseConformanceExportability(SourceLoc loc,
401447
addMissingImport(loc, ext, where);
402448

403449
// If limited by an import, note which one.
404-
if (originKind == DisallowedOriginKind::NonPublicImport) {
450+
if (originKind == DisallowedOriginKind::InternalOrLessImport ||
451+
originKind == DisallowedOriginKind::PackageImport) {
405452
const DeclContext *DC = where.getDeclContext();
406453
ImportAccessLevel limitImport = ext->getImportAccessFrom(DC);
407454
assert(limitImport.has_value() &&

0 commit comments

Comments
 (0)