Using @Bindable with a Observable type

Originally asked on Swift Forums: https://forums.swift.org/t/using-bindable-with-a-observable-type/70993

I'm using SwiftUI environments in my app to hold a preferences object which is an @Observable object

But I want to be able to inject different instances of the preferences object for previews vs the production code so I've abstracted my production object in to a Preferences protocol and updated my Environment key's type to:

protocol Preferences { }

@Observable
final class MyPreferencesObject: Preferences { }

@Observable
final class MyPreviewsObject: Preferences { }


// Environment key

private struct PreferencesKey: EnvironmentKey {
    static let defaultValue : Preferences & Observable = MyPreferencesObject()
}

extension EnvironmentValues {
    var preferences: Preferences & Observable {
        get { self[PreferencesKey.self] }
        set { self[PreferencesKey.self] = newValue }
    }
}

The compiler is happy with this until I go to use @Bindable in my code where the compiler explodes with a generic error, eg:

@Environment(\.preferences) private var preferences

// ... code

@Bindable var preferences = preferences

If I change the environment object back to a conforming type eg:

@Observable
final class MyPreferencesObject() { }

private struct PreferencesKey: EnvironmentKey {
    static let defaultValue : MyPreferencesObject = MyPreferencesObject()
}

extension EnvironmentValues {
    var preferences: MyPreferencesObject {
        get { self[PreferencesKey.self] }
        set { self[PreferencesKey.self] = newValue }
    }
}

Then @Bindable is happy again and things compile.

Is this a known issue/limitation? Or am I missing something here?

Replies

Specifically the compiler errors with:

Failed to produce diagnostic for expression; please submit a bug report (Swift.org - Contributing)

On the parent function the @Bindable is inside of

and with a

Command SwiftCompile failed with a nonzero exit code

In the app target.