Variadic functions (and CustomStringConvertible)


(Marko Havu) #1

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.


(Marko Havu) #2

Can anyone verify whether this happens on platforms other than Cocoa?


(RemObjects) #3

Thanks, logged as bugs://81979