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
18 changes: 10 additions & 8 deletions lib/Sema/ResilienceDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,8 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
}

// Embedded functions can reference non-public decls as they are visible
// to clients. Still report references to decls imported non-publicly
// to enforce access-level on imports.
ImportAccessLevel problematicImport = D->getImportAccessFrom(DC);
if (fragileKind.kind == FragileFunctionKind::EmbeddedAlwaysEmitIntoClient &&
!problematicImport)
// to clients.
if (fragileKind.kind == FragileFunctionKind::EmbeddedAlwaysEmitIntoClient)
return false;

DowngradeToWarning downgradeToWarning = DowngradeToWarning::No;
Expand Down Expand Up @@ -135,6 +132,7 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,

Context.Diags.diagnose(D, diag::resilience_decl_declared_here, D);

ImportAccessLevel problematicImport = D->getImportAccessFrom(DC);
if (problematicImport.has_value() &&
problematicImport->accessLevel < D->getFormalAccess()) {
Context.Diags.diagnose(problematicImport->importLoc,
Expand Down Expand Up @@ -298,6 +296,7 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
}
});

auto fragileKind = where.getFragileFunctionKind();
switch (originKind) {
case DisallowedOriginKind::None:
// The decl does not come from a source that needs to be checked for
Expand Down Expand Up @@ -329,11 +328,15 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
if (reason && reason == ExportabilityReason::AvailableAttribute &&
ctx.LangOpts.LibraryLevel == LibraryLevel::API)
return false;
break;
LLVM_FALLTHROUGH;

case DisallowedOriginKind::ImplementationOnly:
case DisallowedOriginKind::SPIImported:
case DisallowedOriginKind::SPILocal:
if (fragileKind.kind == FragileFunctionKind::EmbeddedAlwaysEmitIntoClient)
return false;
break;

case DisallowedOriginKind::ImplementationOnly:
case DisallowedOriginKind::FragileCxxAPI:
break;
}
Expand All @@ -345,7 +348,6 @@ static bool diagnoseValueDeclRefExportability(SourceLoc loc, const ValueDecl *D,
return false;
}

auto fragileKind = where.getFragileFunctionKind();
if (fragileKind.kind == FragileFunctionKind::None) {
DiagnosticBehavior limit = downgradeToWarning == DowngradeToWarning::Yes
? DiagnosticBehavior::Warning
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ public typealias GenericAliasFromIndirect<T> = (StructFromIndirect, T)

public func globalFunctionFromIndirect() {}
public var globalVariableFromIndirect = 0

@_spi(S) public func spiFunctionFromDirect() {}
182 changes: 182 additions & 0 deletions test/Sema/access-level-and-implementation-only-import-embedded.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
/// Test @_implementationOnly internal import exportability diagnostics in embedded mode.

// RUN: %empty-directory(%t)
// RUN: %target-swift-frontend -emit-module -o %t/indirects.swiftmodule \
// RUN: %S/Inputs/implementation-only-imports/indirects.swift \
// RUN: -swift-version 5 -target arm64-apple-none-macho \
// RUN: -enable-experimental-feature Embedded
// RUN: %target-swift-frontend -emit-module -o %t/directs.swiftmodule -I %t \
// RUN: %S/Inputs/implementation-only-imports/directs.swift \
// RUN: -swift-version 5 -target arm64-apple-none-macho \
// RUN: -enable-experimental-feature Embedded

// RUN: %target-swift-frontend -typecheck -verify -verify-ignore-unrelated %s -I %t \
// RUN: -swift-version 5 -target arm64-apple-none-macho \
// RUN: -enable-experimental-feature Embedded

// REQUIRES: swift_feature_Embedded
// REQUIRES: embedded_stdlib_cross_compiling

@_implementationOnly internal import directs
// expected-warning @-1 {{using '@_implementationOnly' without enabling library evolution for 'main' may lead to instability during execution}}
// expected-note @-2 11 {{struct 'StructFromDirect' imported as 'internal' from 'directs' here}}
// expected-note @-3 6 {{initializer 'init()' imported as 'internal' from 'directs' here}}
import indirects

internal func localInternalFunc() {} // expected-note {{global function 'localInternalFunc()' is not '@usableFromInline' or public}}

@inlinable
public func explicitlyInlinable(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
// expected-error @-3 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}

if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
}

func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an '@inlinable' function}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an '@inlinable' function}}
}
nested()

localInternalFunc() // expected-error {{global function 'localInternalFunc()' is internal and cannot be referenced from an '@inlinable' function}}

explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate() // expected-error {{global function 'implicitlyInlinablePrivate(arg:)' is private and cannot be referenced from an '@inlinable' function}}
explicitNonInliable()
}

public func implicitlyInlinablePublic(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
// expected-error @-3 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}

if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
}

func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
}
nested()

localInternalFunc()

explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}

private func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-note @-2 {{global function 'implicitlyInlinablePrivate(arg:)' is not '@usableFromInline' or public}}
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}

if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
}

func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
// expected-error@-1 {{struct 'StructFromDirect' cannot be used in an embedded function not marked '@_neverEmitIntoClient' because 'directs' was imported implementation-only}}
}
nested()

localInternalFunc()

explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}

