[swift-users] [swift-evolution] Very strange automatic behavior between StringLiteralConvertible and pattern matching

David Hart david at hartbit.com
Wed Jan 6 06:12:22 CST 2016


I'm starting to understand. The implementation of RawRepresentable's probably looks like this:

init?(rawValue: String) {
    switch rawValue {
    case "firstValue": self = .FirstCase
    case "secondValue": self = .SecondCase
    default: return nil
    }
}

In that case (no pun intended), the switch cases are converted to SomeStringLiteralConvertibleType and then pattern matched.

But shouldn't the implementation of switch refrain from any complicated casting when the types correspond?

David.

> On 06 Jan 2016, at 10:20, David Hart via swift-evolution <swift-evolution at swift.org> wrote:
> 
> To bring a little bit more context: I copied this Regex library in my project which had StringLiteralConvertible and implemented the pattern matching operator and all of a sudden, ALL init(rawValue: String) calls of completely unrelated enums started returning unexpected values. If I did not have unit tests, I probably would not have found out about it for a while.
> 
> I understand the mechanism which calls StringLiteralConvertible's init(stringLiteral) under the hood:
> 
> let a: SomeStringLiteralConvertibleType = "hello"
> 
> I also understand the magic in the pattern matching operator. But I don't understand why when associating them together:
> 
> func ~=(lhs: SomeStringLiteralConvertibleType, rhs: String) -> Bool {
>     return false
> }
> 
> Then creates his behaviour in all Enums with String raw values:
> 
> enum MyEnum: String {
>     case Super = "super"
> }
> 
> let a = MyEnum(rawValue: "super") // nil
> 
> I can't figure out if this is just a confusing behaviour of Swift, in which case I want to write a proposal to make it less confusing, or if it is a big with Swift, in which case I should open a bug report.
> 
> David
> 
>> On 05 Jan 2016, at 18:26, David Hart via swift-users <swift-users at swift.org> wrote:
>> 
>> How is it that Swift allows code like this:
>> 
>> struct Sneaky: StringLiteralConvertible {
>> 	init(stringLiteral value: String) {}
>> 	init(extendedGraphemeClusterLiteral value: String) {}
>> 	init(unicodeScalarLiteral value: String) {}
>> }
>> 
>> func ~=(sneaky: Sneaky, string: String) -> Bool {
>> 	return false
>> }
>> 
>> enum NormalEnum: String {
>> 	case Super = "super"
>> 	case Mario = "mario"
>> }
>> 
>> let value = NormalEnum(rawValue: "super”) // return nil!!!!
>> 
>> It hit completely by surprise today because of of a Regex library:
>> 
>> struct Regex: StringLiteralConvertible {
>> 	init(stringLiteral value: String) {}
>> 	init(extendedGraphemeClusterLiteral value: String) {}
>> 	init(unicodeScalarLiteral value: String) {}
>> 
>> 	//...
>> }
>> 
>> func ~=(regex: Regex, string: String) -> Bool {
>> 	return regex.matches(string)
>> }
>> 
>> If I was not already a Swift enthusiast, this behaviour would have left me completely dumbfounded.
>> What can we do about it?
>> 
>> David.
>> 
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160106/529bce48/attachment.html>


More information about the swift-users mailing list