SwiftyUserDefaults icon indicating copy to clipboard operation
SwiftyUserDefaults copied to clipboard

[Xcode 13.3] builtin extensions are missing

Open shimastripe opened this issue 3 years ago • 13 comments

Problem

struct SomeStruct: Codable, DefaultsSerializable {}
=> type 'SomeStruct' does not conform to protocol 'DefaultsSerializable'

In Xcode 13.3, I can't build my apps about DefaultsSerializable.

struct SomeStruct: Codable, DefaultsSerializable {
    public static var _defaults: DefaultsCodableBridge<SomeStruct> { .init() }
    public static var _defaultsArray: DefaultsCodableBridge<[SomeStruct]> { .init() }
}
=> Build succeed

Then I added some default extension's implementations. This problem is occurred about RowRepresentable, NSCoding, or more.

WHY

https://github.com/sunshinejr/SwiftyUserDefaults/blob/master/Sources/BuiltIns.swift extensions are missing?

Xcode 13.3 Beta 1

shimastripe avatar Jan 31 '22 02:01 shimastripe

They're not missing. If you look at the build errors in the logs, it actually says something like:

ambiguous inference of associated type 'Bridge': 'DefaultsCodableBridge<Foo>' vs. 'DefaultsRawRepresentableBridge<Foo>'
matching requirement '_defaults' to this declaration inferred associated type to 'DefaultsCodableBridge<Foo>'
matching requirement '_defaults' to this declaration inferred associated type to 'DefaultsRawRepresentableBridge<Foo>'

In my testing, this only happens if the extensions with the default implementations are in another module. It looks like a compiler bug to me.

robinkunde avatar Feb 01 '22 02:02 robinkunde

@robinkunde Thank you for your help 🙏

shimastripe avatar Feb 01 '22 12:02 shimastripe

Filed here https://bugs.swift.org/browse/SR-15807

robinkunde avatar Feb 02 '22 02:02 robinkunde

same with Xcode 13.3 Beta 3

apps4everyone avatar Feb 24 '22 18:02 apps4everyone

same with RC, maybe a fix is needed here!

apps4everyone avatar Mar 08 '22 22:03 apps4everyone

A simple workaround is change dependency to source code

gewill avatar Mar 09 '22 06:03 gewill

Hi everyone,

This workaround worked for me:

  1. CreateSwiftyUserDefaults+Workaround.swift in the module which is using SwiftyUserDefaults.
  2. Copy the codes below into SwiftyUserDefaults+Workaround.swift
import SwiftyUserDefaults
import Foundation

extension DefaultsSerializable {
    public static var _defaultsArray: DefaultsArrayBridge<[T]> { return DefaultsArrayBridge() }
}
extension Date: DefaultsSerializable {
    public static var _defaults: DefaultsObjectBridge<Date> { return DefaultsObjectBridge() }
}
extension String: DefaultsSerializable {
    public static var _defaults: DefaultsStringBridge { return DefaultsStringBridge() }
}
extension Int: DefaultsSerializable {
    public static var _defaults: DefaultsIntBridge { return DefaultsIntBridge() }
}
extension Double: DefaultsSerializable {
    public static var _defaults: DefaultsDoubleBridge { return DefaultsDoubleBridge() }
}
extension Bool: DefaultsSerializable {
    public static var _defaults: DefaultsBoolBridge { return DefaultsBoolBridge() }
}
extension Data: DefaultsSerializable {
    public static var _defaults: DefaultsDataBridge { return DefaultsDataBridge() }
}

extension URL: DefaultsSerializable {
    #if os(Linux)
    public static var _defaults: DefaultsKeyedArchiverBridge<URL> { return DefaultsKeyedArchiverBridge() }
    #else
    public static var _defaults: DefaultsUrlBridge { return DefaultsUrlBridge() }
    #endif
    public static var _defaultsArray: DefaultsKeyedArchiverBridge<[URL]> { return DefaultsKeyedArchiverBridge() }
}

extension DefaultsSerializable where Self: Codable {
    public static var _defaults: DefaultsCodableBridge<Self> { return DefaultsCodableBridge() }
    public static var _defaultsArray: DefaultsCodableBridge<[Self]> { return DefaultsCodableBridge() }
}

extension DefaultsSerializable where Self: RawRepresentable {
    public static var _defaults: DefaultsRawRepresentableBridge<Self> { return DefaultsRawRepresentableBridge() }
    public static var _defaultsArray: DefaultsRawRepresentableArrayBridge<[Self]> { return DefaultsRawRepresentableArrayBridge() }
}