@_neverEmitIntoClient
public func explicitNonInliable(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
// expected-error @-3 {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
_ = StructFromDirect()

if (true) {
_ = StructFromDirect()
}

@_neverEmitIntoClient
func nested() {
_ = StructFromDirect()
}
nested()

localInternalFunc()

explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}

@_neverEmitIntoClient
internal func explicitNonInliableInternal(arg: StructFromDirect = StructFromDirect()) {
_ = StructFromDirect()

if (true) {
_ = StructFromDirect()
}

@_neverEmitIntoClient
func nested() {
_ = StructFromDirect()
}
nested()

localInternalFunc()

explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate()
explicitNonInliable()
}

public func legalAccessToIndirect(arg: StructFromIndirect = StructFromIndirect()) {
_ = StructFromIndirect()

if (true) {
_ = StructFromIndirect()
}

func nested() {
_ = StructFromIndirect()
}
nested()
}

public struct ExposedLayoutPublic {
public var publicField: StructFromDirect // expected-error {{property cannot be declared public because its type uses an internal type}}
// expected-error @-1 {{cannot use struct 'StructFromDirect' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'directs' has been imported as implementation-only}}
// expected-note @-2 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}

private var privateField: StructFromDirect
}

private struct ExposedLayoutPrivate {
private var privateField: StructFromDirect
}
51 changes: 20 additions & 31 deletions test/Sema/access-level-import-embedded.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
// REQUIRES: swift_feature_Embedded
// REQUIRES: embedded_stdlib_cross_compiling

@_implementationOnly internal import directs
// expected-warning @-1 {{using '@_implementationOnly' without enabling library evolution for 'main' may lead to instability during execution}}
// expected-note @-2 19 {{struct 'StructFromDirect' imported as 'internal' from 'directs' here}}
// expected-note @-3 12 {{initializer 'init()' imported as 'internal' from 'directs' here}}
internal import directs
// expected-note @-1 11 {{struct 'StructFromDirect' imported as 'internal' from 'directs' here}}
// expected-note @-2 6 {{initializer 'init()' imported as 'internal' from 'directs' here}}
import indirects

internal func localInternalFunc() {} // expected-note {{global function 'localInternalFunc()' is not '@usableFromInline' or public}}
Expand Down Expand Up @@ -50,27 +49,23 @@ public func explicitlyInlinable(arg: StructFromDirect = StructFromDirect()) {

explicitlyInlinable()
implicitlyInlinablePublic()
implicitlyInlinablePrivate() // expected-error {{global function 'implicitlyInlinablePrivate(arg:)' is private and cannot be referenced from an '@inlinable' function}}
implicitlyInlinablePrivate() // expected-error {{global function 'implicitlyInlinablePrivate(arg:)' is internal and cannot be referenced from an '@inlinable' function}}
explicitNonInliable()
}

public func implicitlyInlinablePublic(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
// expected-error @-3 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error @-3 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-4 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
_ = StructFromDirect()

if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
_ = StructFromDirect()
}

func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
_ = StructFromDirect()
}
nested()

Expand All @@ -82,20 +77,16 @@ public func implicitlyInlinablePublic(arg: StructFromDirect = StructFromDirect()
explicitNonInliable()
}

private func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-note @-2 {{global function 'implicitlyInlinablePrivate(arg:)' is not '@usableFromInline' or public}}
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
internal func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect()) {
// expected-note @-1 {{global function 'implicitlyInlinablePrivate(arg:)' is not '@usableFromInline' or public}}
_ = StructFromDirect()

if (true) {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
_ = StructFromDirect()
}

func nested() {
_ = StructFromDirect() // expected-error {{initializer 'init()' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
// expected-error@-1 {{struct 'StructFromDirect' is internal and cannot be referenced from an embedded function not marked '@_neverEmitIntoClient'}}
_ = StructFromDirect()
}
nested()

Expand All @@ -111,9 +102,8 @@ private func implicitlyInlinablePrivate(arg: StructFromDirect = StructFromDirect
public func explicitNonInliable(arg: StructFromDirect = StructFromDirect()) {
// expected-error @-1 {{initializer 'init()' is internal and cannot be referenced from a default argument value}}
// expected-error @-2 {{struct 'StructFromDirect' is internal and cannot be referenced from a default argument value}}
// expected-error @-3 {{cannot use struct 'StructFromDirect' here; 'directs' has been imported as implementation-only}}
// expected-error @-4 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-5 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
// expected-error @-3 {{function cannot be declared public because its parameter uses an internal type}}
// expected-note @-4 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
_ = StructFromDirect()

if (true) {
Expand Down Expand Up @@ -171,12 +161,11 @@ public func legalAccessToIndirect(arg: StructFromIndirect = StructFromIndirect()

public struct ExposedLayoutPublic {
public var publicField: StructFromDirect // expected-error {{property cannot be declared public because its type uses an internal type}}
// expected-error @-1 {{cannot use struct 'StructFromDirect' in a property declaration marked public or in a '@frozen' or '@usableFromInline' context; 'directs' has been imported as implementation-only}}
// expected-note @-2 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}
// expected-note @-1 {{struct 'StructFromDirect' is imported by this file as 'internal' from 'directs'}}

private var privateField: StructFromDirect
internal var privateField: StructFromDirect
}

private struct ExposedLayoutPrivate {
private var privateField: StructFromDirect
internal struct ExposedLayoutPrivate {
internal var privateField: StructFromDirect
}
Loading