Skip to content

Commit e1de140

Browse files
committed
[Property Wrappers] Intersect the availability of the wrapped/projected value
setter with the availability of the enclosing scope when inferring the availability of the synthesized setters for an applied property wrapper.
1 parent b85bf55 commit e1de140

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

lib/Sema/TypeCheckStorage.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1968,6 +1968,17 @@ static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage,
19681968

19691969
// Copy availability from the accessor we'll synthesize the setter from.
19701970
SmallVector<Decl *, 2> asAvailableAs;
1971+
1972+
auto addEnclosingScopeAvailability = [&]() {
1973+
Decl *enclosingDecl = storage;
1974+
// Find the innermost enclosing declaration with an @available annotation.
1975+
while ((enclosingDecl = enclosingDecl->getDeclContext()->getAsDecl())) {
1976+
if (enclosingDecl->getAttrs().hasAttribute<AvailableAttr>()) {
1977+
asAvailableAs.push_back(enclosingDecl);
1978+
break;
1979+
}
1980+
}
1981+
};
19711982

19721983
// That could be a property wrapper...
19731984
if (auto var = dyn_cast<VarDecl>(storage)) {
@@ -1978,6 +1989,7 @@ static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage,
19781989
if (info.valueVar) {
19791990
if (auto setter = info.valueVar->getOpaqueAccessor(AccessorKind::Set)) {
19801991
asAvailableAs.push_back(setter);
1992+
addEnclosingScopeAvailability();
19811993
}
19821994
}
19831995
} else if (auto wrapperSynthesizedKind
@@ -1995,6 +2007,7 @@ static AccessorDecl *createSetterPrototype(AbstractStorageDecl *storage,
19952007
if (auto setter
19962008
= info.projectedValueVar->getOpaqueAccessor(AccessorKind::Set)){
19972009
asAvailableAs.push_back(setter);
2010+
addEnclosingScopeAvailability();
19982011
}
19992012
}
20002013
}

test/Sema/generalized_accessors_availability.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,46 @@ func butt(x: inout Butt) { // expected-note*{{}}
6767
x.$wrapped_modify_conditionally_available = 0
6868
}
6969
}
70+
71+
@available(macOS 11.0, *)
72+
struct LessAvailable {
73+
@SetterConditionallyAvailable
74+
var wrapped_setter_more_available: Int
75+
76+
@ModifyConditionallyAvailable
77+
var wrapped_modify_more_available: Int
78+
79+
var nested: Nested
80+
81+
struct Nested {
82+
@SetterConditionallyAvailable
83+
var wrapped_setter_more_available: Int
84+
85+
@ModifyConditionallyAvailable
86+
var wrapped_modify_more_available: Int
87+
}
88+
}
89+
90+
func testInferredAvailability(x: inout LessAvailable) { // expected-error {{'LessAvailable' is only available in macOS 11.0 or newer}} expected-note*{{}}
91+
x.wrapped_setter_more_available = 0 // expected-error {{setter for 'wrapped_setter_more_available' is only available in macOS 11.0 or newer}} expected-note{{}}
92+
x.wrapped_modify_more_available = 0 // expected-error {{setter for 'wrapped_modify_more_available' is only available in macOS 11.0 or newer}} expected-note{{}}
93+
x.$wrapped_setter_more_available = 0 // expected-error {{setter for '$wrapped_setter_more_available' is only available in macOS 11.0 or newer}} expected-note{{}}
94+
x.$wrapped_modify_more_available = 0 // expected-error {{setter for '$wrapped_modify_more_available' is only available in macOS 11.0 or newer}} expected-note{{}}
95+
96+
x.nested.wrapped_setter_more_available = 0 // expected-error {{setter for 'wrapped_setter_more_available' is only available in macOS 11.0 or newer}} expected-note{{}}
97+
x.nested.wrapped_modify_more_available = 0 // expected-error {{setter for 'wrapped_modify_more_available' is only available in macOS 11.0 or newer}} expected-note{{}}
98+
x.nested.$wrapped_setter_more_available = 0 // expected-error {{setter for '$wrapped_setter_more_available' is only available in macOS 11.0 or newer}} expected-note{{}}
99+
x.nested.$wrapped_modify_more_available = 0 // expected-error {{setter for '$wrapped_modify_more_available' is only available in macOS 11.0 or newer}} expected-note{{}}
100+
101+
if #available(macOS 11.0, *) {
102+
x.wrapped_setter_more_available = 0
103+
x.wrapped_modify_more_available = 0
104+
x.$wrapped_setter_more_available = 0
105+
x.$wrapped_modify_more_available = 0
106+
107+
x.nested.wrapped_setter_more_available = 0
108+
x.nested.wrapped_modify_more_available = 0
109+
x.nested.$wrapped_setter_more_available = 0
110+
x.nested.$wrapped_modify_more_available = 0
111+
}
112+
}

0 commit comments

Comments
 (0)