swiftlang / swift

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

[SR-11594] Using StringInterpolation in PropertyWrapper closure fails (inout to non-inout error) #53999

Open AliSoftware opened 4 years ago

AliSoftware commented 4 years ago
Previous ID SR-11594
Radar rdar://problem/56119891
Original Reporter @AliSoftware
Type Bug
Environment Xcode 11.1 (11A1027) ``` java $ DEVELOPER_DIR=/Applications/Xcode-11.1.app xcrun swift --version Apple Swift version 5.1 (swiftlang-1100.0.270.13 clang-1100.0.33.7) Target: x86_64-apple-darwin18.7.0 ```
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 0 | |Component/s | Compiler | |Labels | Bug, CompilerCrash, StringInterpolation | |Assignee | None | |Priority | Medium | md5: 06bcd465e4cc99f47be14ff22d5258a4

relates to:

Issue Description:

Consider the following code below (written in a playground)

import Foundation

@propertyWrapper struct CustomEncodable<T, U: Encodable> {
    var wrappedValue: T
    var encodeTransform: (T) -> U
    init(wrappedValue: T, _ encodeTransform: @escaping (T) -> U) {
        self.wrappedValue = wrappedValue
        self.encodeTransform = encodeTransform
    }
}
extension CustomEncodable: Encodable {
    func encode(to encoder: Encoder) throws {
        let u = encodeTransform(self.wrappedValue)
        var container = encoder.singleValueContainer()
        try container.encode(u)
    }
}

struct User: Encodable {
    @CustomEncodable({ "[0-\($0)-100]" })
    var lotteryTicket = Int.random(in: 0..<100)
    var name: String
}
let user = User(name: "Olivier")
print(json(from: user))

When we use

@CustomEncodable({ "[0-\($0)-100]" })

as an annotation like above, the compiler complains with the following error in the Debug console:

error: 'inout DefaultStringInterpolation' is not convertible to 'DefaultStringInterpolation'
error: 'inout DefaultStringInterpolation' is not convertible to 'DefaultStringInterpolation'
error: 'inout DefaultStringInterpolation' is not convertible to 'DefaultStringInterpolation'

The error disappears if we un-sugar the annotation ourselves – i.e, we implement _lotteryTicket and lotteryTicket manually like below:

struct User: Encodable {
    var _lotteryTicket = CustomEncodable(wrappedValue: Int.random(in: 0..<100), { "[0-\($0)-100]" })
    var lotteryTicket: Int {
        get { _lotteryTicket.wrappedValue }
        set { _lotteryTicket.wrappedValue = newValue }
    }
    var name: String
}

(But then of course the default CodingKeys generated for User now use the underscore in the default key name)

belkadan commented 4 years ago

Looks a lot like SR-10753, which didn't make it into 5.1. But…I get a crash when trying this on master, so I guess it's not completely fixed!

@swift-ci create

hborla commented 4 years ago

This is fixed by https://github.com/apple/swift/pull/30807