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

[SR-11910] @_implementationOnly types not allowed as private properties on public types #54328

Open
keith opened this issue Dec 6, 2019 · 7 comments
Assignees

Comments

@keith
Copy link
Collaborator

keith commented Dec 6, 2019

Previous ID SR-11910
Radar rdar://problem/57712090
Original Reporter @keith
Type Improvement

Attachment: Download

Additional Detail from JIRA
Votes 1
Component/s
Labels Improvement
Assignee @xymus
Priority Medium

md5: 43f6fcffed6a4ec0ba4c89fbdaa1aa13

Issue Description:

If I import a target with `@_implementationOnly import base` that defines a type `Base` and create a `public` type `Foo` that has `private let base: Base` it fails to build with:

/private/tmp/privatetestonly/Sources/privatetestonly/main.swift:4:17: error: cannot use struct 'Base' here; 'base' has been imported as implementation-only
    private let base: Base
                ^     ~~~~

I would expect this to build since the property should not be viewable by dependees even though the enclosing type is public. This might be by design though? See the attached sample project and run `swift build` for an example.

@beccadax
Copy link
Contributor

beccadax commented Dec 6, 2019

@swift-ci create

@xymus
Copy link
Contributor

xymus commented Dec 10, 2019

It is by design, but the error message could be more clear about why it is an issue. The type Base is rejected here because the clients of this module (main.swift) need to know the actual layout of the struct to allocate it and access its stored properties directly. The implementation-only import completely hides `Base` from the clients, and also from the compiler compiling the clients. Making the property private protects it at the semantic level but the compiler would still need to know of its presence and type when compiling the clients.

Depending on your use case, a solution could be to compile this module with resilience by using `-enable-library-evolution`. This setting will enable compiling the module for clients to use indirections when initializing or accessing non-frozen structs. With indirections instead of direct accesses the clients may be less optimizable but they don’t need the full knowledge of the struct layout so the compiler can hide the private stored property from the clients. This private property should then be accepted.

@keith
Copy link
Collaborator Author

keith commented Dec 10, 2019

Thanks for the context!

@keith
Copy link
Collaborator Author

keith commented Jan 15, 2020

Just also found https://bugs.swift.org/browse/SR-11613

@keith
Copy link
Collaborator Author

keith commented Apr 17, 2020

@xymus what if everything here were classes instead? Could that case be allowed? It seems like currently this fails with the same error, but I assume it shouldn't have the same struct layout issues

@keith
Copy link
Collaborator Author

keith commented Aug 4, 2020

For historians it seems like the class issue is unexpected https://forums.swift.org/t/swift-implementationonly-not-working-correctly-with-private-members/39002/3?u=keith

@belkadan
Copy link
Contributor

belkadan commented Aug 4, 2020

"Unexpected" is a little strong. It's absolutely expected today, just possible to change in the future if we're willing to compromise on cross-module inlining in some ways.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants