Swift: method overloading is not reliable
| Originator: | gwendal.roue | ||
| Number: | rdar://19017096 | Date Originated: | 2014-11-18 |
| Status: | Open | Resolved: | |
| Product: | Developper Tools | Product Version: | Xcode 6.1 (6A1052d) |
| Classification: | Serious Bug | Reproducible: | Always |
Summary:
Given a set of argument types, Swift should always chose the same overloaded method in the set of methods that accept those arguments. This is not the case.
Steps to Reproduce:
Run the following code in a Playground:
import Foundation
protocol P1: Printable { }
protocol P2: Printable { }
class Container {
let type: String
init(type: String) {
self.type = type
println(type)
}
convenience init(_ o:AnyObject?) { self.init(type: "AnyObject(\(o))") }
convenience init(_ o:P1) { self.init(type: "P1(\(o.description))") }
convenience init(_ o:P2) { self.init(type: "P2(\(o.description))") }
convenience init(_ o:protocol<P1,P2>) { self.init(type: "P1,P2(\(o.description))") }
convenience init(_ d:[String: Container]) { self.init(type: "Dictionary") }
}
class O1: P1 { let description = "O1" }
class O2: P2 { let description = "O2" }
class O12: P1, P2 { let description = "O12" }
Container([
"a": Container([
"o1": Container(O1()),
"o2": Container(O2()),
"o12": Container(O12()),
"any": Container("string"),
]),
"b": Container([
"o1": Container(O1()),
"o2": Container(O2()),
"o12": Container(O12()),
"any": Container("string"),
]),
])
Expected Results:
The `Container(O1())` expressions should *always* trigger the same Container.init(_ o:P1) constructor, and the program outputs:
P1(O1)
P2(O2)
P1,P2(O12)
AnyObject(Optional(string))
Dictionary
P1(O1)
P2(O2)
P1,P2(O12)
AnyObject(Optional(string))
Dictionary
Dictionary
Actual Results:
The `Container(O1())` expressions sometimes trigger the Container.init(_ o:P1) constructor, and sometimes trigger the convenience init(_ o:AnyObject?) constructor, and outputs:
AnyObject(Optional(__lldb_expr_1511.O1))
AnyObject(Optional(__lldb_expr_1511.O2))
AnyObject(Optional(__lldb_expr_1511.O12))
AnyObject(Optional(string))
Dictionary
P1(O1)
P2(O2)
P1,P2(O12)
AnyObject(Optional(string))
Dictionary
Dictionary
Version:
Xcode 6.1 (6A1052d)
Notes:
This bug is particularly painful when you want to implement an API that relies on method overloading in order to avoid to explicitly give a name to initial parameters. The goal is to be nicer to the API user (who does not have to remember which method to use), and this is better for future compatibility (since newly introduced types or refactored types don't need API change).
See for instance the consequences of this bug in the "TODO: avoid this `as [String: Value]` cast" comments in https://github.com/groue/GRMustache.swift/blob/5be90ab67ada61bc8c0222b2df3edb07cf8889f0/GRMustacheTests/Public/FilterTests/VariadicFilterTests.swift
Configuration:
OSX 10.10 (14A389)
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!