Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,24 @@ namespace swift {
Complete,
};

/// Access or distribution level of a library.
/// Intended distribution level of a module.
///
/// Ordered from more private to more public.
enum class LibraryLevel : uint8_t {
/// Application Programming Interface that is publicly distributed so
/// public decls are really public and only @_spi decls are SPI.
API,

/// System Programming Interface that has restricted distribution
/// all decls in the module are considered to be SPI including public ones.
SPI,
/// This isn't a library or the library distribution intent is unknown.
Other,

/// Internal Programming Interface that is not distributed and only usable
/// from within a project.
/// Internal Programming Interface: the module is not distributed and
/// only usable from within its project.
IPI,

/// The library has some other undefined distribution.
Other
/// System Programming Interface: the module has restricted distribution,
/// all public decls in the module are considered to be SPI.
SPI,

/// Application Programming Interface: the module is distributed publicly,
/// public decls are really public and only @_spi decls are SPI.
API,
};

enum class AccessNoteDiagnosticBehavior : uint8_t {
Expand Down
17 changes: 10 additions & 7 deletions lib/Sema/ImportResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -908,21 +908,24 @@ void UnboundImport::validateResilience(NullablePtr<ModuleDecl> topLevelModule,
targetName, importerName);

if (ctx.LangOpts.hasFeature(Feature::InternalImportsByDefault)) {
// This will catch Swift 6 language mode as well where
// it will be reported as an error.
inFlight.fixItRemove(import.accessLevelRange);
} else {
SourceRange attrRange = import.accessLevelRange;
if (attrRange.isValid())
inFlight.fixItReplace(attrRange, "internal");
else
inFlight.fixItInsert(import.importLoc, "internal ");

// Downgrade to warning only in pre-Swift 6 mode and
// when not using the experimental flag.
if (!ctx.LangOpts.hasFeature(Feature::AccessLevelOnImport))
inFlight.limitBehavior(DiagnosticBehavior::Warning);
}

// Report as an error when InternalImportsByDefault is enabled or
// the experimental AccessLevelOnImport (but not Swift 6), only in libraries
// that are meant to be distributed.
auto featureEnabled =
ctx.LangOpts.hasFeature(Feature::AccessLevelOnImport) ||
ctx.LangOpts.hasFeature(Feature::InternalImportsByDefault);
if (!featureEnabled ||
SF.getParentModule()->getLibraryLevel() < LibraryLevel::SPI)
inFlight.limitBehavior(DiagnosticBehavior::Warning);
}

void UnboundImport::diagnoseInvalidAttr(DeclAttrKind attrKind,
Expand Down
32 changes: 29 additions & 3 deletions test/ModuleInterface/imports-swift7.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,31 @@
// RUN: %target-swift-frontend -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -emit-module -o %t/nonResilient.swiftmodule %t/empty.swift
// RUN: %target-swift-frontend -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -emit-module -o %t/resilient.swiftmodule %t/empty.swift -enable-library-evolution

/// Check errors.
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/clientWithError.swift -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -I %t -verify -enable-upcoming-feature InternalImportsByDefault
/// Warning vs error on public import of a non-LE module from LE.
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) \
// RUN: %t/clientWithError.swift -I %t -verify \
// RUN: -disable-implicit-concurrency-module-import \
// RUN: -disable-implicit-string-processing-module-import \
// RUN: -enable-upcoming-feature InternalImportsByDefault \
// RUN: -verify-additional-prefix library-level-private-
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) \
// RUN: %t/clientWithError.swift -I %t -verify \
// RUN: -disable-implicit-concurrency-module-import \
// RUN: -disable-implicit-string-processing-module-import \
// RUN: -enable-upcoming-feature InternalImportsByDefault \
// RUN: -verify-additional-prefix library-level-private- -library-level ipi
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) \
// RUN: %t/clientWithError.swift -I %t -verify \
// RUN: -disable-implicit-concurrency-module-import \
// RUN: -disable-implicit-string-processing-module-import \
// RUN: -enable-upcoming-feature InternalImportsByDefault \
// RUN: -verify-additional-prefix library-level-public- -library-level spi
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) \
// RUN: %t/clientWithError.swift -I %t -verify \
// RUN: -disable-implicit-concurrency-module-import \
// RUN: -disable-implicit-string-processing-module-import \
// RUN: -enable-upcoming-feature InternalImportsByDefault \
// RUN: -verify-additional-prefix library-level-public- -library-level api

