swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.49k stars 10.35k forks source link

[SR-14411] @propertyWrapper for Optional type: wrappedValue initialization error for automatically assigned nil value #56768

Open swift-ci opened 3 years ago

swift-ci commented 3 years ago
Previous ID SR-14411
Radar None
Original Reporter jactmp (JIRA User)
Type Bug
Environment $ swift -version Apple Swift version 5.4 (swiftlang-1205.0.26.4 clang-1205.0.19.54) Target: x86_64-apple-darwin20.4.0 $ uname -a Darwin xxx.local 20.4.0 Darwin Kernel Version 20.4.0: Fri Mar 5 03:57:04 PST 2021; root:xnu-7195.101.1\~4/RELEASE_X86_64 x86_64
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: 54cb0df633179d959fc0194950433baa

Issue Description:

Initialization works as intended only in case property wrapper init has no additional parameters.

@propertyWrapper
struct Wrapper<Value> {
    private var parameter: Int?

    var wrappedValue: Value

    init(wrappedValue: Value, parameter: Int? = 0) {
        self.wrappedValue = wrappedValue
        self.parameter = parameter
    }
}

class WrapperTest {
    @Wrapper var valueImplicitNil: Double?                                  // OK
    @Wrapper var valueExplicitNil: Double? = nil                            // OK
    //@Wrapper(parameter: 1) var valueWithParamImplicitNil: Double?           // NOK (Missing argument for parameter 'wrappedValue' in call)
    @Wrapper(parameter: 1) var valueWithParamExplicitNil: Double? = nil    // OK
}

For valueImplicitNil, Swift automatically assigns nil to it, and then propertyWrapper initializer automatically assigns nil to first init parameter wrappedValue - both behaviors clearly described in Swift documentation. For some reason it doesn't do the same for valueWithParamImplicitNil variable.

xAlien95 commented 3 years ago

Related discussion: Allow Property Wrappers with Multiple Arguments to Defer Initialization when wrappedValue is not Specified.

swift-ci commented 3 years ago

Comment by Jacek Szczech (JIRA)

Although discussion is definitely related, in this case property wrapper is formally initialized with nil value. It seems like the problem is that for some reason rule (B) (initialization of wrappedValue from assignment) it tried to be applied before rule (A) - implicit nil initialization of Optional type. Shouldn't it be opposite?

swift-ci commented 3 years ago

Comment by Jacek Szczech (JIRA)

OK. I understand that the problem arise from the fact that in Swift implicit nil assignment works for variables, but not for function parameters of Optional type. In this case variable initialization is actually treated more like initialization of first parameter of init function: wrappedValue. In result implicit nil initialization doesn't work.

Problem is easy addressable by second initializer, e.g.:

{{ init\<V>(wrappedValue: Value = nil, parameter: Int? = 0) where Value == V? {...}}}

but still it might be a bit confusing.