Property wrapper with wrappedValue of closure type

This @propertyWrapper definition doesn't compile

@propertyWrapper
struct Precomputed<Wrapped> {
  var wrappedValue: () -> Wrapped {
    { projectedValue }
  }

  var projectedValue: Wrapped

  init(wrappedValue: () -> Wrapped) {
    self.projectedValue = wrappedValue()
  }
}

the error is

'init(wrappedValue:)' parameter type ('() -> Wrapped') must be the same as its 'wrappedValue' property type ('() -> Wrapped') or an @autoclosure thereof

but the error makes no sense because it says A must be the same as A, which is of course true.

The error is fixed, though, if I change the initializer to init(wrappedValue: @escaping () -> Wrapped), but that's not actually escaping, and changing it like this would defeat the purpose.

What's the reason behind this? Is it a bug?

3 Likes

The closure value is escaping: it lasts longer than the lifetime of the call to init(wrappedValue:). The diagnostic should be updated for closures, though. Can you file a GitHub issue about that?

Sorry, I read your code backwards! What you’re doing is unusual but I don’t think it breaks the reasoning behind the “wrappedValue type must match” rule.

2 Likes

Looks like a bug, although I doubt people would encounter it frequently.

We have a similar, much more frequently encountered mis-feature – optional closures are always escaping.