Skip to content

Commit 28a817b

Browse files
committed
[Property Wrappers] Treat default wrapped values that are noescape
autoclosures the same way we treat default arguments that are noescape autoclosures.
1 parent a6c33a9 commit 28a817b

File tree

6 files changed

+65
-27
lines changed

6 files changed

+65
-27
lines changed

lib/SIL/IR/TypeLowering.cpp

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

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

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

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

lib/SILGen/SILGenFunction.cpp

Lines changed: 9 additions & 3 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);
@@ -882,6 +883,11 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, VarDecl *var) {
882883
if (auto originalProperty = var->getOriginalWrappedProperty()) {
883884
if (originalProperty->isPropertyMemberwiseInitializedWithWrappedType()) {
884885
interfaceType = originalProperty->getPropertyWrapperInitValueInterfaceType();
886+
887+
if (auto fnType = interfaceType->getAs<AnyFunctionType>()) {
888+
auto newExtInfo = fnType->getExtInfo().withNoEscape(false);
889+
interfaceType = fnType->withExtInfo(newExtInfo);
890+
}
885891
}
886892
}
887893

lib/Sema/CSApply.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5488,16 +5488,17 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, AnyFunctionType *funcType,
54885488
bool shouldInjectWrappedValuePlaceholder =
54895489
target->shouldInjectWrappedValuePlaceholder(apply);
54905490

5491-
auto injectWrappedValuePlaceholder = [&](Expr *arg) -> Expr * {
5492-
auto *placeholder = PropertyWrapperValuePlaceholderExpr::create(
5493-
ctx, arg->getSourceRange(), cs.getType(arg),
5494-
target->propertyWrapperHasInitialWrappedValue() ? arg : nullptr,
5495-
isa<AutoClosureExpr>(arg));
5496-
cs.cacheType(placeholder);
5497-
cs.cacheType(placeholder->getOpaqueValuePlaceholder());
5498-
shouldInjectWrappedValuePlaceholder = false;
5499-
return placeholder;
5500-
};
5491+
auto injectWrappedValuePlaceholder =
5492+
[&](Expr *arg, bool isAutoClosure = false) -> Expr * {
5493+
auto *placeholder = PropertyWrapperValuePlaceholderExpr::create(
5494+
ctx, arg->getSourceRange(), cs.getType(arg),
5495+
target->propertyWrapperHasInitialWrappedValue() ? arg : nullptr,
5496+
isAutoClosure);
5497+
cs.cacheType(placeholder);
5498+
cs.cacheType(placeholder->getOpaqueValuePlaceholder());
5499+
shouldInjectWrappedValuePlaceholder = false;
5500+
return placeholder;
5501+
};
55015502

55025503
// Quickly test if any further fix-ups for the argument types are necessary.
55035504
if (AnyFunctionType::equalParams(args, params) &&
@@ -5696,8 +5697,11 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, AnyFunctionType *funcType,
56965697
// the effect of autoclosure forwarding of the placeholder
56975698
// autoclosure. The only way to do this is to call the placeholder
56985699
// autoclosure when passing it to the init.
5700+
bool isDefaultWrappedValue =
5701+
target->propertyWrapperHasInitialWrappedValue();
56995702
auto *placeholder = injectWrappedValuePlaceholder(
5700-
cs.buildAutoClosureExpr(arg, closureType));
5703+
cs.buildAutoClosureExpr(arg, closureType, isDefaultWrappedValue),
5704+
/*isAutoClosure=*/true);
57015705
arg = CallExpr::createImplicit(ctx, placeholder, {}, {});
57025706
arg->setType(closureType->getResult());
57035707
cs.cacheType(arg);

lib/Sema/ConstraintSystem.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4432,12 +4432,16 @@ ConstraintSystem::isConversionEphemeral(ConversionRestrictionKind conversion,
44324432
}
44334433

44344434
Expr *ConstraintSystem::buildAutoClosureExpr(Expr *expr,
4435-
FunctionType *closureType) {
4435+
FunctionType *closureType,
4436+
bool isDefaultWrappedValue) {
44364437
auto &Context = DC->getASTContext();
44374438
bool isInDefaultArgumentContext = false;
4438-
if (auto *init = dyn_cast<Initializer>(DC))
4439+
if (auto *init = dyn_cast<Initializer>(DC)) {
4440+
auto initKind = init->getInitializerKind();
44394441
isInDefaultArgumentContext =
4440-
init->getInitializerKind() == InitializerKind::DefaultArgument;
4442+
initKind == InitializerKind::DefaultArgument ||
4443+
(initKind == InitializerKind::PatternBinding && isDefaultWrappedValue);
4444+
}
44414445

44424446
auto info = closureType->getExtInfo();
44434447
auto newClosureType = closureType;

lib/Sema/ConstraintSystem.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4094,7 +4094,8 @@ class ConstraintSystem {
40944094

40954095
/// Build implicit autoclosure expression wrapping a given expression.
40964096
/// Given expression represents computed result of the closure.
4097-
Expr *buildAutoClosureExpr(Expr *expr, FunctionType *closureType);
4097+
Expr *buildAutoClosureExpr(Expr *expr, FunctionType *closureType,
4098+
bool isDefaultWrappedValue = false);
40984099

40994100
/// Builds a type-erased return expression that can be used in dynamic
41004101
/// replacement.

test/SILGen/property_wrappers.swift

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,25 @@ struct WrapperWithNonEscapingAutoclosure<V> {
309309
}
310310

311311
struct UseWrapperWithNonEscapingAutoclosure {
312-
@WrapperWithNonEscapingAutoclosure var foo: Int
312+
@WrapperWithNonEscapingAutoclosure var p1: Int
313+
@WrapperWithNonEscapingAutoclosure var p2: UInt = 10
313314

314-
// Memberwise init should take an Int arg, not a closure
315-
// CHECK: // UseWrapperWithNonEscapingAutoclosure.init(foo:)
316-
// CHECK: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV3fooACSiyXK_tcfC : $@convention(method) (@noescape @callee_guaranteed () -> Int, @thin UseWrapperWithNonEscapingAutoclosure.Type) -> UseWrapperWithNonEscapingAutoclosure
315+
// property wrapper backing initializer of UseWrapperWithNonEscapingAutoclosure.p1
316+
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV2p1SivpfP : $@convention(thin) (@noescape @callee_guaranteed () -> Int) -> WrapperWithNonEscapingAutoclosure<Int>
317+
318+
// property wrapper backing initializer of UseWrapperWithNonEscapingAutoclosure.p2
319+
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV2p2SuvpfP : $@convention(thin) (@noescape @callee_guaranteed () -> UInt) -> WrapperWithNonEscapingAutoclosure<UInt>
320+
321+
// variable initialization expression of UseWrapperWithNonEscapingAutoclosure._p2
322+
// CHECK-LABEL: sil hidden [transparent] [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV3_p233_F728088E0028E14D18C6A10CF68512E8LLAA0defgH0VySuGvpfi : $@convention(thin) () -> @owned @callee_guaranteed () -> UInt
323+
// CHECK: return %1 : $@callee_guaranteed () -> UInt
324+
325+
// default argument 1 of UseWrapperWithNonEscapingAutoclosure.init(p1:p2:)
326+
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV2p12p2ACSiyXK_SuyXKtcfcfA0_ : $@convention(thin) () -> @owned @callee_guaranteed () -> UInt
327+
// CHECK: return %1 : $@callee_guaranteed () -> UInt
328+
329+
// UseWrapperWithNonEscapingAutoclosure.init(p1:p2:)
330+
// CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV2p12p2ACSiyXK_SuyXKtcfC : $@convention(method) (@noescape @callee_guaranteed () -> Int, @noescape @callee_guaranteed () -> UInt, @thin UseWrapperWithNonEscapingAutoclosure.Type) -> UseWrapperWithNonEscapingAutoclosure
317331
}
318332

319333
struct UseStatic {

0 commit comments

Comments
 (0)