Introduction
Swift macros provide developers with powerful tools for code generation and transformation. However, handling variadic parameters in Swift often requires manual wrapping, which can lead to verbose and error-prone code. This pitch proposes a new compiler-level macro, @VariadicWrapper
, to simplify and automate the wrapping of variadic parameters using custom property wrappers.
The proposed macro enhances code ergonomics by reducing boilerplate and improving clarity while maintaining Swift's strong type system.
Motivation
Variadic parameters are widely used in Swift for functions that accept a variable number of arguments. However, developers often need to manually wrap these parameters in custom types or property wrappers for additional functionality (e.g., validation, transformation, or encapsulation). This process is repetitive and prone to errors.
Example of Current Manual Wrapping:
swift
func testFunction(values: Int...) {
let wrappedValues = Wrapper(wrappedValue: values)
print(wrappedValues)
}
This approach introduces boilerplate code that must be repeated across multiple functions. Instead, we propose automating this process at the compiler level using the @VariadicWrapper
macro.
Proposed Solution:
swift
@VariadicWrapper
func testFunction(values: Int...) {
print(values)
}
// Compiler-generated code:
func testFunction_macro(values: Int...) {
testFunction(values: Wrapper(wrappedValue: [values]))
}
This transformation improves code readability and reduces developer effort while ensuring type safety.
The @VariadicWrapper
macro will be implemented as a built-in attached peer macro that transforms function declarations with variadic parameters. The transformation will generate a companion function that wraps variadic parameters in a custom property wrapper (Wrapper
) automatically.
Key Features:
- Automatic Wrapping: Variadic parameters are wrapped in a
Wrapper
type without manual intervention. - Type Safety: The macro ensures that the wrapped types conform to Swift's type system.
- Improved Ergonomics: Reduces repetitive boilerplate code and improves readability.
Detailed Design
Transformation Logic
The @VariadicWrapper
macro will:
- Detect function declarations annotated with
@VariadicWrapper
. - Identify variadic parameters in the function signature.
- Generate a companion function that wraps variadic parameters using the specified property wrapper (
Wrapper
).
Example Transformation:
Input:
swift
@VariadicWrapper
func testFunction(values: Int...) {
print(values)
}
Generated Code:
swift
func testFunction_macro(values: Int...) {
testFunction(values: Wrapper(wrappedValue: [values]))
}
Type Checking
The compiler will ensure that:
- The
Wrapper
type is valid for the parameter's base type. - Transformed functions are correctly type-checked during semantic analysis.
Example Use Cases
Case 1: Logging Wrapped Values
swift
@VariadicWrapper
func logValues(values: Int...) {
print("Wrapped values:", values)
}
Generated Code:
swift
func logValues_macro(values: Int...) {
logValues(values: Wrapper(wrappedValue: [values]))
}
Case 2: Validation of Variadic Parameters
swift
@propertyWrapper struct ValidatedArray<T> {
var wrappedValue: [T]
init(wrappedValue: [T]) {
self.wrappedValue = wrappedValue.filter { $0 > 0 }
}
}
@VariadicWrapper
func validateValues(values: Int...) {
print("Validated values:", values)
}
Generated Code:
swift
func validateValues_macro(values: Int...) {
validateValues(values: ValidatedArray(wrappedValue: [values]))
}
Source Compatibility
This feature is additive and does not break existing Swift code. Functions without the @VariadicWrapper
annotation will remain unaffected.
Alternatives Considered
- Manual Wrapping
Developers could continue manually wrapping variadic parameters, but this approach increases boilerplate code and reduces clarity. - Library-Level Solutions
Implementing similar functionality at the library level would not leverage the compiler's capabilities, leading to less efficient code generation.
Implementation Plan
- Extend Macro System
Modify Swift's macro processor to support@VariadicWrapper
transformations. - Modify Syntactic Transformations
Extend SwiftSyntax to detect and rewrite function declarations with variadic parameters. - Integrate with Semantic Analysis
Ensure type checking applies correctly to transformed functions. - Test Cases
Add tests to validate the behavior of@VariadicWrapper
under various scenarios.
Conclusion
The proposed @VariadicWrapper
macro simplifies handling of variadic parameters by automating their wrapping at the compiler level. This feature improves code ergonomics, reduces boilerplate, and adheres to Swift's strong type system principles.
feedback is welcome from the community on this pitch!