Skip to content

Commit 61cb9a5

Browse files
authored
Merge pull request swiftlang#32866 from hborla/property-wrapper-autoclosure
[Property Wrappers] Use autoclosure information from CSApply to compute `VarDecl::getPropertyWrapperInitValueInterfaceType`
2 parents 6a255ec + 28a817b commit 61cb9a5

19 files changed

+196
-180
lines changed

include/swift/AST/Decl.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5221,10 +5221,6 @@ class VarDecl : public AbstractStorageDecl {
52215221
/// a suitable `init(wrappedValue:)`.
52225222
bool isPropertyMemberwiseInitializedWithWrappedType() const;
52235223

5224-
/// Whether the innermost property wrapper's initializer's 'wrappedValue' parameter
5225-
/// is marked with '@autoclosure' and '@escaping'.
5226-
bool isInnermostPropertyWrapperInitUsesEscapingAutoClosure() const;
5227-
52285224
/// Return the interface type of the value used for the 'wrappedValue:'
52295225
/// parameter when initializing a property wrapper.
52305226
///

include/swift/AST/Expr.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4156,16 +4156,20 @@ class PropertyWrapperValuePlaceholderExpr : public Expr {
41564156
SourceRange Range;
41574157
OpaqueValueExpr *Placeholder;
41584158
Expr *WrappedValue;
4159+
bool IsAutoClosure = false;
41594160

41604161
PropertyWrapperValuePlaceholderExpr(SourceRange Range, Type Ty,
41614162
OpaqueValueExpr *placeholder,
4162-
Expr *wrappedValue)
4163+
Expr *wrappedValue,
4164+
bool isAutoClosure)
41634165
: Expr(ExprKind::PropertyWrapperValuePlaceholder, /*Implicit=*/true, Ty),
4164-
Range(Range), Placeholder(placeholder), WrappedValue(wrappedValue) {}
4166+
Range(Range), Placeholder(placeholder), WrappedValue(wrappedValue),
4167+
IsAutoClosure(isAutoClosure) {}
41654168

41664169
public:
41674170
static PropertyWrapperValuePlaceholderExpr *
4168-
create(ASTContext &ctx, SourceRange range, Type ty, Expr *wrappedValue);
4171+
create(ASTContext &ctx, SourceRange range, Type ty, Expr *wrappedValue,
4172+
bool isAutoClosure = false);
41694173

41704174
/// The original wrappedValue initialization expression provided via
41714175
/// \c = on a proprety with attached property wrappers.
@@ -4187,6 +4191,8 @@ class PropertyWrapperValuePlaceholderExpr : public Expr {
41874191
Placeholder = placeholder;
41884192
}
41894193

4194+
bool isAutoClosure() const { return IsAutoClosure; }
4195+
41904196
SourceRange getSourceRange() const { return Range; }
41914197

41924198
static bool classof(const Expr *E) {

include/swift/AST/PropertyWrappers.h

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@ struct PropertyWrapperTypeInfo {
4343
HasInitialValueInit
4444
} wrappedValueInit = NoWrappedValueInit;
4545

46-
/// Whether the init(wrappedValue:), if it exists, has the wrappedValue
47-
/// argument as an escaping autoclosure.
48-
bool isWrappedValueInitUsingEscapingAutoClosure = false;
49-
5046
/// The initializer that will be called to default-initialize a
5147
/// value with an attached property wrapper.
5248
enum {
@@ -153,37 +149,24 @@ struct PropertyWrapperBackingPropertyInfo {
153149
/// '$foo' from `backingVar`.
154150
VarDecl *storageWrapperVar = nullptr;
155151

156-
/// When the original default value is specified in terms of an '='
157-
/// initializer on the initial property, e.g.,
158-
///
159-
/// \code
160-
/// @Lazy var i = 17
161-
/// \endcode
162-
///
163-
/// This is the specified initial value (\c 17), which is suitable for
164-
/// embedding in the expression \c initializeFromOriginal.
165-
Expr *originalInitialValue = nullptr;
166-
167152
/// An expression that initializes the backing property from a value of
168153
/// the original property's type (e.g., via `init(wrappedValue:)`), or
169154
/// \c NULL if the backing property can only be initialized directly.
170155
Expr *initializeFromOriginal = nullptr;
171156

172157
/// When \c initializeFromOriginal is non-NULL, the opaque value that
173158
/// is used as a stand-in for a value of the original property's type.
174-
OpaqueValueExpr *underlyingValue = nullptr;
159+
PropertyWrapperValuePlaceholderExpr *wrappedValuePlaceholder = nullptr;
175160

176161
PropertyWrapperBackingPropertyInfo() { }
177162

178163
PropertyWrapperBackingPropertyInfo(VarDecl *backingVar,
179-
VarDecl *storageWrapperVar,
180-
Expr *originalInitialValue,
181-
Expr *initializeFromOriginal,
182-
OpaqueValueExpr *underlyingValue)
164+
VarDecl *storageWrapperVar,
165+
Expr *initializeFromOriginal,
166+
PropertyWrapperValuePlaceholderExpr *placeholder)
183167
: backingVar(backingVar), storageWrapperVar(storageWrapperVar),
184-
originalInitialValue(originalInitialValue),
185168
initializeFromOriginal(initializeFromOriginal),
186-
underlyingValue(underlyingValue) { }
169+
wrappedValuePlaceholder(placeholder) { }
187170

188171
/// Whether this is a valid property wrapper.
189172
bool isValid() const {

lib/AST/Decl.cpp

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6067,21 +6067,14 @@ bool VarDecl::isPropertyMemberwiseInitializedWithWrappedType() const {
60676067
return allAttachedPropertyWrappersHaveWrappedValueInit();
60686068
}
60696069

6070-
bool VarDecl::isInnermostPropertyWrapperInitUsesEscapingAutoClosure() const {
6071-
auto customAttrs = getAttachedPropertyWrappers();
6072-
if (customAttrs.empty())
6073-
return false;
6074-
6075-
unsigned innermostWrapperIndex = customAttrs.size() - 1;
6076-
auto typeInfo = getAttachedPropertyWrapperTypeInfo(innermostWrapperIndex);
6077-
return typeInfo.isWrappedValueInitUsingEscapingAutoClosure;
6078-
}
6079-
60806070
Type VarDecl::getPropertyWrapperInitValueInterfaceType() const {
6081-
Type valueInterfaceTy = getValueInterfaceType();
6071+
auto wrapperInfo = getPropertyWrapperBackingPropertyInfo();
6072+
if (!wrapperInfo || !wrapperInfo.wrappedValuePlaceholder)
6073+
return Type();
60826074

6083-
if (isInnermostPropertyWrapperInitUsesEscapingAutoClosure())
6084-
return FunctionType::get({}, valueInterfaceTy);
6075+
Type valueInterfaceTy = wrapperInfo.wrappedValuePlaceholder->getType();
6076+
if (valueInterfaceTy->hasArchetype())
6077+
valueInterfaceTy = valueInterfaceTy->mapTypeOutOfContext();
60856078

60866079
return valueInterfaceTy;
60876080
}

lib/AST/Expr.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,13 +1463,13 @@ static ValueDecl *getCalledValue(Expr *E) {
14631463

14641464
PropertyWrapperValuePlaceholderExpr *
14651465
PropertyWrapperValuePlaceholderExpr::create(ASTContext &ctx, SourceRange range,
1466-
Type ty, Expr *wrappedValue) {
1466+
Type ty, Expr *wrappedValue,
1467+
bool isAutoClosure) {
14671468
auto *placeholder =
14681469
new (ctx) OpaqueValueExpr(range, ty, /*isPlaceholder=*/true);
14691470

1470-
return new (ctx) PropertyWrapperValuePlaceholderExpr(range, ty,
1471-
placeholder,
1472-
wrappedValue);
1471+
return new (ctx) PropertyWrapperValuePlaceholderExpr(
1472+
range, ty, placeholder, wrappedValue, isAutoClosure);
14731473
}
14741474

14751475
const ParamDecl *DefaultArgumentExpr::getParamDecl() const {

lib/SIL/IR/TypeLowering.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,17 @@ static CanAnyFunctionType getGlobalAccessorType(CanType varType) {
20522052
return CanFunctionType::get({}, C.TheRawPointerType);
20532053
}
20542054

2055+
/// Removes @noescape from the given type if it's a function type. Otherwise,
2056+
/// returns the original type.
2057+
static CanType removeNoEscape(CanType resultType) {
2058+
if (auto funTy = resultType->getAs<AnyFunctionType>()) {
2059+
auto newExtInfo = funTy->getExtInfo().withNoEscape(false);
2060+
return adjustFunctionType(cast<AnyFunctionType>(resultType), newExtInfo);
2061+
}
2062+
2063+
return resultType;
2064+
}
2065+
20552066
/// Get the type of a default argument generator, () -> T.
20562067
static CanAnyFunctionType getDefaultArgGeneratorInterfaceType(
20572068
SILDeclRef c) {
@@ -2068,11 +2079,7 @@ static CanAnyFunctionType getDefaultArgGeneratorInterfaceType(
20682079

20692080
// Remove @noescape from function return types. A @noescape
20702081
// function return type is a contradiction.
2071-
if (auto funTy = canResultTy->getAs<AnyFunctionType>()) {
2072-
auto newExtInfo = funTy->getExtInfo().withNoEscape(false);
2073-
canResultTy =
2074-
adjustFunctionType(cast<AnyFunctionType>(canResultTy), newExtInfo);
2075-
}
2082+
canResultTy = removeNoEscape(canResultTy);
20762083

20772084
// Get the generic signature from the surrounding context.
20782085
auto sig = vd->getInnermostDeclContext()->getGenericSignatureOfContext();
@@ -2103,6 +2110,8 @@ static CanAnyFunctionType getStoredPropertyInitializerInterfaceType(
21032110
if (originalProperty->isPropertyMemberwiseInitializedWithWrappedType()) {
21042111
resultTy = originalProperty->getPropertyWrapperInitValueInterfaceType()
21052112
->getCanonicalType();
2113+
// Stored property initializers can't return @noescape functions
2114+
resultTy = removeNoEscape(resultTy);
21062115
}
21072116
}
21082117

lib/SILGen/SILGen.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -770,8 +770,8 @@ static void emitDelayedFunction(SILGenModule &SGM,
770770
->isPropertyMemberwiseInitializedWithWrappedType()) {
771771
auto wrapperInfo =
772772
originalProperty->getPropertyWrapperBackingPropertyInfo();
773-
assert(wrapperInfo.originalInitialValue);
774-
init = wrapperInfo.originalInitialValue;
773+
assert(wrapperInfo.wrappedValuePlaceholder->getOriginalWrappedValue());
774+
init = wrapperInfo.wrappedValuePlaceholder->getOriginalWrappedValue();
775775
}
776776
}
777777

lib/SILGen/SILGenConstructor.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,9 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
230230
// the property wrapper backing initializer.
231231
if (auto *wrappedVar = field->getOriginalWrappedProperty()) {
232232
auto wrappedInfo = wrappedVar->getPropertyWrapperBackingPropertyInfo();
233-
if (wrappedInfo.originalInitialValue) {
234-
auto arg = SGF.emitRValue(wrappedInfo.originalInitialValue);
233+
auto *placeholder = wrappedInfo.wrappedValuePlaceholder;
234+
if (placeholder && placeholder->getOriginalWrappedValue()) {
235+
auto arg = SGF.emitRValue(placeholder->getOriginalWrappedValue());
235236
maybeEmitPropertyWrapperInitFromValue(SGF, Loc, field, subs,
236237
std::move(arg))
237238
.forwardInto(SGF, Loc, init.get());
@@ -274,8 +275,9 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF,
274275
// memberwise initialized, use the original wrapped value if it exists.
275276
if (auto *wrappedVar = field->getOriginalWrappedProperty()) {
276277
auto wrappedInfo = wrappedVar->getPropertyWrapperBackingPropertyInfo();
277-
if (wrappedInfo.originalInitialValue) {
278-
init = wrappedInfo.originalInitialValue;
278+
auto *placeholder = wrappedInfo.wrappedValuePlaceholder;
279+
if (placeholder && placeholder->getOriginalWrappedValue()) {
280+
init = placeholder->getOriginalWrappedValue();
279281
}
280282
}
281283

lib/SILGen/SILGenFunction.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -805,9 +805,10 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
805805
RegularLocation Loc(value);
806806
Loc.markAutoGenerated();
807807

808-
// Default argument generators of function typed values return noescape
809-
// functions. Strip the escape to noescape function conversion.
810-
if (function.kind == SILDeclRef::Kind::DefaultArgGenerator) {
808+
// If a default argument or stored property initializer value is a noescape
809+
// function type, strip the escape to noescape function conversion.
810+
if (function.kind == SILDeclRef::Kind::DefaultArgGenerator ||
811+
function.kind == SILDeclRef::Kind::StoredPropertyInitializer) {
811812
if (auto funType = value->getType()->getAs<AnyFunctionType>()) {
812813
if (funType->getExtInfo().isNoEscape()) {
813814
auto conv = cast<FunctionConversionExpr>(value);
@@ -852,7 +853,8 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value,
852853
auto var = cast<VarDecl>(function.getDecl());
853854
auto wrappedInfo = var->getPropertyWrapperBackingPropertyInfo();
854855
auto param = params->get(0);
855-
opaqueValue.emplace(*this, wrappedInfo.underlyingValue,
856+
auto *placeholder = wrappedInfo.wrappedValuePlaceholder;
857+
opaqueValue.emplace(*this, placeholder->getOpaqueValuePlaceholder(),
856858
maybeEmitValueOfLocalVarDecl(param));
857859

858860
assert(value == wrappedInfo.initializeFromOriginal);
@@ -881,6 +883,11 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, VarDecl *var) {
881883
if (auto originalProperty = var->getOriginalWrappedProperty()) {
882884
if (originalProperty->isPropertyMemberwiseInitializedWithWrappedType()) {
883885
interfaceType = originalProperty->getPropertyWrapperInitValueInterfaceType();
886+
887+
if (auto fnType = interfaceType->getAs<AnyFunctionType>()) {
888+
auto newExtInfo = fnType->getExtInfo().withNoEscape(false);
889+
interfaceType = fnType->withExtInfo(newExtInfo);
890+
}
884891
}
885892
}
886893

lib/SILGen/SILGenLValue.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1335,10 +1335,7 @@ namespace {
13351335
// the argument types of the setter and initializer shall be
13361336
// different, so we don't rewrite an assignment into an
13371337
// initialization.
1338-
if (VD->isInnermostPropertyWrapperInitUsesEscapingAutoClosure())
1339-
return false;
1340-
1341-
return true;
1338+
return !wrapperInfo.wrappedValuePlaceholder->isAutoClosure();
13421339
}
13431340

13441341
return false;

0 commit comments

Comments
 (0)