Skip to content

Commit ecc363d

Browse files
committed
[Sema] TypeWrappers: Allow wrapping stored properties with attached property wrappers
Type wrapper doesn't wrap anything expect to a private backing storage property. This means that type wrapper is applied first and subsequent `.wrappedValue` and/or `.projectedValue` is referenced for the returned property wrapper type.
1 parent 39b1566 commit ecc363d

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

lib/Sema/TypeCheckStorage.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -923,7 +923,9 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
923923
underlyingVars.push_back({ wrappedValue, isWrapperRefLValue });
924924
}
925925
}
926-
semantics = AccessSemantics::DirectToStorage;
926+
semantics = backing->isAccessedViaTypeWrapper()
927+
? AccessSemantics::DirectToImplementation
928+
: AccessSemantics::DirectToStorage;
927929
selfAccessKind = SelfAccessorKind::Peer;
928930
break;
929931
}
@@ -952,7 +954,9 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
952954
{ var->getAttachedPropertyWrapperTypeInfo(0).projectedValueVar,
953955
isLValue });
954956
}
955-
semantics = AccessSemantics::DirectToStorage;
957+
semantics = backing->isAccessedViaTypeWrapper()
958+
? AccessSemantics::DirectToImplementation
959+
: AccessSemantics::DirectToStorage;
956960
selfAccessKind = SelfAccessorKind::Peer;
957961
break;
958962
}

lib/Sema/TypeCheckTypeWrapper.cpp

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,9 +322,27 @@ bool IsPropertyAccessedViaTypeWrapper::evaluate(Evaluator &evaluator,
322322
if (property->getAttrs().hasAttribute<LazyAttr>())
323323
return false;
324324

325-
// properties with attached property wrappers are not yet supported.
326-
if (property->hasAttachedPropertyWrapper())
327-
return false;
325+
// Properties with attached property wrappers are not considered
326+
// accessible via type wrapper directly, only their backing storage is.
327+
{
328+
// Wrapped property itself `<name>`
329+
if (property->hasAttachedPropertyWrapper())
330+
return false;
331+
332+
// Projection - `$<name>`
333+
if (property->getOriginalWrappedProperty(
334+
PropertyWrapperSynthesizedPropertyKind::Projection))
335+
return false;
336+
337+
// Backing storage (or wrapper property) - `_<name>`.
338+
//
339+
// This is the only thing that wrapper needs to handle because
340+
// all access to the wrapped variable and it's projection
341+
// is routed through it.
342+
if (property->getOriginalWrappedProperty(
343+
PropertyWrapperSynthesizedPropertyKind::Backing))
344+
return true;
345+
}
328346

329347
// Check whether this is a computed property.
330348
{

0 commit comments

Comments
 (0)