Skip to content

Commit

Permalink
Make protocol usage obvious using any and some keywords (#307)
Browse files Browse the repository at this point in the history
Motivation:

Calling through protocols is more expensive than many other types of call.

Modifications:

Annotate each protocol usage with any or some keywords.

Result:

Protocol usage now obvious
  • Loading branch information
PeterAdams-A authored Jun 10, 2024
1 parent 0f170b4 commit d16e216
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 32 deletions.
10 changes: 8 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@

import PackageDescription

let swiftSettings: [SwiftSetting] = [
.enableUpcomingFeature("ExistentialAny"),
]

let package = Package(
name: "swift-log",
products: [
Expand All @@ -26,11 +30,13 @@ let package = Package(
targets: [
.target(
name: "Logging",
dependencies: []
dependencies: [],
swiftSettings: swiftSettings
),
.testTarget(
name: "LoggingTests",
dependencies: ["Logging"]
dependencies: ["Logging"],
swiftSettings: swiftSettings
),
]
)
46 changes: 23 additions & 23 deletions Sources/Logging/Logging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ public struct Logger {
var label: String

@usableFromInline
var handler: LogHandler
var handler: any LogHandler

@inlinable
init(label: String, handler: LogHandler) {
init(label: String, handler: any LogHandler) {
self.label = label
self.handler = handler
}
Expand All @@ -68,7 +68,7 @@ public struct Logger {

/// A computed property to access the `LogHandler`.
@inlinable
public var handler: LogHandler {
public var handler: any LogHandler {
get {
return self._storage.handler
}
Expand All @@ -87,7 +87,7 @@ public struct Logger {
}

@usableFromInline
internal init(label: String, _ handler: LogHandler) {
internal init(label: String, _ handler: any LogHandler) {
self._storage = Storage(label: label, handler: handler)
}
}
Expand Down Expand Up @@ -515,7 +515,7 @@ public enum LoggingSystem {
///
/// - parameters:
/// - factory: A closure that given a `Logger` identifier, produces an instance of the `LogHandler`.
public static func bootstrap(_ factory: @escaping (String) -> LogHandler) {
public static func bootstrap(_ factory: @escaping (String) -> any LogHandler) {
self._factory.replaceFactory({ label, _ in
factory(label)
}, validate: true)
Expand All @@ -531,28 +531,28 @@ public enum LoggingSystem {
/// - parameters:
/// - metadataProvider: The `MetadataProvider` used to inject runtime-generated metadata from the execution context.
/// - factory: A closure that given a `Logger` identifier, produces an instance of the `LogHandler`.
public static func bootstrap(_ factory: @escaping (String, Logger.MetadataProvider?) -> LogHandler,
public static func bootstrap(_ factory: @escaping (String, Logger.MetadataProvider?) -> any LogHandler,
metadataProvider: Logger.MetadataProvider?) {
self._metadataProviderFactory.replaceMetadataProvider(metadataProvider, validate: true)
self._factory.replaceFactory(factory, validate: true)
}

// for our testing we want to allow multiple bootstrapping
internal static func bootstrapInternal(_ factory: @escaping (String) -> LogHandler) {
internal static func bootstrapInternal(_ factory: @escaping (String) -> any LogHandler) {
self._metadataProviderFactory.replaceMetadataProvider(nil, validate: false)
self._factory.replaceFactory({ label, _ in
factory(label)
}, validate: false)
}

// for our testing we want to allow multiple bootstrapping
internal static func bootstrapInternal(_ factory: @escaping (String, Logger.MetadataProvider?) -> LogHandler,
internal static func bootstrapInternal(_ factory: @escaping (String, Logger.MetadataProvider?) -> any LogHandler,
metadataProvider: Logger.MetadataProvider?) {
self._metadataProviderFactory.replaceMetadataProvider(metadataProvider, validate: false)
self._factory.replaceFactory(factory, validate: false)
}

fileprivate static var factory: (String, Logger.MetadataProvider?) -> LogHandler {
fileprivate static var factory: (String, Logger.MetadataProvider?) -> any LogHandler {
return { label, metadataProvider in
self._factory.underlying(label, metadataProvider)
}
Expand Down Expand Up @@ -582,22 +582,22 @@ public enum LoggingSystem {

private final class FactoryBox {
private let lock = ReadWriteLock()
fileprivate var _underlying: (_ label: String, _ provider: Logger.MetadataProvider?) -> LogHandler
fileprivate var _underlying: (_ label: String, _ provider: Logger.MetadataProvider?) -> any LogHandler
private var initialized = false

init(_ underlying: @escaping (String, Logger.MetadataProvider?) -> LogHandler) {
init(_ underlying: @escaping (String, Logger.MetadataProvider?) -> any LogHandler) {
self._underlying = underlying
}

func replaceFactory(_ factory: @escaping (String, Logger.MetadataProvider?) -> LogHandler, validate: Bool) {
func replaceFactory(_ factory: @escaping (String, Logger.MetadataProvider?) -> any LogHandler, validate: Bool) {
self.lock.withWriterLock {
precondition(!validate || !self.initialized, "logging system can only be initialized once per process.")
self._underlying = factory
self.initialized = true
}
}

var underlying: (String, Logger.MetadataProvider?) -> LogHandler {
var underlying: (String, Logger.MetadataProvider?) -> any LogHandler {
return self.lock.withReaderLock {
return self._underlying
}
Expand Down Expand Up @@ -655,7 +655,7 @@ extension Logger {
case string(String)

/// A metadata value which is some `CustomStringConvertible`.
case stringConvertible(CustomStringConvertible & Sendable)
case stringConvertible(any CustomStringConvertible & Sendable)

/// A metadata value which is a dictionary from `String` to `Logger.MetadataValue`.
///
Expand Down Expand Up @@ -728,7 +728,7 @@ extension Logger {
/// - parameters:
/// - label: An identifier for the creator of a `Logger`.
/// - factory: A closure creating non-standard `LogHandler`s.
public init(label: String, factory: (String) -> LogHandler) {
public init(label: String, factory: (String) -> any LogHandler) {
self = Logger(label: label, factory(label))
}

Expand All @@ -743,7 +743,7 @@ extension Logger {
/// - parameters:
/// - label: An identifier for the creator of a `Logger`.
/// - factory: A closure creating non-standard `LogHandler`s.
public init(label: String, factory: (String, Logger.MetadataProvider?) -> LogHandler) {
public init(label: String, factory: (String, Logger.MetadataProvider?) -> any LogHandler) {
self = Logger(label: label, factory(label, LoggingSystem.metadataProvider))
}

Expand Down Expand Up @@ -889,7 +889,7 @@ extension Logger {
/// "more important" than the second handler. The same rule applies when querying for the `metadata` property of the
/// multiplex log handler - it constructs `Metadata` uniquing values.
public struct MultiplexLogHandler: LogHandler {
private var handlers: [LogHandler]
private var handlers: [any LogHandler]
private var effectiveLogLevel: Logger.Level
/// This metadata provider runs after all metadata providers of the multiplexed handlers.
private var _metadataProvider: Logger.MetadataProvider?
Expand All @@ -899,13 +899,13 @@ public struct MultiplexLogHandler: LogHandler {
/// - parameters:
/// - handlers: An array of `LogHandler`s, each of which will receive the log messages sent to this `Logger`.
/// The array must not be empty.
public init(_ handlers: [LogHandler]) {
public init(_ handlers: [any LogHandler]) {
assert(!handlers.isEmpty, "MultiplexLogHandler.handlers MUST NOT be empty")
self.handlers = handlers
self.effectiveLogLevel = handlers.map { $0.logLevel }.min() ?? .trace
}

public init(_ handlers: [LogHandler], metadataProvider: Logger.MetadataProvider?) {
public init(_ handlers: [any LogHandler], metadataProvider: Logger.MetadataProvider?) {
assert(!handlers.isEmpty, "MultiplexLogHandler.handlers MUST NOT be empty")
self.handlers = handlers
self.effectiveLogLevel = handlers.map { $0.logLevel }.min() ?? .trace
Expand Down Expand Up @@ -1009,7 +1009,7 @@ public struct MultiplexLogHandler: LogHandler {
}
}

private mutating func mutatingForEachHandler(_ mutator: (inout LogHandler) -> Void) {
private mutating func mutatingForEachHandler(_ mutator: (inout any LogHandler) -> Void) {
for index in self.handlers.indices {
mutator(&self.handlers[index])
}
Expand Down Expand Up @@ -1126,7 +1126,7 @@ public struct StreamLogHandler: LogHandler {
return StreamLogHandler(label: label, stream: StdioOutputStream.stderr, metadataProvider: metadataProvider)
}

private let stream: _SendableTextOutputStream
private let stream: any _SendableTextOutputStream
private let label: String

public var logLevel: Logger.Level = .info
Expand All @@ -1150,12 +1150,12 @@ public struct StreamLogHandler: LogHandler {
}

// internal for testing only
internal init(label: String, stream: _SendableTextOutputStream) {
internal init(label: String, stream: any _SendableTextOutputStream) {
self.init(label: label, stream: stream, metadataProvider: LoggingSystem.metadataProvider)
}

// internal for testing only
internal init(label: String, stream: _SendableTextOutputStream, metadataProvider: Logger.MetadataProvider?) {
internal init(label: String, stream: any _SendableTextOutputStream, metadataProvider: Logger.MetadataProvider?) {
self.label = label
self.stream = stream
self.metadataProvider = metadataProvider
Expand Down
6 changes: 3 additions & 3 deletions Tests/LoggingTests/CompatibilityTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ private struct OldSchoolTestLogging {
private let _config = Config() // shared among loggers
private let recorder = Recorder() // shared among loggers

func make(label: String) -> LogHandler {
func make(label: String) -> any LogHandler {
return OldSchoolLogHandler(label: label,
config: self.config,
recorder: self.recorder,
Expand All @@ -54,15 +54,15 @@ private struct OldSchoolTestLogging {
}

var config: Config { return self._config }
var history: History { return self.recorder }
var history: some History { return self.recorder }
}

private struct OldSchoolLogHandler: LogHandler {
var label: String
let config: Config
let recorder: Recorder

func make(label: String) -> LogHandler {
func make(label: String) -> some LogHandler {
return TestLogHandler(label: label, config: self.config, recorder: self.recorder)
}

Expand Down
2 changes: 1 addition & 1 deletion Tests/LoggingTests/LoggingTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,7 @@ class LoggingTest: XCTestCase {
}

extension Logger {
public func error(error: Error,
public func error(error: any Error,
metadata: @autoclosure () -> Logger.Metadata? = nil,
file: String = #fileID, function: String = #function, line: UInt = #line) {
self.error("\(error.localizedDescription)", metadata: metadata(), file: file, function: function, line: line)
Expand Down
6 changes: 3 additions & 3 deletions Tests/LoggingTests/TestLogger.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ internal struct TestLogging {
private let _config = Config() // shared among loggers
private let recorder = Recorder() // shared among loggers

func make(label: String) -> LogHandler {
func make(label: String) -> some LogHandler {
return TestLogHandler(
label: label,
config: self.config,
Expand All @@ -31,7 +31,7 @@ internal struct TestLogging {
)
}

func makeWithMetadataProvider(label: String, metadataProvider: Logger.MetadataProvider?) -> LogHandler {
func makeWithMetadataProvider(label: String, metadataProvider: Logger.MetadataProvider?) -> (some LogHandler) {
return TestLogHandler(
label: label,
config: self.config,
Expand All @@ -41,7 +41,7 @@ internal struct TestLogging {
}

var config: Config { return self._config }
var history: History { return self.recorder }
var history: some History { return self.recorder }
}

internal struct TestLogHandler: LogHandler {
Expand Down

0 comments on commit d16e216

Please sign in to comment.