Property Wrappers: Access to both enclosing 'self' and wrapper instance

Changing Self to Wrapper worked, thanks!!

https://bugs.swift.org/browse/SR-12023

1 Like

@suyashsrijan regarding your comment on Jira. Shouldn‘t this example still pass because the class is marked as final?

Yeah, Self and TypeName should be equivalent in a final class, but it's just not supported at the moment (I opened a PR then forgot about it, so sorry about that. I'll try to find some time soon). I think there's a dup for this, so I'll update the JIRA ticket when I find it.

1 Like

Possibly this one? https://bugs.swift.org/browse/SR-11176

Yeah or https://bugs.swift.org/browse/SR-11414. Seems like there are a few dupes!

What's a private API...? From what I can tell looking at Swift's source for PropertyWrappers, this is supported right in the base of Swift, if not described in the docs. I mean, it seems to compile and run without even importing Foundation.

As you said it, it's undocumented implementation which also happens to be prefixed with an underscore which by Swift standards considered as "hands off" or simply private.

I see, well I hope that they make an official way to pass the keypath of a wrapped property into the wrapper, soon-ish.

I want to use this feature. I see it's "private" but I'm not sure what that means. Are both of these possible, or just #1?

  1. It could change and force me to rewrite some code if I want to compile my app again.
  2. It could change and break deployed apps in the App Store.

#1 is fine with me. #2 I need to avoid.

I don't think #2 will happen, but I'm not a compiler expert (could bitcode compilation affect this somehow?).

#1 is more likely, but I don't think it "will change", it rather gets removed and somehow reattached to the new feature in the future for backwards compatibility with existing code Apple already published.

With 99% I'd say you're safe to use it already.

I was worrying about #2 because I thought with Swift 5 ABI stability apps are no longer deployed bundled with a static version of the standard library. So something like this could be there in one version of iOS and disappear in the next. ??

May be a moot point anyway. I can't get that static subscript in the property wrapper to compile without crashing the compiler.

Do you mean that there are compilation errors, or compiler literally crashes? Compiler shouldn't ever crash, so that's a bug you can file at bugs.swift.org

Yes, it literally crashes. I was making the property wrapper type a class. Once I made it a struct, it stopped crashing and worked. I will file a bug soon.

Unfortunately for my case, I also wanted to be able to turn the keypaths into a strings, to store data in dynamic things like CKRecords and SQL insert/update statements, and there is apparently no way to get a string from those ReferenceWritableKeyPaths. (Correct?) Grrr.

Why does only work when wrapping properties of a class? When I wrap properties of a struct, then the property wrapper's wrappedValue function gets called instead of static subscript<EnclosingSelf>(_enclosingInstance observed: EnclosingSelf, wrapped wrappedKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Value>, storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Self>) -> Value. I tried changing the keypath types to WritableKeyPath but it still doesn't work.

Please advise. We really need this functionality to work!

1 Like

I think this limitation exists in the current design of enclosing self property wrappers because there currently is no way to support mutation of an enclosing self value type through the static subscript.

Using ReferenceWritableKeyPath allows you to write a setter for the static subscript because it promises that the value being written to has reference semantics. So, the _enclosingInstance parameter doesn't need to be mutable. Since value types don't have reference semantics, you'd have to use WritableKeyPath, but in order to write to that value, you need the enclosing instance parameter to be mutable. However, inout isn't supported on subscript parameters.

3 Likes

So... can we add support for inout on subscript params? If not, why? If so, when?

It depends on who this “we” is. It can be done, but it has not yet been done, because doing so takes work:

1 Like

I will also say that using inout for the enclosing instance parameter might violate the memory exclusivity issues that the static subscript was aiming to solve (discussed in the original proposal here). I think a general solution to the exclusive access issue might involve a re-think of the design of enclosing self property wrappers.

EDIT: Just to clarify, I'm not 100% sure whether or not passing inout self to the static subscript within the wrapped property setter would violate memory exclusivity.