Open allevato opened 6 months ago
fyi - @tbkka @FranzBusch @Lukasa
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.
AnyMessageStorage
definitely looks sketchy.
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?
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?
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.
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.
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]
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.
@FranzBusch suggested to me offline that
nonisolated(unsafe)
on the global/static vars that hold the default instances_Storage
classes remain unmarked@unchecked Sendable
Opened #1563 for some of the issues.
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 = {
^
The module: Bundle
ones are generate code by SwiftPM, anyone know if that's already tracked by for Swift in general?
I couldn't find an immediate issue, can't hurt to file a new one.
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.
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?
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?
I guess we could hack the resource one with a #if
check for Linux and not add the privacy manifest info?
For the dispatch queue issue, use @preconcurrency import
to silence it on Linux.
Did you file an issue for the Module warning?
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.
@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
~~~~~~~~~~~~~~~~^
This warning is firing on Linux?
This warning is firing on Linux?
Yup - https://github.com/apple/swift-protobuf/actions/runs/8345218414/job/22839591811?pr=1585
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.
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.
Looking back at that code, we don't really need to use CharacterSet
, I'll do a quick PR to drop it.
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.
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
)
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:
The
_NameMap
of each generated message:SE-0412 added the requirements that:
Neither the storage classes nor
_NameMap
areSendable
. 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 ofUnsafe*Pointer
s, 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
String
s are UTF-8 backed, we could probably revisit the UTF-8 buffer interning approach and just storeString
s 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.