Segmentation Fault: 11 with local property wrappers

I recently updated to XCode 12.5, excited to try out new features from Swift 5.4 - particularly local property wrappers. However, upon adding one to try it out, the compiler failed to build the project with the error Segmentation fault: 11. After playing around a bit, I determined that this is happening because the property wrapper does not get initialized with a wrappedValue parameter. Basically something like this:

@propertyWrapper struct Test {
    var wrappedValue: Int

    init() {
        self.wrappedValue = 0
    }
}

class MyClass {
    @Test var classValue: Int // This compiles fine

    func doSomething() {
        @Test var localValue: Int // This compiles with Segmentation fault: 11 error
    }
}

What I'm unsure about is: is this behaviour intentional? If this is supposed to be invalid code (i.e. a property wrapper must have a wrappedValue initializer in order to be used on a local variable) then I think the compiler and XCode should properly convey that information rather than providing an unhelpful error at build time. Alternatively, if this actually should work, then it seems something needs to be fixed with the compiler. I haven't been able to find anything online about which is the case.

1 Like

Not intentional, and this is valid code. There's a bug with local property wrappers that causes a compiler crash when the wrapper is initialized in-line and does not use init(wrappedValue:) for initialization.

EDIT:

For a little more detail, I believe this is an issue with effects checking. Initializing a property wrapper via init(wrappedValue:) is special because the compiler creates a generator function that takes in a wrapped value and returns the backing property wrapper, and this initializer is type-checked specially. When the wrapper uses another initialization mechanism -- e.g. arguments in the wrapper attribute or default initialization like this case -- then the initializer is just part of the AST for the backing property wrapper storage. Local property wrappers use a special mechanism for synthesized variables (including the backing storage and the projected value property if it exists) and they are actually not part of the AST. These "auxiliary variables" instead get visited in the relevant places. I believe the auxiliary variables are not visited in the effects checker, which means the compiler doesn't know whether or not the initializer has any effects, thus causing the crash when attempting to emit the initializer in SILGen.

4 Likes

Any plans or timeline to fix this? Got a DI library that uses @Inject var thing: SomeType as syntax and it'd be great to use that locally.

Heh, yes I plan on fixing the issue. I'll post back here when I put the PR up (although next time, it's best to track bugs on bugs.swift.org).

2 Likes

Here's the fix!

2 Likes