Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swift 6 mode converts decl_from_hidden_module diagnostics to errors, from warnings #78297

Open
dylansturg opened this issue Dec 19, 2024 · 7 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels

Comments

@dylansturg
Copy link
Contributor

Description

Prior to Swift 6, there has been a warning on public declarations that use a type that is not imported in the current file. This warning is the diagnostic decl_from_hidden_module. I believe this diagnostic is notifying the user about possibly exposing types from a Swift module that doesn't directly import the exposed type.

This became more tightly enforced as an error with Swift 6 mode. Because this is an error, additional imports are required in the source file(s) to satisfy this diagnostic. That is possibly a source breaking change. Is the change in severity intended?

Reproduction

This issue can be reproduced with 3 Swift modules.

  • A module containing a definition of a type: call it decls.
  • A module containing a way to access a type from decls; call it helpers.
  • Finally, a module containing public declarations relying on types from decls; call it api.
// decls.swift
public protocol ExportedP {}
// helpers.swift
import decls
struct Foo: ExportedP {}
public func makeProtocol() -> ExportedP { Foo() }
// api.swift
import helpers
public struct API {
  public let p = makeProtocol()
}

Compile the modules in order: decls, helpers, then api:

  • swiftc -swift-version 6 -emit-module -emit-module-path $BUILD -module-name decls decls.swift
  • swiftc -swift-version 6 -I $BUILD -emit-module -emit-module-path $BUILD -module-name helpers helpers.swift
  • swiftc -swift-version 6 -I $BUILD -emit-module -emit-module-path $BUILD -module-name api api.swift

Expected behavior

I believe this should generate a warning in api.swift:

 cannot use protocol 'ExportedP' here; 'decls' was not imported by this file

Instead the diagnostic is raised as an error when using -swift-version 6. Without swift-version 6, the diagnostic is a warning.

Environment

swift-driver version: 1.115 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2)
Target: arm64-apple-macosx14.0

Additional information

No response

@dylansturg dylansturg added bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels labels Dec 19, 2024
@allevato
Copy link
Member

@xymus @tshortli Was it intended that this would still be an error (and thus a source break) in Swift 6 language mode, since some of the other import-visibility-related changes were pulled back from Swift 6?

@tshortli
Copy link
Contributor

tshortli commented Dec 19, 2024

Yes, it's intentional that these are errors in Swift 6. Access level on imports is a feature available in the Swift 6 compiler, even though InternalImportsByDefault was deferred from the release. These diagnostics are part of ensuring that valid textual .swiftinterface files can be emitted for a module with library evolution enabled.

@allevato
Copy link
Member

Should those still be errors then if the code isn't being built with -enable-library-evolution, as in this example?

@tshortli
Copy link
Contributor

Yes, in general we don't want library evolution to create a language dialect, and the error really makes sense semantically regardless of library evolution mode.

@tshortli
Copy link
Contributor

Can I turn this around and ask why it being an error a problem? It should be very simple to resolve (just add the missing import), and new language modes are often leveraged as the opportunity to fix existing gaps in type checking.

@allevato
Copy link
Member

It's not that I disagree with the error or what it's going for (and I agree that we don't want library evolution to be a dialect). I was just surprised because it was a source-breaking error specifically when enabling Swift 6 language mode that didn't appear to be tied to and staged in via an upcoming feature flag, and I couldn't recall it being broadcast as one of the breaking changes for users to expect. That's the main reason I was wondering if it was intentional, especially since some of the other import visibility changes were pulled back from being enforced in Swift 6.

@dylansturg
Copy link
Contributor Author

dylansturg commented Dec 19, 2024

I noticed there's some inconsistency with this diagnostic when using a typealias in the "middle" module, helpers in my example. Consider this example:

// helpers.swift
public typealias ExportType = ExportedP
public typealias CompoundType = ExportedP & Hashable

struct Foo: ExportedP, Hashable {}

public func makeProtocol() -> ExportType { Foo() }
public func makeProtocol2() -> any CompoundType { Foo() }
// api.swift
import helpers

public struct API {
  public let p = makeProtocol()
  public let c = makeProtocol2()
}

The diagnostic flags the first property, p, as requiring an import for the protocol decls.ExportedP.

The diagnostic doesn't flag anything on the second property, c. I built the swiftinterface for this module, and the typealias is "resolved" so the property looks like public let c: any Hashable & ExportedP. So I wonder if the diagnostic should have triggered here too?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. triage needed This issue needs more specific labels
Projects
None yet
Development

No branches or pull requests

3 participants