1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
|
// RUN: %target-typecheck-verify-swift
enum Foo : Int {
case a, b, c
}
var raw1: Int = Foo.a.rawValue
var raw2: Foo.RawValue = raw1
var cooked1: Foo? = Foo(rawValue: 0)
var cooked2: Foo? = Foo(rawValue: 22)
enum Bar : Double {
case a, b, c
}
func localEnum() -> Int {
enum LocalEnum : Int {
case a, b, c
}
return LocalEnum.a.rawValue
}
enum MembersReferenceRawType : Int {
case a, b, c
init?(rawValue: Int) {
self = MembersReferenceRawType(rawValue: rawValue)!
}
func successor() -> MembersReferenceRawType {
return MembersReferenceRawType(rawValue: rawValue + 1)!
}
}
func serialize<T : RawRepresentable>(_ values: [T]) -> [T.RawValue] {
return values.map { $0.rawValue }
}
func deserialize<T : RawRepresentable>(_ serialized: [T.RawValue]) -> [T] {
return serialized.map { T(rawValue: $0)! }
}
var ints: [Int] = serialize([Foo.a, .b, .c])
var doubles: [Double] = serialize([Bar.a, .b, .c])
var foos: [Foo] = deserialize([1, 2, 3])
var bars: [Bar] = deserialize([1.2, 3.4, 5.6])
// We reject enums where the raw type stated in the inheritance clause does not
// match the types of the witnesses.
enum Color : Int {
case red
case blue
init?(rawValue: Double) {
return nil
}
var rawValue: Double { // expected-note {{found this candidate}}
return 1.0
}
}
func useRawValue(of color: Color) {
_ = color.rawValue
// expected-error@-1 {{ambiguous use of 'rawValue'}}
}
var colorRaw: Color.RawValue = 7.5
// expected-error@-1 {{cannot convert value of type 'Double' to specified type 'Color.RawValue' (aka 'Int')}}
// Mismatched case types
enum BadPlain : UInt { // expected-error {{'BadPlain' declares raw type 'UInt', but does not conform to RawRepresentable and conformance could not be synthesized}}
case a = "hello" // expected-error {{cannot convert value of type 'String' to raw type 'UInt'}}
}
// Recursive diagnostics issue in tryRawRepresentableFixIts()
class Outer {
// The setup is that we have to trigger the conformance check
// while diagnosing the conversion here. For the purposes of
// the test I'm putting everything inside a class in the right
// order, but the problem can trigger with a multi-file
// scenario too.
let a: Int = E.a // expected-error {{cannot convert value of type 'Outer.E' to specified type 'Int'}}
enum E : Array<Int> {
// expected-error@-1 {{raw type 'Array<Int>' is not expressible by a string, integer, or floating-point literal}}
// expected-error@-2 {{'Outer.E' declares raw type 'Array<Int>', but does not conform to RawRepresentable and conformance could not be synthesized}}
case a
}
}
// rdar://problem/32431736 - Conversion fix-it from String to String raw value enum can't look through optionals
func rdar32431736() {
enum E : String {
case A = "A"
case B = "B"
}
let items1: [String] = ["A", "a"]
let items2: [String]? = ["A"]
let myE1: E = items1.first
// expected-error@-1 {{cannot convert value of type 'String?' to specified type 'E'}}
// expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: }} {{29-29=!) ?? <#default value#>}}
let myE2: E = items2?.first
// expected-error@-1 {{cannot convert value of type 'String?' to specified type 'E'}}
// expected-note@-2 {{construct 'E' from unwrapped 'String' value}} {{17-17=E(rawValue: (}} {{30-30=)!) ?? <#default value#>}}
}
// rdar://problem/32431165 - improve diagnostic for raw representable argument mismatch
enum E_32431165 : String {
case foo = "foo"
case bar = "bar" // expected-note {{'bar' declared here}}
}
func rdar32431165_1(_: E_32431165) {}
func rdar32431165_1(_: Int) {}
func rdar32431165_1(_: Int, _: E_32431165) {}
rdar32431165_1(E_32431165.baz)
// expected-error@-1 {{type 'E_32431165' has no member 'baz'; did you mean 'bar'?}}
rdar32431165_1(.baz)
// expected-error@-1 {{reference to member 'baz' cannot be resolved without a contextual type}}
rdar32431165_1("")
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}}
rdar32431165_1(42, "")
// expected-error@-1 {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{20-20=E_32431165(rawValue: }} {{22-22=) ?? <#default value#>}}
func rdar32431165_2(_: String) {}
func rdar32431165_2(_: Int) {}
func rdar32431165_2(_: Int, _: String) {}
rdar32431165_2(E_32431165.bar)
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{30-30=.rawValue}}
rdar32431165_2(42, E_32431165.bar)
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{34-34=.rawValue}}
// TODO: In following two examples it's possible to fix a problem by either using `.rawValue` on first argument
// or constructing raw representable type from second, both ways are valid.
do {
E_32431165.bar == "bar"
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{17-17=.rawValue}}
"bar" == E_32431165.bar
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{26-26=.rawValue}}
}
func rdar32431165_overloaded() -> Int { 42 } // expected-note {{'rdar32431165_overloaded()' produces 'Int', not the expected contextual result type 'E_32431165'}}
func rdar32431165_overloaded() -> String { "A" } // expected-note {{'rdar32431165_overloaded()' produces 'String', not the expected contextual result type 'E_32431165'}}
func test_candidate_diagnostic() {
func test_argument(_: E_32431165) {}
let _: E_32431165 = rdar32431165_overloaded() // expected-error {{no 'rdar32431165_overloaded' candidates produce the expected contextual result type 'E_32431165'}}
test_argument(rdar32431165_overloaded()) // expected-error {{cannot convert value of type 'String' to expected argument type 'E_32431165'}} {{17-17=E_32431165(rawValue: }} {{42-42=) ?? <#default value#>}}
}
func rdar32432253(_ condition: Bool = false) {
let choice: E_32431165 = condition ? .foo : .bar
let _ = choice == "bar"
// expected-error@-1 {{cannot convert value of type 'E_32431165' to expected argument type 'String'}} {{17-17=.rawValue}}
}
// https://github.com/apple/swift/issues/50682
do {
func helper1(_: Int) {}
func helper1(_: Double) {}
func helper2(_: Double) {}
func helper2(_: Int) {}
func helper3(_: Foo) {}
func helper3(_: Bar) {}
func helper4(_: Bar) {}
func helper4(_: Foo) {}
do {
let bar: Bar
helper1(bar)
// expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{16-16=.rawValue}}
helper2(bar)
// expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{16-16=.rawValue}}
helper3(0.0)
// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{13-13=Bar(rawValue: }} {{16-16=) ?? <#default value#>}}
helper4(0.0)
// expected-error@-1 {{cannot convert value of type 'Double' to expected argument type 'Bar'}} {{13-13=Bar(rawValue: }} {{16-16=) ?? <#default value#>}}
}
// Bonus problem with mutable values being passed.
do {
class Box {
var bar: Bar
init(bar: Bar) {}
}
let box: Box
helper1(box.bar)
// expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{20-20=.rawValue}}
var bar = box.bar
helper1(bar)
// expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{16-16=.rawValue}}
}
do {
let opt: Bar?
helper1(opt)
// expected-error@-1 {{cannot convert value of type 'Bar?' to expected argument type 'Double'}} {{16-16=?.rawValue ?? <#default value#>}}
helper1(opt ?? Bar.a)
// expected-error@-1 {{cannot convert value of type 'Bar' to expected argument type 'Double'}} {{13-13=(}} {{25-25=).rawValue}}
let _: Double? = opt
// expected-error@-1 {{cannot convert value of type 'Bar?' to specified type 'Double?'}} {{25-25=?.rawValue}}
}
}
struct NotEquatable { }
enum ArrayOfNewEquatable : Array<NotEquatable> { }
// expected-error@-1{{raw type 'Array<NotEquatable>' is not expressible by a string, integer, or floating-point literal}}
// expected-error@-2{{'ArrayOfNewEquatable' declares raw type 'Array<NotEquatable>', but does not conform to RawRepresentable and conformance could not be synthesized}}
// expected-error@-3{{RawRepresentable conformance cannot be synthesized because raw type 'Array<NotEquatable>' is not Equatable}}
// expected-error@-4{{an enum with no cases cannot declare a raw type}}
// rdar://58127114
struct NotEquatableInteger : ExpressibleByIntegerLiteral {
typealias IntegerLiteralType = Int
init(integerLiteral: Int) {}
}
enum NotEquatableRawType1 : NotEquatableInteger {
// expected-error@-1 {{'NotEquatableRawType1' declares raw type 'NotEquatableInteger', but does not conform to RawRepresentable and conformance could not be synthesized}}
// expected-error@-2 {{RawRepresentable conformance cannot be synthesized because raw type 'NotEquatableInteger' is not Equatable}}
case a = 123
}
enum NotEquatableRawType2 : NotEquatableInteger {
// expected-error@-1 {{'NotEquatableRawType2' declares raw type 'NotEquatableInteger', but does not conform to RawRepresentable and conformance could not be synthesized}}
// expected-error@-2 {{RawRepresentable conformance cannot be synthesized because raw type 'NotEquatableInteger' is not Equatable}}
typealias RawValue = NotEquatableInteger
case a = 123
}
struct NotEquatableString : ExpressibleByStringLiteral {
init(stringLiteral: String) {}
}
// FIXME: This could be diagnosed a bit better. The notes are disembodied
enum NotEquatableRawType3: NotEquatableString {
// expected-error@-1 {{RawRepresentable conformance cannot be synthesized because raw type 'NotEquatableString' is not Equatable}}
// expected-error@-2 {{'NotEquatableRawType3' declares raw type 'NotEquatableString', but does not conform to RawRepresentable and conformance could not be synthesized}}
case a
typealias RawValue = NotEquatableString
init?(rawValue: Int) { self = .a }
// expected-note@-1 {{candidate has non-matching type '(rawValue: Int)'}}
var rawValue: Int { 0 }
// expected-note@-1 {{candidate has non-matching type 'Int'}}
}
enum MismatchedRawValues {
enum ExistentialBound: Any? {
// expected-error@-1 {{raw type 'Any?' is not expressible}}
// expected-error@-2 {{'MismatchedRawValues.ExistentialBound' declares raw type 'Any?'}}
// expected-error@-3 {{RawRepresentable conformance cannot be synthesized }}
case test = nil
}
public enum StringViaStaticString: StaticString {
// expected-error@-1 {{'MismatchedRawValues.StringViaStaticString' declares raw type 'StaticString', but does not conform to RawRepresentable}}
// expected-error@-2 {{RawRepresentable conformance cannot be synthesized because}}
public typealias RawValue = String
case TRUE = "TRUE"
case FALSE = "FALSE"
}
public enum IntViaString: String {
// expected-error@-1 {{'MismatchedRawValues.IntViaString' declares raw type 'String', but does not conform to RawRepresentable}}
public typealias RawValue = Int
case TRUE = "TRUE"
case FALSE = "FALSE"
}
public enum ViaNested: String {
// expected-error@-1 {{'MismatchedRawValues.ViaNested' declares raw type 'String', but does not conform to RawRepresentable}}
struct RawValue: Equatable {
let x: String
}
case TRUE = "TRUE"
case FALSE = "FALSE"
}
public enum ViaGenericBound<RawValue: Equatable>: String {
// expected-error@-1 {{'MismatchedRawValues.ViaGenericBound<RawValue>' declares raw type 'String'}}
typealias RawValue = RawValue
case TRUE = "TRUE"
case FALSE = "FALSE"
}
}
|