extension DefaultsSerializable where Self: NSCoding {
    public static var _defaults: DefaultsKeyedArchiverBridge<Self> { return DefaultsKeyedArchiverBridge() }
    public static var _defaultsArray: DefaultsKeyedArchiverBridge<[Self]> { return DefaultsKeyedArchiverBridge() }
}

extension Dictionary: DefaultsSerializable where Key == String {
    public typealias T = [Key: Value]
    public typealias Bridge = DefaultsObjectBridge<T>
    public typealias ArrayBridge = DefaultsArrayBridge<[T]>
    public static var _defaults: Bridge { return Bridge() }
    public static var _defaultsArray: ArrayBridge { return ArrayBridge() }
}
extension Array: DefaultsSerializable where Element: DefaultsSerializable {
    public typealias T = [Element.T]
    public typealias Bridge = Element.ArrayBridge
    public typealias ArrayBridge = DefaultsObjectBridge<[T]>
    public static var _defaults: Bridge {
        return Element._defaultsArray
    }
    public static var _defaultsArray: ArrayBridge {
        fatalError("Multidimensional arrays are not supported yet")
    }
}

This is pretty much a copy from the BuiltIns.swift file in the Sources folder: https://raw.githubusercontent.com/sunshinejr/SwiftyUserDefaults/master/Sources/BuiltIns.swift

I just removed the last part due to an error that I didn't spend too much time to solve. Just removed this piece of code and the app compiled successfully.

extension Optional: DefaultsSerializable where Wrapped: DefaultsSerializable {
    public typealias Bridge = DefaultsOptionalBridge<Wrapped.Bridge>
    public typealias ArrayBridge = DefaultsOptionalBridge<Wrapped.ArrayBridge>

    public static var _defaults: DefaultsOptionalBridge<Wrapped.Bridge> { return DefaultsOptionalBridge(bridge: Wrapped._defaults) }
    public static var _defaultsArray: DefaultsOptionalBridge<Wrapped.ArrayBridge> { return DefaultsOptionalBridge(bridge: Wrapped._defaultsArray) }
}

This was based on a workaround shared here: https://github.com/sindresorhus/Defaults/issues/93#issuecomment-1053183113

ricardopaiva avatar Mar 14 '22 14:03 ricardopaiva

FYI: in our project codebase that only using DefaultsSerializable with Codable, this small workaround code adding to main module is resolved compiler error too. But this is not maybe fit to all of the case.

extension DefaultsSerializable where Self: Codable {
    typealias Bridge = DefaultsCodableBridge<Self>
    typealias ArrayBridge = DefaultsCodableBridge<[Self]>
}

r-plus avatar Mar 16 '22 02:03 r-plus

FYI: in our project codebase that only using DefaultsSerializable with Codable, this small workaround code adding to main module is resolved compiler error too. But this is not maybe fit to all of the case.

extension DefaultsSerializable where Self: Codable {
    typealias Bridge = DefaultsCodableBridge<Self>
    typealias ArrayBridge = DefaultsCodableBridge<[Self]>
}

Thanks, this avoided a ton of compiler warnings

morgz avatar Mar 16 '22 10:03 morgz

can we update a new version and get this done?

skywalkerlw avatar Mar 21 '22 05:03 skywalkerlw

This worked for me, having had classes/structs using RawRepresentable or Codable paired with DefaultsSerializable:

extension DefaultsSerializable where Self: Codable {
    public typealias Bridge = DefaultsCodableBridge<Self>
    public typealias ArrayBridge = DefaultsCodableBridge<[Self]>
}

extension DefaultsSerializable where Self: RawRepresentable {
    typealias Bridge = DefaultsRawRepresentableBridge<Self>
    typealias ArrayBridge = DefaultsRawRepresentableArrayBridge<[Self]>
}

Added this to our global constants file, got rid of the issues related to this post.

WestFlow127 avatar Mar 28 '22 22:03 WestFlow127

why not release new version to fix this bug

thanhdevapp avatar May 09 '22 07:05 thanhdevapp

I checked Xcode 14 Beta ([email protected]) was resolved this problem!

shimastripe avatar Jun 12 '22 13:06 shimastripe

I checked this bug was resolved in Xcode 14 RC too! So close this issue! Thanks!

shimastripe avatar Oct 02 '22 04:10 shimastripe