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-5308] global variable initializer runs even when first access initializes #47883

Open
mattneub opened this issue Jun 25, 2017 · 2 comments
Open
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself feature A feature request or implementation

Comments

@mattneub
Copy link

Previous ID SR-5308
Radar rdar://19085421
Original Reporter @mattneub
Type Bug
Environment

Swift 4

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, LanguageFeatureRequest
Assignee None
Priority Medium

md5: d81068550564c0bc0de8ac7c29afb91a

Issue Description:

The basic example is:

var laz : String = {
    print("lazy initializing laz")
    return "Howdy"
}()

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        laz = "Greetings"
        print(laz)
    }
}

The first access is laz = "Greetings" but it causes `laz` to be first set to "Howdy" as a side effect because the lazy initializer runs. This seems wrong.

@belkadan
Copy link
Contributor

I'm concerned that changing this would be a language change at this point, since the initial value expression may have side effects.

@mattneub
Copy link
Author

Those side effects are exactly what concern me. If the first access is to set the variable, that is (or should be) the initialization. The (possibly expensive) initializer isn't needed.

Also there's a weird difference here; setting a `lazy var` instance variable doesn't run its initial value expression. To see that, run this variant of the above code:

var laz : String = {
    print("lazy initializing global")
    return "Howdy"
}()

class ViewController: UIViewController {
    lazy var lazyProperty : String = {
        print("lazy initializing property")
        return "Howdy"
    }()
    override func viewDidLoad() {
        super.viewDidLoad()
        laz = "Greetings"
        print(laz)
        lazyProperty = "Greetings"
        print(lazyProperty)
    }
}

So why should setting a global do so? You surely wouldn't argue that the language should be changed the other way, to make them both run their initializers when set?

So I've long regarded this behavior as a bug. I can see that fixing it might require passing through a decision-making process, but I'm not in any doubt that the current behavior is intuitively not what one would expect or want.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself feature A feature request or implementation
Projects
None yet
Development

No branches or pull requests

2 participants