The following piece of code brings up a couple of bugs in CustomStringConvertible protocol and variadic functions (not necessarily connected to each other):
public enum LogLevel: Int, CustomStringConvertible {
case debug
case info
case warning
case error
case fatal
public var description: String { // Method hides a method in parent class
var description: String
switch self {
case .debug:
description = "[DEBUG]"
case .info:
description = "[INFO]"
case .warning:
description = "[WARNING]"
case .error:
description = "[ERROR]"
case .fatal:
description = "[FATAL]"
}
return description
}
}
public final class Logger {
public static let shared = Logger()
private init() {}
public func log(_ message: String, level: LogLevel = .info, _ args: Any...) {
let levelString = String(describing: level) // EXC_BAD_ACCESS
print("\(levelString) \(message) \(args)")
}
}
Logger.shared.log("Testing logging")
Logger.shared.log("Testing logging", level: .error) // No matching overload
Logger.shared.log("Testing logging", level: .error, "param")
Logger.shared.log("Testing logging", level: .error)
works if the level argument does not have a default value, but combining default values and variadic parameters should be allowed in Swift.
The CustomStringConvertible bug also seems to affect enum constructor init(rawValue:)
: it doesn’t work for enums that define description
.