@@ -1314,6 +1314,17 @@ namespace {
13141314 IsOnSelfParameter &&
13151315 isa<ConstructorDecl>(SGF.FunctionDC ->getAsDecl ());
13161316
1317+ // Assignment to a wrapped property can only be re-written to initialization for
1318+ // members of `self` in an initializer, and for local variables.
1319+ if (!(isAssignmentToSelfParamInInit || VD->getDeclContext ()->isLocalContext ()))
1320+ return false ;
1321+
1322+ // If this var isn't in a type context, assignment will always use the setter
1323+ // if there is an initial value.
1324+ if (!VD->getDeclContext ()->isTypeContext () &&
1325+ wrapperInfo.wrappedValuePlaceholder ->getOriginalWrappedValue ())
1326+ return false ;
1327+
13171328 // If we have a nonmutating setter on a value type, the call
13181329 // captures all of 'self' and we cannot rewrite an assignment
13191330 // into an initialization.
@@ -1403,7 +1414,7 @@ namespace {
14031414 assert (getAccessorDecl ()->isSetter ());
14041415 SILDeclRef setter = Accessor;
14051416
1406- if (IsOnSelfParameter && canRewriteSetAsPropertyWrapperInit (SGF) &&
1417+ if (canRewriteSetAsPropertyWrapperInit (SGF) &&
14071418 !Storage->isStatic () &&
14081419 isBackingVarVisible (cast<VarDecl>(Storage),
14091420 SGF.FunctionDC )) {
@@ -1434,7 +1445,9 @@ namespace {
14341445
14351446 // Get the address of the storage property.
14361447 ManagedValue proj;
1437- if (BaseFormalType->mayHaveSuperclass ()) {
1448+ if (!BaseFormalType) {
1449+ proj = SGF.maybeEmitValueOfLocalVarDecl (backingVar);
1450+ } else if (BaseFormalType->mayHaveSuperclass ()) {
14381451 RefElementComponent REC (backingVar, LValueOptions (), varStorageType,
14391452 typeData);
14401453 proj = std::move (REC).project (SGF, loc, base);
@@ -1471,33 +1484,51 @@ namespace {
14711484 .SILFnType )
14721485 .getValue ();
14731486
1474- } else
1487+ } else {
14751488 setterFRef = SGF.emitGlobalFunctionRef (loc, setter, setterInfo);
1489+ }
1490+
14761491 CanSILFunctionType setterTy = setterFRef->getType ().castTo <SILFunctionType>();
14771492 SILFunctionConventions setterConv (setterTy, SGF.SGM .M );
14781493
1479- SILValue capturedBase;
1480- unsigned argIdx = setterConv.getNumSILArguments () - 1 ;
1481- if (setterConv.getSILArgumentConvention (argIdx).isInoutConvention ()) {
1482- capturedBase = base.getValue ();
1483- } else {
1484- capturedBase = base.copy (SGF, loc).forward (SGF);
1485- }
1494+ // Emit captures for the setter
1495+ SmallVector<SILValue, 4 > capturedArgs;
1496+ auto captureInfo = SGF.SGM .Types .getLoweredLocalCaptures (setter);
1497+ if (!captureInfo.getCaptures ().empty ()) {
1498+ SmallVector<ManagedValue, 4 > captures;
1499+ SGF.emitCaptures (loc, setter, CaptureEmission::AssignByWrapper, captures);
14861500
1487- // If the base is a reference and the setter expects a value, emit a
1488- // load. This pattern is emitted for property wrappers with a
1489- // nonmutating setter, for example.
1490- if (base.getType ().isAddress () &&
1491- base.getType ().getObjectType () ==
1492- setterConv.getSILArgumentType (argIdx,
1493- SGF.getTypeExpansionContext ())) {
1494- capturedBase = SGF.B .createTrivialLoadOr (
1495- loc, capturedBase, LoadOwnershipQualifier::Take);
1501+ for (auto capture : captures)
1502+ capturedArgs.push_back (capture.forward (SGF));
1503+ } else {
1504+ assert (base);
1505+
1506+ SILValue capturedBase;
1507+ unsigned argIdx = setterConv.getNumSILArguments () - 1 ;
1508+
1509+ if (setterConv.getSILArgumentConvention (argIdx).isInoutConvention ()) {
1510+ capturedBase = base.getValue ();
1511+ } else {
1512+ capturedBase = base.copy (SGF, loc).forward (SGF);
1513+ }
1514+
1515+ // If the base is a reference and the setter expects a value, emit a
1516+ // load. This pattern is emitted for property wrappers with a
1517+ // nonmutating setter, for example.
1518+ if (base.getType ().isAddress () &&
1519+ base.getType ().getObjectType () ==
1520+ setterConv.getSILArgumentType (argIdx,
1521+ SGF.getTypeExpansionContext ())) {
1522+ capturedBase = SGF.B .createTrivialLoadOr (
1523+ loc, capturedBase, LoadOwnershipQualifier::Take);
1524+ }
1525+
1526+ capturedArgs.push_back (capturedBase);
14961527 }
14971528
14981529 PartialApplyInst *setterPAI =
14991530 SGF.B .createPartialApply (loc, setterFRef,
1500- Substitutions, { capturedBase } ,
1531+ Substitutions, capturedArgs ,
15011532 ParameterConvention::Direct_Guaranteed);
15021533 ManagedValue setterFn = SGF.emitManagedRValueWithCleanup (setterPAI);
15031534
0 commit comments