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-13896] Confusing error message when assigning an optional UIImage as a state property #57

Open
swift-ci opened this issue Nov 24, 2020 · 2 comments

Comments

@swift-ci
Copy link

Previous ID SR-13896
Radar rdar://60600911
Original Reporter frostra1n (JIRA User)
Type Bug

Attachment: Download

Environment

macOS Catalina 10.15.7

Apple Swift version 5.3 (swiftlang-1200.0.29.2 clang-1200.0.30.1)

Xcode 12.1

Additional Detail from JIRA
Votes 0
Component/s Compiler, Xcode Playground Support
Labels Bug, PropertyWrappers
Assignee None
Priority Medium

md5: f20a4f1b3d227c0ef91b2fdd21421924

Issue Description:

I'm working on project that uses both UIKit and SwiftUI and I found a scenario that shows a confusing error when assigning a `UIImage?` in a struct initializer. The error is:

Variable 'self.asPreview' used before being initialized

And this is the code that produces the error:

import SwiftUI
import UIKit

struct BookView: View {
    let asPreview: Bool
    @State var image: UIImage?

    init(image: UIImage?, asPreview: Bool = false) {
        self.image = image         
        self.asPreview = asPreview
    }

    var body: some View {
         Group {}
     }
 }

The error is pointed in line 9 right under the equal sign ("self.image = image"), but actually that line assigns a different struct property, so it's a little bit confusing.

What it could be happening is that a different type of value is being assigned to the image variable, so the error message that should be shown instead could be something related of assigning an `UIImage?` to a `State<UIImage?>` variable.

The code above can be used in Xcode playground to reproduce the issue. I've attached a screenshot reproducing the bug.

@LucianoPAlmeida
Copy link

Here is a reduced reproducer

@propertyWrapper
class A {
  var wrappedValue: Int?
}

struct S {
    let b: Bool
    @A var a: Int?

    init(a: Int?, b: Bool = false) {
        self.a = a // 'self' used before all stored properties are initialized
        self.b = b
    }
}

As far as I could see the problem is related to the fact that in this case @A is a class and the way self is implicit passed to the property wrapper in the assignment that is required to all properties being initialized.
To me, the diagnostics should be improved to make this more clear.
But as a workaround, it should be able to make it work by making sure initialized all the other members before the property wrapper
e.g.

init(image: UIImage?, asPreview: Bool = false) {
   self.asPreview = asPreview // Make sure this is initialized before call property wrapper
   self.image = image 
}

cc @hborla

@hborla
Copy link
Member

hborla commented Nov 30, 2020

This is a known issue where out-of-line initialization via wrapped value isn't supported for class property wrappers and struct property wrappers with nonmutating setters (due to limitations of the assign_by_wrapper instruction in SIL). Here's a reproducer without SwiftUI:

@propertyWrapper
struct State<Value> {
  private var _wrappedValue: Value

  var wrappedValue: Value {
    get { _wrappedValue }
    nonmutating set {}
  }

  init(wrappedValue: Value) {
    _wrappedValue = wrappedValue
  }
}

struct BookView {
    let flag: Bool
    @State var str: String

    init(str: String, flag: Bool = false) {
        self.str = str
        self.flag = flag
    }
 }

@LucianoPAlmeida you're right that the error message should make it clear how to fix the issue. The right fix is to initialize the backing property wrapper directly, e.g.:

    init(str: String, flag: Bool = false) {
        self._str = State(wrappedValue: str)
        self.flag = flag
    }

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from swiftlang/swift May 9, 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

3 participants