/// Check Swift 7 imports printed in swiftinterface from 2 source files.
// RUN: %target-swift-emit-module-interface(%t.swiftinterface) %t/main.swift %t/main-other.swift -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -I %S/Inputs/imports-clang-modules/ -I %t -verify -enable-upcoming-feature InternalImportsByDefault
Expand Down Expand Up @@ -38,8 +61,11 @@ public import D // expected-warning {{public import of 'D' was not used in publi
public import NotSoSecret // expected-warning {{'NotSoSecret' inconsistently imported as implementation-only}}
// expected-warning @-1 {{public import of 'NotSoSecret' was not used in public declarations or inlinable code}}
@_implementationOnly import NotSoSecret2 // expected-note {{imported as implementation-only here}}

//--- clientWithError.swift
@_exported public import nonResilient // expected-error {{module 'nonResilient' was not compiled with library evolution support; using it means binary compatibility for 'clientWithError' can't be guaranteed}}
@_exported public import nonResilient
// expected-library-level-public-error @-1 {{module 'nonResilient' was not compiled with library evolution support; using it means binary compatibility for 'clientWithError' can't be guaranteed}}
// expected-library-level-private-warning @-2 {{module 'nonResilient' was not compiled with library evolution support; using it means binary compatibility for 'clientWithError' can't be guaranteed}}

// CHECK-7-NOT: import
// CHECK-7: {{^}}public import A{{$}}
Expand Down
19 changes: 10 additions & 9 deletions test/Sema/access-level-and-non-resilient-import.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,25 @@
// RUN: %target-swift-frontend -emit-module %t/PrivateLib.swift -o %t

/// A resilient client will error on public imports.
/// Keep AccessLevelOnImport to get the error from Swift 6 in Swift 5.
/// Use AccessLevelOnImport or InternalImportsByDefault to get the error
/// from Swift 7 in Swift 5.
// RUN: %target-swift-frontend -typecheck %t/Client_Swift5.swift -I %t \
// RUN: -enable-library-evolution -swift-version 5 \
// RUN: -enable-experimental-feature AccessLevelOnImport -verify \
// RUN: -package-name pkg
// RUN: %target-swift-frontend -typecheck %t/Client_Swift6.swift -I %t \
// RUN: -package-name pkg -library-level api
// RUN: %target-swift-frontend -typecheck %t/Client_Swift7.swift -I %t \
// RUN: -enable-library-evolution \
// RUN: -enable-upcoming-feature InternalImportsByDefault \
// RUN: -verify -package-name pkg
// RUN: -verify -package-name pkg -library-level api

/// A non-resilient client doesn't complain.
// RUN: %target-swift-frontend -typecheck %t/Client_Swift5.swift -I %t \
// RUN: -swift-version 5 \
// RUN: -enable-experimental-feature AccessLevelOnImport \
// RUN: -package-name pkg
// RUN: %target-swift-frontend -typecheck %t/Client_Swift6.swift -I %t \
// RUN: -package-name pkg -library-level api
// RUN: %target-swift-frontend -typecheck %t/Client_Swift7.swift -I %t \
// RUN: -enable-upcoming-feature InternalImportsByDefault \
// RUN: -package-name pkg
// RUN: -package-name pkg -library-level api

// REQUIRES: swift_feature_AccessLevelOnImport
// REQUIRES: swift_feature_InternalImportsByDefault
Expand All @@ -53,10 +54,10 @@ internal import InternalLib
fileprivate import FileprivateLib
private import PrivateLib

//--- Client_Swift6.swift
//--- Client_Swift7.swift

import DefaultLib
public import PublicLib // expected-error {{module 'PublicLib' was not compiled with library evolution support; using it means binary compatibility for 'Client_Swift6' can't be guaranteed}} {{1-8=}}
public import PublicLib // expected-error {{module 'PublicLib' was not compiled with library evolution support; using it means binary compatibility for 'Client_Swift7' can't be guaranteed}} {{1-8=}}
// expected-warning @-1 {{public import of 'PublicLib' was not used in public declarations or inlinable code}}
package import PackageLib
// expected-warning @-1 {{package import of 'PackageLib' was not used in package declarations}}
Expand Down