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

New concurrency warnings when building with Swift 5.10 #1560

Closed
allevato opened this issue Feb 29, 2024 · 31 comments
Closed

New concurrency warnings when building with Swift 5.10 #1560

allevato opened this issue Feb 29, 2024 · 31 comments

Comments

@allevato
Copy link
Collaborator

allevato commented Feb 29, 2024

As a consequence of SE-0412: Strict concurrency for global variables, we're getting new concurrency warnings when building swift-protobuf. They can be narrowed down to two places:

Default instances of storage classes:

swift-protobuf/Sources/SwiftProtobuf/AnyMessageStorage.swift:144:14: error: static property 'defaultInstance'
is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this
is an error in Swift 6
  static let defaultInstance = AnyMessageStorage()
             ^

swift-protobuf/Sources/SwiftProtobuf/descriptor.pb.swift:3111:16: error: static property 'defaultInstance' is
not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is
an error in Swift 6
    static let defaultInstance = _StorageClass()
             ^

The _NameMap of each generated message:

swift-protobuf/Sources/SwiftProtobuf/any.pb.swift:195:21: error: static property '_protobuf_nameMap' is not
concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an
error in Swift 6
  public static let _protobuf_nameMap: _NameMap = [
                    ^

SE-0412 added the requirements that:

Under strict concurrency checking, require every global variable to either be isolated to a global actor or be both:

  1. immutable
  2. of Sendable type

Neither the storage classes nor _NameMap are Sendable. I need some more eyes who are better versed with Swift concurrency than I am 🙂

Storage classes

For the storage classes, we could just drop the defaultInstance property entirely and just allocate a new empty instance. However, it is a nice optimization to defer allocation of storage until the message is actually mutated. It's not super important if you're creating a new message and then immediately parsing or mutating it, but anywhere that we return an empty message as a default value of an unset message-typed field, it's very nice to not have to allocate storage if the user is only going to read from it.

Can we just mark the storage classes as Sendable on @unchecked Sendable since the messages themselves already conform to that, and the storage types can't be accessed from outside the message?

_NameMap

_NameMap looked more challenging because of the string interning logic and storage of Unsafe*Pointers, but upon further reflection, a _NameMap can never be mutated after its been initialized, so I think we could just declare _NameMap to be @unchecked Sendable and call it a day, right?

As a follow-up, now that Swift Strings are UTF-8 backed, we could probably revisit the UTF-8 buffer interning approach and just store Strings directly. The UTF-8 buffer interning dates back to 2017, so it was when Swift native strings weren't guaranteed to be UTF-8 backed, which I believe was the original motivation for the buffer approach.

@thomasvl
Copy link
Collaborator

fyi - @tbkka @FranzBusch @Lukasa

@thomasvl
Copy link
Collaborator

I went ahead and opened #1561 for topic of revisiting _NameMap. It might make sense do the @unchecked Sendable to get pass the warnings "right now", but doing that revisit to potential remove the issue seems like it might be a good thing in general.

@Lukasa
Copy link
Contributor

Lukasa commented Feb 29, 2024

AnyMessageStorage definitely looks sketchy.

@Lukasa
Copy link
Contributor

Lukasa commented Feb 29, 2024

Ok, so I think AnyMessageStorage is probably fine, but the default instance is causing us some pain. This is because it's used to skip an allocation, as any mutation to the storage should be CoW'd away. All well and good, but it means we're hitting this. @tbkka is it possible for us to suppress this warning on a per-attribute basis, on the grounds that we're only using it safely?

@thomasvl
Copy link
Collaborator

Why would AnyMessageStorage be any different than an other of the _Storage classes? The outer Message will call _uniqueStorage() before triggering any mutations within the AnyMessageStorage; so doesn't that make the usage the same as the others?

The thing being flagged about AnyMessageStorage is actually the same as the generated ones, it's the static let defaultInstance() = ... initialization. Right?

@tbkka
Copy link
Collaborator

tbkka commented Feb 29, 2024

Based on my (limited) understanding, we should mark the backing class as @unchecked Sendable. It's not an entirely satisfying answer -- we're basically just saying to the compiler "trust us, we never use this in a bad way" -- but it seems the best we can do for now.

@FranzBusch
Copy link
Member

I don't think we should make the backing class @unchecked Sendable but rather the struct holding the class. Since that struct is enforcing the CoW behaviour. If we would ever hold that backing class somewhere differently then that place also needs to make sure it implements the CoW correctly.

@thomasvl
Copy link
Collaborator

thomasvl commented Feb 29, 2024

I don't think we should make the backing class @unchecked Sendable but rather the struct holding the class. Since that struct is enforcing the CoW behaviour. If we would ever hold that backing class somewhere differently then that place also needs to make sure it implements the CoW correctly.

What do you mean by backing class? And holding class?

Right now we mark the message structs at @unchecked Sendable and the storage classes with nothing, but the problem is the static let defaultInstance within the storage class.

[Edited]

@tbkka
Copy link
Collaborator

tbkka commented Feb 29, 2024

What do you mean by backing class?

The _Storage classes.

I don't think we should make the backing class @unchecked Sendable ...

@FranzBusch So how do we deal with the static global that holds an empty copy of that class? Those are the errors that @thomasvl is referring to above.

@tbkka
Copy link
Collaborator

tbkka commented Feb 29, 2024

@FranzBusch suggested to me offline that

  • We use nonisolated(unsafe) on the global/static vars that hold the default instances
  • The _Storage classes remain unmarked
  • The CoW structs be @unchecked Sendable

@thomasvl
Copy link
Collaborator

Opened #1563 for some of the issues.

thomasvl added a commit to thomasvl/swift-protobuf that referenced this issue Mar 15, 2024
I think this is the rest of the issues in apple#1560

This is the different approach discussed in apple#1564.
@thomasvl
Copy link
Collaborator

With the repeated ones out of the way, here are some of the additional ones I'm seeing:

/__w/swift-protobuf/swift-protobuf/Sources/SwiftProtobuf/Google_Protobuf_Any+Registry.swift:20:17: warning: let 'knownTypesQueue' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
fileprivate let knownTypesQueue =
                ^
/__w/swift-protobuf/swift-protobuf/.build/x86_64-unknown-linux-gnu/release/SwiftProtobuf.build/DerivedSources/resource_bundle_accessor.swift:4:16: warning: static property 'module' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
    static let module: Bundle = {
               ^
[16/29] Compiling SwiftProtobufTestHelpers Descriptor+TestHelpers.swift
[17/29] Compiling SwiftProtobufPluginLibrary CodeGenerator.swift
/__w/swift-protobuf/swift-protobuf/Sources/SwiftProtobufPluginLibrary/NamingUtils.swift:364:17: warning: let 'backtickCharacterSet' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
fileprivate let backtickCharacterSet = CharacterSet(charactersIn: "`")
                ^
/__w/swift-protobuf/swift-protobuf/.build/x86_[64](https://github.com/apple/swift-protobuf/actions/runs/8297904866/job/22710035443?pr=1577#step:4:65)-unknown-linux-gnu/release/SwiftProtobufPluginLibrary.build/DerivedSources/resource_bundle_accessor.swift:4:16: warning: static property 'module' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
    static let module: Bundle = {
               ^

@thomasvl
Copy link
Collaborator

The module: Bundle ones are generate code by SwiftPM, anyone know if that's already tracked by for Swift in general?

@Lukasa
Copy link
Contributor

Lukasa commented Mar 15, 2024

I couldn't find an immediate issue, can't hurt to file a new one.

thomasvl added a commit to thomasvl/swift-protobuf that referenced this issue Mar 18, 2024
I think this is the rest of the issues in apple#1560

This is the different approach discussed in apple#1564.
thomasvl added a commit that referenced this issue Mar 19, 2024
I think this is the rest of the issues in #1560

This is the different approach discussed in #1564.
thomasvl added a commit to thomasvl/swift-protobuf that referenced this issue Mar 19, 2024
I think this is the rest of the issues in apple#1560

This is the different approach discussed in apple#1564.
thomasvl added a commit to thomasvl/swift-protobuf that referenced this issue Mar 19, 2024
I think this is the rest of the issues in apple#1560

This is the different approach discussed in apple#1564.
@thomasvl
Copy link
Collaborator

Actually, I might have pulled those off the branch build, where I think some things haven't built, let me try the main branch again.

@thomasvl
Copy link
Collaborator

Ok, here's a test on main: https://github.com/apple/swift-protobuf/actions/runs/8344464434/job/22837023897?pr=1585

/__w/swift-protobuf/swift-protobuf/main/Sources/SwiftProtobuf/Google_Protobuf_Any+Registry.swift:20:17: error: let 'knownTypesQueue' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
fileprivate let knownTypesQueue =
                ^
/__w/swift-protobuf/swift-protobuf/main/.build/x86_64-unknown-linux-gnu/debug/SwiftProtobuf.build/DerivedSources/resource_bundle_accessor.swift:4:16: error: static property 'module' is not concurrency-safe because it is not either conforming to 'Sendable' or isolated to a global actor; this is an error in Swift 6
    static let module: Bundle = {
               ^

Aside: things get printing multiple times which makes me wonder if 5.10 has some other issue going on.

@FranzBusch @Lukasa @tbkka – given the problems with resource_bundle_accessor.swift it seems like we'll have to stop using -Xswiftc -warnings-as-errors, do you see any other way around this?

@thomasvl
Copy link
Collaborator

Oh no. If I build on my Mac with Xcode 15.3, I don't get either of these. Does that mean Linux's version of DispatchQueue might not be annotated correctly in 5.10?

Any suggestions for that then?

@thomasvl
Copy link
Collaborator

I guess we could hack the resource one with a #if check for Linux and not add the privacy manifest info?

thomasvl added a commit to thomasvl/swift-protobuf that referenced this issue Mar 19, 2024
AppleStore only requires the informatiion on iOS, watchOS, tvOS, visionOS; so
exclude the resources for Linux and macOS.

As of Swift 5.10 (apple#1560), the generated Linux code when there are resources gets
flagged with issues when using `StrictConcurrency=complete`; so this dodges the
issue.
thomasvl added a commit to thomasvl/swift-protobuf that referenced this issue Mar 19, 2024
AppleStore only requires the informatiion on iOS, watchOS, tvOS, visionOS; so
exclude the resources for Linux and macOS.

As of Swift 5.10 (apple#1560), the generated Linux code when there are resources gets
flagged with issues when using `StrictConcurrency=complete`; so this dodges the
issue.
@Lukasa
Copy link
Contributor

Lukasa commented Mar 19, 2024

For the dispatch queue issue, use @preconcurrency import to silence it on Linux.

@Lukasa
Copy link
Contributor

Lukasa commented Mar 19, 2024

Did you file an issue for the Module warning?

@thomasvl
Copy link
Collaborator

For the dispatch queue issue, use @preconcurrency import to silence it on Linux.

Ha, I'm testing that out now, I'll move that to it's own PR shortly.

Did you file an issue for the Module warning?

Haven't gotten there yet. If you'd got the time to do it, it will likely get more attention if filed by one of you.

@thomasvl
Copy link
Collaborator

@preconcurrency appears to be a nogo:

/__w/swift-protobuf/swift-protobuf/main/Sources/SwiftProtobuf/Google_Protobuf_Any+Registry.swift:20:17: remark: '@preconcurrency' attribute on module 'Dispatch' is unused
@preconcurrency import Dispatch
~~~~~~~~~~~~~~~~^

@Lukasa
Copy link
Contributor

Lukasa commented Mar 19, 2024

This warning is firing on Linux?

@thomasvl
Copy link
Collaborator

thomasvl added a commit that referenced this issue Mar 25, 2024
I think this is the rest of the issues in #1560

This is the different approach discussed in #1564.
thomasvl added a commit to thomasvl/swift-protobuf that referenced this issue Mar 26, 2024
See apple#1560 for the details, but
things currently don't pass on linux, and some of the issues are within the
Swift toolchain.
thomasvl added a commit to thomasvl/swift-protobuf that referenced this issue Mar 26, 2024
See apple#1560 for the details, but
things currently don't pass on linux, and some of the issues are within the
Swift toolchain.
thomasvl added a commit to thomasvl/swift-protobuf that referenced this issue Mar 27, 2024
See apple#1560 for the details, but
things currently don't pass on linux, and some of the issues are within the
Swift toolchain.
thomasvl added a commit that referenced this issue Mar 29, 2024
See #1560 for the details, but
things currently don't pass on linux, and some of the issues are within the
Swift toolchain.
@thomasvl
Copy link
Collaborator

I don't appear to get the CharacterSet warning when building on macOS either, so I guess that's another issue within Linux Foundation.

So I think we're down to all problems in the Swift Linux distro now. Everything we can control should be warning free.

@FranzBusch
Copy link
Member

We should be able to fix the warning with CharacterSet by using a @preconcurrency import struct Foundation.CharacterSet. Importantly this import needs to be conditionalised on the platform by using #if canImport(Darwin). Only on Darwin we can avoid the @preconcurrency import since there it is correctly annotated.

@thomasvl
Copy link
Collaborator

Looking back at that code, we don't really need to use CharacterSet, I'll do a quick PR to drop it.

@thomasvl
Copy link
Collaborator

Now we're down to just the generated file for resources and then the dispatch related one.

Guess it's safe to close this now since we've done everything we can for the 5.10 specific issues.

@thomasvl
Copy link
Collaborator

thomasvl commented Jul 8, 2024

I happened to be looking at swift-nio, and realized they did do the conditional in Package.swift that would break cross comp for the privacy manifest, do we want to do that also? (Our use of Dispatch for the Any registry will still prevent warnings-as-errors)

@thomasvl thomasvl changed the title New concurrency warnings when building with Xcode 15.3 beta (Swift 5.10) New concurrency warnings when building with Swift 5.10 Jul 8, 2024
@thomasvl
Copy link
Collaborator

I'm going to go ahead and close this since it was specific to 5.10. We may end up revisit some things for Swift 6, but it feels like that should be a new issue.

@rebello95
Copy link
Contributor

Related: #1729

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants