Hey everyone ![]()
I'm Janat, a final year computer science student! I'm excited to share my progress working with my mentor @xedin on an "unofficial" GSoC project this past summer - hence the logical not ('!') in the title! The original GSoC project title was: 'Re-implement Property Wrappers with Macros'
Context: Despite my mentor's approval of my proposal, we were told that Google could only fund a select number of projects, and ours was not selected for funding. Despite this, however, me and my mentor decided to have a go at it this summer!
The Motivation
Property wrappers are currently handled through a mix of ad-hoc logic in multiple parts of the compiler. The long term goal is to re-implement them using well-defined features like macros and init accessors, making the implementation more consistent, maintainable, and easier to reason about.
Finished Progress 
This summer, we focused on the first step toward the larger goal of re-implementing property wrappers: unifying their initialization with init accessors.
Previously, SILGen emitted an ad-hoc assign_by_wrapper instruction whenever it encountered an ambiguous property-wrapper assignment -- one where it couldn’t determine whether the statement was an initialization or a reassignment. We’ve replaced this with assign_or_init, unifying property-wrapper initialization with the same ambiguous-assignment handling path used by init accessors.
Here is the PR that implements this change - [SILGen] Remove and replace ad-hoc assign_by_wrapper instruction
Detailed Context
Here's an example of an ambiguous assignment:
@propertyWrapper
struct MyWrapper { /* ... */ }
struct MyStruct {
@MyWrapper var x: Int
init(inputVal: Int) {
// Is this '=' initializing 'x' or reassigning it?
// SILGen used to emit 'assign_by_wrapper' and let DI resolve it later.
self.x = inputVal
}
}
Definite Initialization (DI) is a mandatory SIL pass that ensures variables are fully initialized before use. By switching to assign_or_init, we leverage DI’s existing logic and avoid maintaining separate property-wrapper-specific behavior.
As part of this change, SILGen now synthesizes and attaches an init accessor thunk for the wrapped property when it determines that assignment is in an ambiguous context. This thunk performs the backing storage initialization directly, and is passed into the assign_or_init instruction. The thunk's behaviour is shown below:
var x: Int {
@storageRestrictions(initializes: _x)
init(initialValue) {
self._x = MyWrapper(wrappedValue: initialValue)
}
// getter and setter elided
}
Future Work
There is still a long way to go before property wrappers are fully re-implemented in terms of init accessor and macros. Possible extensions to init accessors (e.g. support for local contexts) and macros may be needed for the re-implementation to reach the finish line.
In the future, If time and opportunity permit, I’d love to continue building on this work -- but for now, I’m glad to have contributed this single piece of the puzzle.
Closing Thoughts
This was my first large-scale open-source contribution, and it has been such a rewarding experience. Debugging, iterating, and refining this work taught me so much about the Swift compiler’s internals and gave me more confidence as an engineer.
I’ve probably expressed my gratitude to my mentor, @xedin, a dozen times already over the course of the summer haha -- but it’s worth saying again. His patience, depth of knowledge, and generosity with his time completely shaped this experience. I’m incredibly thankful for the guidance and mentorship that made this contribution not just possible, but one of the most meaningful experiences of my early career ![]()