diff --git a/include/swift/AST/Decl.h b/include/swift/AST/Decl.h index 8848b5c2360..09517f27108 100644 --- a/include/swift/AST/Decl.h +++ b/include/swift/AST/Decl.h @@ -5221,10 +5221,6 @@ public: /// a suitable `init(wrappedValue:)`. bool isPropertyMemberwiseInitializedWithWrappedType() const; - /// Whether the innermost property wrapper's initializer's 'wrappedValue' parameter - /// is marked with '@autoclosure' and '@escaping'. - bool isInnermostPropertyWrapperInitUsesEscapingAutoClosure() const; - /// Return the interface type of the value used for the 'wrappedValue:' /// parameter when initializing a property wrapper. /// diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index eaca55f9513..5a4763dd5e6 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -4165,16 +4165,20 @@ class PropertyWrapperValuePlaceholderExpr : public Expr { SourceRange Range; OpaqueValueExpr *Placeholder; Expr *WrappedValue; + bool IsAutoClosure = false; PropertyWrapperValuePlaceholderExpr(SourceRange Range, Type Ty, OpaqueValueExpr *placeholder, - Expr *wrappedValue) + Expr *wrappedValue, + bool isAutoClosure) : Expr(ExprKind::PropertyWrapperValuePlaceholder, /*Implicit=*/true, Ty), - Range(Range), Placeholder(placeholder), WrappedValue(wrappedValue) {} + Range(Range), Placeholder(placeholder), WrappedValue(wrappedValue), + IsAutoClosure(isAutoClosure) {} public: static PropertyWrapperValuePlaceholderExpr * - create(ASTContext &ctx, SourceRange range, Type ty, Expr *wrappedValue); + create(ASTContext &ctx, SourceRange range, Type ty, Expr *wrappedValue, + bool isAutoClosure = false); /// The original wrappedValue initialization expression provided via /// \c = on a proprety with attached property wrappers. @@ -4196,6 +4200,8 @@ public: Placeholder = placeholder; } + bool isAutoClosure() const { return IsAutoClosure; } + SourceRange getSourceRange() const { return Range; } static bool classof(const Expr *E) { diff --git a/include/swift/AST/PropertyWrappers.h b/include/swift/AST/PropertyWrappers.h index 5ad7db49475..f1a1b574902 100644 --- a/include/swift/AST/PropertyWrappers.h +++ b/include/swift/AST/PropertyWrappers.h @@ -43,10 +43,6 @@ struct PropertyWrapperTypeInfo { HasInitialValueInit } wrappedValueInit = NoWrappedValueInit; - /// Whether the init(wrappedValue:), if it exists, has the wrappedValue - /// argument as an escaping autoclosure. - bool isWrappedValueInitUsingEscapingAutoClosure = false; - /// The initializer that will be called to default-initialize a /// value with an attached property wrapper. enum { @@ -153,17 +149,6 @@ struct PropertyWrapperBackingPropertyInfo { /// '$foo' from `backingVar`. VarDecl *storageWrapperVar = nullptr; - /// When the original default value is specified in terms of an '=' - /// initializer on the initial property, e.g., - /// - /// \code - /// @Lazy var i = 17 - /// \endcode - /// - /// This is the specified initial value (\c 17), which is suitable for - /// embedding in the expression \c initializeFromOriginal. - Expr *originalInitialValue = nullptr; - /// An expression that initializes the backing property from a value of /// the original property's type (e.g., via `init(wrappedValue:)`), or /// \c NULL if the backing property can only be initialized directly. @@ -171,19 +156,17 @@ struct PropertyWrapperBackingPropertyInfo { /// When \c initializeFromOriginal is non-NULL, the opaque value that /// is used as a stand-in for a value of the original property's type. - OpaqueValueExpr *underlyingValue = nullptr; + PropertyWrapperValuePlaceholderExpr *wrappedValuePlaceholder = nullptr; PropertyWrapperBackingPropertyInfo() { } PropertyWrapperBackingPropertyInfo(VarDecl *backingVar, - VarDecl *storageWrapperVar, - Expr *originalInitialValue, - Expr *initializeFromOriginal, - OpaqueValueExpr *underlyingValue) + VarDecl *storageWrapperVar, + Expr *initializeFromOriginal, + PropertyWrapperValuePlaceholderExpr *placeholder) : backingVar(backingVar), storageWrapperVar(storageWrapperVar), - originalInitialValue(originalInitialValue), initializeFromOriginal(initializeFromOriginal), - underlyingValue(underlyingValue) { } + wrappedValuePlaceholder(placeholder) { } /// Whether this is a valid property wrapper. bool isValid() const { diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index e377aa4789b..5efe02d03bb 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -6067,21 +6067,14 @@ bool VarDecl::isPropertyMemberwiseInitializedWithWrappedType() const { return allAttachedPropertyWrappersHaveWrappedValueInit(); } -bool VarDecl::isInnermostPropertyWrapperInitUsesEscapingAutoClosure() const { - auto customAttrs = getAttachedPropertyWrappers(); - if (customAttrs.empty()) - return false; - - unsigned innermostWrapperIndex = customAttrs.size() - 1; - auto typeInfo = getAttachedPropertyWrapperTypeInfo(innermostWrapperIndex); - return typeInfo.isWrappedValueInitUsingEscapingAutoClosure; -} - Type VarDecl::getPropertyWrapperInitValueInterfaceType() const { - Type valueInterfaceTy = getValueInterfaceType(); + auto wrapperInfo = getPropertyWrapperBackingPropertyInfo(); + if (!wrapperInfo || !wrapperInfo.wrappedValuePlaceholder) + return Type(); - if (isInnermostPropertyWrapperInitUsesEscapingAutoClosure()) - return FunctionType::get({}, valueInterfaceTy); + Type valueInterfaceTy = wrapperInfo.wrappedValuePlaceholder->getType(); + if (valueInterfaceTy->hasArchetype()) + valueInterfaceTy = valueInterfaceTy->mapTypeOutOfContext(); return valueInterfaceTy; } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 4ed744025e9..ebf0ccfcb0a 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1463,13 +1463,13 @@ static ValueDecl *getCalledValue(Expr *E) { PropertyWrapperValuePlaceholderExpr * PropertyWrapperValuePlaceholderExpr::create(ASTContext &ctx, SourceRange range, - Type ty, Expr *wrappedValue) { + Type ty, Expr *wrappedValue, + bool isAutoClosure) { auto *placeholder = new (ctx) OpaqueValueExpr(range, ty, /*isPlaceholder=*/true); - return new (ctx) PropertyWrapperValuePlaceholderExpr(range, ty, - placeholder, - wrappedValue); + return new (ctx) PropertyWrapperValuePlaceholderExpr( + range, ty, placeholder, wrappedValue, isAutoClosure); } const ParamDecl *DefaultArgumentExpr::getParamDecl() const { diff --git a/lib/SILGen/SILGen.cpp b/lib/SILGen/SILGen.cpp index bc93cdf2387..d3fb272957f 100644 --- a/lib/SILGen/SILGen.cpp +++ b/lib/SILGen/SILGen.cpp @@ -772,8 +772,8 @@ static void emitDelayedFunction(SILGenModule &SGM, ->isPropertyMemberwiseInitializedWithWrappedType()) { auto wrapperInfo = originalProperty->getPropertyWrapperBackingPropertyInfo(); - assert(wrapperInfo.originalInitialValue); - init = wrapperInfo.originalInitialValue; + assert(wrapperInfo.wrappedValuePlaceholder->getOriginalWrappedValue()); + init = wrapperInfo.wrappedValuePlaceholder->getOriginalWrappedValue(); } } diff --git a/lib/SILGen/SILGenConstructor.cpp b/lib/SILGen/SILGenConstructor.cpp index e81be5a9cef..3bc55834a34 100644 --- a/lib/SILGen/SILGenConstructor.cpp +++ b/lib/SILGen/SILGenConstructor.cpp @@ -230,8 +230,9 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, // the property wrapper backing initializer. if (auto *wrappedVar = field->getOriginalWrappedProperty()) { auto wrappedInfo = wrappedVar->getPropertyWrapperBackingPropertyInfo(); - if (wrappedInfo.originalInitialValue) { - auto arg = SGF.emitRValue(wrappedInfo.originalInitialValue); + auto *placeholder = wrappedInfo.wrappedValuePlaceholder; + if (placeholder && placeholder->getOriginalWrappedValue()) { + auto arg = SGF.emitRValue(placeholder->getOriginalWrappedValue()); maybeEmitPropertyWrapperInitFromValue(SGF, Loc, field, subs, std::move(arg)) .forwardInto(SGF, Loc, init.get()); @@ -274,8 +275,9 @@ static void emitImplicitValueConstructor(SILGenFunction &SGF, // memberwise initialized, use the original wrapped value if it exists. if (auto *wrappedVar = field->getOriginalWrappedProperty()) { auto wrappedInfo = wrappedVar->getPropertyWrapperBackingPropertyInfo(); - if (wrappedInfo.originalInitialValue) { - init = wrappedInfo.originalInitialValue; + auto *placeholder = wrappedInfo.wrappedValuePlaceholder; + if (placeholder && placeholder->getOriginalWrappedValue()) { + init = placeholder->getOriginalWrappedValue(); } } diff --git a/lib/SILGen/SILGenFunction.cpp b/lib/SILGen/SILGenFunction.cpp index bacfbd3c9df..ac174d49b38 100644 --- a/lib/SILGen/SILGenFunction.cpp +++ b/lib/SILGen/SILGenFunction.cpp @@ -852,7 +852,8 @@ void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value, auto var = cast(function.getDecl()); auto wrappedInfo = var->getPropertyWrapperBackingPropertyInfo(); auto param = params->get(0); - opaqueValue.emplace(*this, wrappedInfo.underlyingValue, + auto *placeholder = wrappedInfo.wrappedValuePlaceholder; + opaqueValue.emplace(*this, placeholder->getOpaqueValuePlaceholder(), maybeEmitValueOfLocalVarDecl(param)); assert(value == wrappedInfo.initializeFromOriginal); diff --git a/lib/SILGen/SILGenLValue.cpp b/lib/SILGen/SILGenLValue.cpp index da8d723b8d4..522f89f02f4 100644 --- a/lib/SILGen/SILGenLValue.cpp +++ b/lib/SILGen/SILGenLValue.cpp @@ -1335,10 +1335,7 @@ namespace { // the argument types of the setter and initializer shall be // different, so we don't rewrite an assignment into an // initialization. - if (VD->isInnermostPropertyWrapperInitUsesEscapingAutoClosure()) - return false; - - return true; + return !wrapperInfo.wrappedValuePlaceholder->isAutoClosure(); } return false; diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 36ee5f7a6c5..89a12466d62 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -5489,8 +5489,10 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, AnyFunctionType *funcType, target->shouldInjectWrappedValuePlaceholder(apply); auto injectWrappedValuePlaceholder = [&](Expr *arg) -> Expr * { - auto *placeholder = PropertyWrapperValuePlaceholderExpr::create(ctx, - arg->getSourceRange(), cs.getType(arg), arg); + auto *placeholder = PropertyWrapperValuePlaceholderExpr::create( + ctx, arg->getSourceRange(), cs.getType(arg), + target->propertyWrapperHasInitialWrappedValue() ? arg : nullptr, + isa(arg)); cs.cacheType(placeholder); cs.cacheType(placeholder->getOpaqueValuePlaceholder()); shouldInjectWrappedValuePlaceholder = false; @@ -5690,19 +5692,15 @@ Expr *ExprRewriter::coerceCallArguments(Expr *arg, AnyFunctionType *funcType, locator.withPathElement(ConstraintLocator::AutoclosureResult)); if (shouldInjectWrappedValuePlaceholder) { - // If init(wrappedValue:) takes an escaping autoclosure, then we want + // If init(wrappedValue:) takes an autoclosure, then we want // the effect of autoclosure forwarding of the placeholder // autoclosure. The only way to do this is to call the placeholder // autoclosure when passing it to the init. - if (!closureType->isNoEscape()) { - auto *placeholder = injectWrappedValuePlaceholder( - cs.buildAutoClosureExpr(arg, closureType)); - arg = CallExpr::createImplicit(ctx, placeholder, {}, {}); - arg->setType(closureType->getResult()); - cs.cacheType(arg); - } else { - arg = injectWrappedValuePlaceholder(arg); - } + auto *placeholder = injectWrappedValuePlaceholder( + cs.buildAutoClosureExpr(arg, closureType)); + arg = CallExpr::createImplicit(ctx, placeholder, {}, {}); + arg->setType(closureType->getResult()); + cs.cacheType(arg); } convertedArg = cs.buildAutoClosureExpr(arg, closureType); diff --git a/lib/Sema/CodeSynthesis.cpp b/lib/Sema/CodeSynthesis.cpp index 225de9b9751..1ea72f9a7db 100644 --- a/lib/Sema/CodeSynthesis.cpp +++ b/lib/Sema/CodeSynthesis.cpp @@ -253,8 +253,9 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl, // type. if (var->isPropertyMemberwiseInitializedWithWrappedType()) { varInterfaceType = var->getPropertyWrapperInitValueInterfaceType(); - isAutoClosure = - var->isInnermostPropertyWrapperInitUsesEscapingAutoClosure(); + + auto wrapperInfo = var->getPropertyWrapperBackingPropertyInfo(); + isAutoClosure = wrapperInfo.wrappedValuePlaceholder->isAutoClosure(); } else { varInterfaceType = backingPropertyType; } diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 1141966e1df..8cd6cec414e 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -4539,8 +4539,9 @@ SolutionApplicationTarget::SolutionApplicationTarget( expression.contextualPurpose = contextualPurpose; expression.convertType = convertType; expression.pattern = nullptr; - expression.wrappedVar = nullptr; - expression.innermostWrappedValueInit = nullptr; + expression.propertyWrapper.wrappedVar = nullptr; + expression.propertyWrapper.innermostWrappedValueInit = nullptr; + expression.propertyWrapper.hasInitialWrappedValue = false; expression.isDiscarded = isDiscarded; expression.bindPatternVarsOneWay = false; expression.initialization.patternBinding = nullptr; @@ -4564,11 +4565,14 @@ void SolutionApplicationTarget::maybeApplyPropertyWrapper() { auto outermostWrapperAttr = wrapperAttrs.front(); Expr *backingInitializer; if (Expr *initializer = expression.expression) { + if (!isa(initializer)) { + expression.propertyWrapper.hasInitialWrappedValue = true; + } // Form init(wrappedValue:) call(s). Expr *wrappedInitializer = buildPropertyWrapperWrappedValueCall( singleVar, Type(), initializer, /*ignoreAttributeArgs=*/false, [&](ApplyExpr *innermostInit) { - expression.innermostWrappedValueInit = innermostInit; + expression.propertyWrapper.innermostWrappedValueInit = innermostInit; }); if (!wrappedInitializer) return; @@ -4609,7 +4613,7 @@ void SolutionApplicationTarget::maybeApplyPropertyWrapper() { // Note that we have applied to property wrapper, so we can adjust // the initializer type later. - expression.wrappedVar = singleVar; + expression.propertyWrapper.wrappedVar = singleVar; expression.expression = backingInitializer; expression.convertType = {outermostWrapperAttr->getTypeRepr(), outermostWrapperAttr->getType()}; diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 1001b42d10f..acc05e5e629 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -1382,13 +1382,19 @@ private: /// pattern. Pattern *pattern; - /// The variable to which property wrappers have been applied, if - /// this is an initialization involving a property wrapper. - VarDecl *wrappedVar; + struct { + /// The variable to which property wrappers have been applied, if + /// this is an initialization involving a property wrapper. + VarDecl *wrappedVar; - /// The innermost call to \c init(wrappedValue:), if this is an - /// initialization involving a property wrapper. - ApplyExpr *innermostWrappedValueInit; + /// The innermost call to \c init(wrappedValue:), if this is an + /// initialization involving a property wrapper. + ApplyExpr *innermostWrappedValueInit; + + /// Whether this property wrapper has an initial wrapped value specified + /// via \c = . + bool hasInitialWrappedValue; + } propertyWrapper; /// Whether the expression result will be discarded at the end. bool isDiscarded; @@ -1618,11 +1624,18 @@ public: expression.contextualPurpose != CTP_Initialization) return false; - auto *wrappedVar = expression.wrappedVar; + auto *wrappedVar = expression.propertyWrapper.wrappedVar; if (!wrappedVar || wrappedVar->isStatic()) return false; - return expression.innermostWrappedValueInit == apply; + return expression.propertyWrapper.innermostWrappedValueInit == apply; + } + + /// Whether this target is for initialization of a property wrapper + /// with an initial wrapped value specified via \c = . + bool propertyWrapperHasInitialWrappedValue() const { + return (kind == Kind::expression && + expression.propertyWrapper.hasInitialWrappedValue); } /// Retrieve the wrapped variable when initializing a pattern with a @@ -1630,7 +1643,7 @@ public: VarDecl *getInitializationWrappedVar() const { assert(kind == Kind::expression); assert(expression.contextualPurpose == CTP_Initialization); - return expression.wrappedVar; + return expression.propertyWrapper.wrappedVar; } PatternBindingDecl *getInitializationPatternBindingDecl() const { diff --git a/lib/Sema/TypeCheckPropertyWrapper.cpp b/lib/Sema/TypeCheckPropertyWrapper.cpp index a47909b6004..0ff4e76afc5 100644 --- a/lib/Sema/TypeCheckPropertyWrapper.cpp +++ b/lib/Sema/TypeCheckPropertyWrapper.cpp @@ -292,42 +292,6 @@ static SubscriptDecl *findEnclosingSelfSubscript(ASTContext &ctx, return subscript; } -/// Whether the argument with label 'argumentLabel' in the initializer 'init' -/// is an escaping autoclosure argument. -static bool isEscapingAutoclosureArgument(const ConstructorDecl *init, - Identifier argumentLabel) { - if (!init) - return false; - - Optional parameterIndex = None; - auto params = init->getParameters(); - for (size_t i = 0; i < params->size(); ++i) { - if (params->get(i)->getArgumentName() == argumentLabel) { - parameterIndex = i; - break; - } - } - - if (!parameterIndex.hasValue()) - return false; - - size_t paramIndex = parameterIndex.getValue(); - if (!params->get(paramIndex)->isAutoClosure()) - return false; - - if (auto initTy = init->getInterfaceType()->getAs()) { - if (auto funcTy = initTy->getResult()->getAs()) { - if (funcTy->getNumParams() > paramIndex) { - Type paramTy = funcTy->getParams()[paramIndex].getPlainType(); - if (auto paramFuncTy = paramTy->getAs()) - return !paramFuncTy->isNoEscape(); - } - } - } - - return false; -} - PropertyWrapperTypeInfo PropertyWrapperTypeInfoRequest::evaluate( Evaluator &eval, NominalTypeDecl *nominal) const { @@ -356,14 +320,10 @@ PropertyWrapperTypeInfoRequest::evaluate( if (auto init = findSuitableWrapperInit(ctx, nominal, valueVar, PropertyWrapperInitKind::WrappedValue, decls)) { result.wrappedValueInit = PropertyWrapperTypeInfo::HasWrappedValueInit; - result.isWrappedValueInitUsingEscapingAutoClosure = - isEscapingAutoclosureArgument(init, ctx.Id_wrappedValue); } else if (auto init = findSuitableWrapperInit( ctx, nominal, valueVar, PropertyWrapperInitKind::InitialValue, decls)) { result.wrappedValueInit = PropertyWrapperTypeInfo::HasInitialValueInit; - result.isWrappedValueInitUsingEscapingAutoClosure = - isEscapingAutoclosureArgument(init, ctx.Id_initialValue); if (init->getLoc().isValid()) { auto diag = init->diagnose(diag::property_wrapper_init_initialValue); @@ -634,18 +594,6 @@ Type swift::computeWrappedValueType(VarDecl *var, Type backingStorageType, return wrappedValueType; } -static bool isOpaquePlaceholderClosure(const Expr *value) { - auto *placeholder = dyn_cast(value); - if (!placeholder) - return false; - - if (auto valueFnTy = placeholder->getType()->getAs()) { - return (valueFnTy->getNumParams() == 0); - } - - return false; -} - Expr *swift::buildPropertyWrapperWrappedValueCall( VarDecl *var, Type backingStorageType, Expr *value, bool ignoreAttributeArgs, llvm::function_ref innermostInitCallback) { @@ -654,13 +602,7 @@ Expr *swift::buildPropertyWrapperWrappedValueCall( auto wrapperAttrs = var->getAttachedPropertyWrappers(); Expr *initializer = value; ApplyExpr *innermostInit = nullptr; - if (var->isInnermostPropertyWrapperInitUsesEscapingAutoClosure() && - isOpaquePlaceholderClosure(value)) { - // We can't pass the opaque closure directly as an autoclosure arg. - // So we instead pass a CallExpr calling the opaque closure, which - // the type checker shall wrap in an AutoClosureExpr. - initializer = CallExpr::createImplicit(ctx, value, {}, {}); - } + for (unsigned i : llvm::reverse(indices(wrapperAttrs))) { Type wrapperType = backingStorageType ? computeWrappedValueType(var, backingStorageType, i) diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 47817266887..362fa635650 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -2478,7 +2478,14 @@ static void typeCheckSynthesizedWrapperInitializer( } // Type-check the initialization. - TypeChecker::typeCheckExpression(initializer, originalDC); + { + auto *wrappedVar = backingVar->getOriginalWrappedProperty(); + auto i = parentPBD->getPatternEntryIndexForVarDecl(wrappedVar); + auto *pattern = parentPBD->getPattern(i); + TypeChecker::typeCheckBinding(pattern, initializer, originalDC, + wrappedVar->getType(), parentPBD, i); + } + const auto i = pbd->getPatternEntryIndexForVarDecl(backingVar); if (auto initializerContext = dyn_cast_or_null(pbd->getInitContext(i))) { @@ -2729,8 +2736,7 @@ PropertyWrapperBackingPropertyInfoRequest::evaluate(Evaluator &evaluator, if (!parentPBD->isInitialized(patternNumber) && wrapperInfo.defaultInit) { // FIXME: Record this expression somewhere so that DI can perform the // initialization itself. - auto typeExpr = TypeExpr::createImplicit(storageType, ctx); - Expr *initializer = CallExpr::createImplicit(ctx, typeExpr, {}, { }); + Expr *initializer = nullptr; typeCheckSynthesizedWrapperInitializer(pbd, backingVar, parentPBD, initializer); pbd->setInit(0, initializer); @@ -2759,27 +2765,21 @@ PropertyWrapperBackingPropertyInfoRequest::evaluate(Evaluator &evaluator, if (!wrappedValue && (!var->allAttachedPropertyWrappersHaveWrappedValueInit() || initializer)) { return PropertyWrapperBackingPropertyInfo( - backingVar, storageVar, nullptr, nullptr, nullptr); + backingVar, storageVar, nullptr, nullptr); } // Form the initialization of the backing property from a value of the // original property's type. if (!initializer) { - Type origValueInterfaceType = var->getPropertyWrapperInitValueInterfaceType(); - Type origValueType = - var->getDeclContext()->mapTypeIntoContext(origValueInterfaceType); - wrappedValue = PropertyWrapperValuePlaceholderExpr::create( - ctx, var->getSourceRange(), origValueType, /*wrappedValue=*/nullptr); - initializer = buildPropertyWrapperWrappedValueCall( - var, storageType, wrappedValue, /*ignoreAttributeArgs=*/true); + initializer = PropertyWrapperValuePlaceholderExpr::create( + ctx, var->getSourceRange(), var->getType(), /*wrappedValue=*/nullptr); typeCheckSynthesizedWrapperInitializer( pbd, backingVar, parentPBD, initializer); + wrappedValue = findWrappedValuePlaceholder(initializer); } return PropertyWrapperBackingPropertyInfo(backingVar, storageVar, - wrappedValue->getOriginalWrappedValue(), - initializer, - wrappedValue->getOpaqueValuePlaceholder()); + initializer, wrappedValue); } /// Given a storage declaration in a protocol, set it up with the right diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 85ae497d11c..e540a2390d9 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -2908,7 +2908,7 @@ public: } PropertyWrapperBackingPropertyInfo info( - backingVar, storageWrapperVar, nullptr, nullptr, nullptr); + backingVar, storageWrapperVar, nullptr, nullptr); ctx.evaluator.cacheOutput( PropertyWrapperBackingPropertyInfoRequest{var}, std::move(info)); ctx.evaluator.cacheOutput( diff --git a/test/SILGen/property_wrapper_autoclosure.swift b/test/SILGen/property_wrapper_autoclosure.swift new file mode 100644 index 00000000000..b86098a692f --- /dev/null +++ b/test/SILGen/property_wrapper_autoclosure.swift @@ -0,0 +1,27 @@ +// RUN: %empty-directory(%t) +// RUN: %target-build-swift %s -o %t/a.out +// RUN: %target-run %t/a.out | %FileCheck %s + +// REQUIRES: executable_test + +@propertyWrapper +public class Autoclosure { + public var wrappedValue: Value + + public init(wrappedValue: @autoclosure () -> Value) { + print("Property Wrapper init") + self.wrappedValue = wrappedValue() + } +} + +struct S { + init() { print("S.init") } +} + +struct ValueHolder { + @Autoclosure var value: S +} + +// CHECK: Property Wrapper init +// CHECK-NEXT: S.init +_ = ValueHolder(value: S()) diff --git a/test/SILGen/property_wrappers.swift b/test/SILGen/property_wrappers.swift index 0b2a0fefd12..8d9beb85d37 100644 --- a/test/SILGen/property_wrappers.swift +++ b/test/SILGen/property_wrappers.swift @@ -313,7 +313,7 @@ struct UseWrapperWithNonEscapingAutoclosure { // Memberwise init should take an Int arg, not a closure // CHECK: // UseWrapperWithNonEscapingAutoclosure.init(foo:) - // CHECK: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV3fooACSi_tcfC : $@convention(method) (Int, @thin UseWrapperWithNonEscapingAutoclosure.Type) -> UseWrapperWithNonEscapingAutoclosure + // CHECK: sil hidden [ossa] @$s17property_wrappers36UseWrapperWithNonEscapingAutoclosureV3fooACSiyXK_tcfC : $@convention(method) (@noescape @callee_guaranteed () -> Int, @thin UseWrapperWithNonEscapingAutoclosure.Type) -> UseWrapperWithNonEscapingAutoclosure } struct UseStatic { @@ -425,6 +425,21 @@ struct CompositionWithAutoclosure { // CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers26CompositionWithAutoclosureV2p12p22p3ACSiyXA_S2itcfC : $@convention(method) (@owned @callee_guaranteed () -> Int, Int, Int, @thin CompositionWithAutoclosure.Type) -> CompositionWithAutoclosure } +@propertyWrapper +struct WrapperWithAutoclosureAndExtraArgs { + var wrappedValue: V + init(wrappedValue: @autoclosure @escaping () -> V, key: String) { + self.wrappedValue = wrappedValue() + } +} + +struct UseAutoclosureWrapperWithExtraArgs { + @WrapperWithAutoclosureAndExtraArgs(key: "") + var value = 10 + + // CHECK-LABEL: sil hidden [ossa] @$s17property_wrappers34UseAutoclosureWrapperWithExtraArgsV5valueSivpfP : $@convention(thin) (@owned @callee_guaranteed () -> Int) -> WrapperWithAutoclosureAndExtraArgs +} + // Observers with non-default mutatingness. @propertyWrapper struct NonMutatingSet {