Skip to content

Commit 2acd425

Browse files
authored
Merge pull request #28857 from DougGregor/property-wrappers-unavailable-wrappedvalue
2 parents 37c6be8 + b7532f9 commit 2acd425

File tree

2 files changed

+52
-3
lines changed

2 files changed

+52
-3
lines changed

lib/Sema/TypeCheckStorage.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "CodeSynthesis.h"
1919
#include "TypeChecker.h"
20+
#include "TypeCheckAvailability.h"
2021
#include "TypeCheckDecl.h"
2122
#include "TypeCheckType.h"
2223
#include "swift/AST/ASTContext.h"
@@ -694,7 +695,20 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
694695
// Perform accesses to the wrappedValues along the composition chain.
695696
for (unsigned i : range(firstWrapperIdx, lastWrapperIdx)) {
696697
auto wrapperInfo = var->getAttachedPropertyWrapperTypeInfo(i);
697-
underlyingVars.push_back(wrapperInfo.valueVar);
698+
auto wrappedValue = wrapperInfo.valueVar;
699+
700+
// Check for availability of wrappedValue.
701+
if (accessor->getAccessorKind() == AccessorKind::Get ||
702+
accessor->getAccessorKind() == AccessorKind::Read) {
703+
if (auto *attr = wrappedValue->getAttrs().getUnavailable(ctx)) {
704+
diagnoseExplicitUnavailability(
705+
wrappedValue,
706+
var->getAttachedPropertyWrappers()[i]->getRangeWithAt(),
707+
var->getDeclContext(), nullptr);
708+
}
709+
}
710+
711+
underlyingVars.push_back(wrappedValue);
698712
}
699713
semantics = AccessSemantics::DirectToStorage;
700714
selfAccessKind = SelfAccessorKind::Peer;

test/decl/var/property_wrappers.swift

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ struct Wrapper<T> {
99
init(stored: T) {
1010
self._stored = stored
1111
}
12-
12+
1313
var wrappedValue: T {
1414
get { _stored }
1515
set { _stored = newValue }
1616
}
17-
1817
}
1918

2019
@propertyWrapper
@@ -837,6 +836,42 @@ struct UsesExplicitClosures {
837836
var y: Int
838837
}
839838

839+
// ---------------------------------------------------------------------------
840+
// Enclosing instance diagnostics
841+
// ---------------------------------------------------------------------------
842+
@propertyWrapper
843+
struct Observable<Value> {
844+
private var stored: Value
845+
846+
init(wrappedValue: Value) {
847+
self.stored = wrappedValue
848+
}
849+
850+
@available(*, unavailable, message: "must be in a class")
851+
var wrappedValue: Value { // expected-note{{'wrappedValue' has been explicitly marked unavailable here}}
852+
get { fatalError("called wrappedValue getter") }
853+
set { fatalError("called wrappedValue setter") }
854+
}
855+
856+
static subscript<EnclosingSelf>(
857+
_enclosingInstance observed: EnclosingSelf,
858+
wrapped wrappedKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Value>,
859+
storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Self>
860+
) -> Value {
861+
get {
862+
observed[keyPath: storageKeyPath].stored
863+
}
864+
set {
865+
observed[keyPath: storageKeyPath].stored = newValue
866+
}
867+
}
868+
}
869+
870+
struct MyObservedValueType {
871+
@Observable // expected-error{{'wrappedValue' is unavailable: must be in a class}}
872+
var observedProperty = 17
873+
}
874+
840875
// ---------------------------------------------------------------------------
841876
// Miscellaneous bugs
842877
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)