@@ -1314,6 +1314,17 @@ namespace {
1314
1314
IsOnSelfParameter &&
1315
1315
isa<ConstructorDecl>(SGF.FunctionDC ->getAsDecl ());
1316
1316
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
+
1317
1328
// If we have a nonmutating setter on a value type, the call
1318
1329
// captures all of 'self' and we cannot rewrite an assignment
1319
1330
// into an initialization.
@@ -1403,7 +1414,7 @@ namespace {
1403
1414
assert (getAccessorDecl ()->isSetter ());
1404
1415
SILDeclRef setter = Accessor;
1405
1416
1406
- if (IsOnSelfParameter && canRewriteSetAsPropertyWrapperInit (SGF) &&
1417
+ if (canRewriteSetAsPropertyWrapperInit (SGF) &&
1407
1418
!Storage->isStatic () &&
1408
1419
isBackingVarVisible (cast<VarDecl>(Storage),
1409
1420
SGF.FunctionDC )) {
@@ -1434,7 +1445,9 @@ namespace {
1434
1445
1435
1446
// Get the address of the storage property.
1436
1447
ManagedValue proj;
1437
- if (BaseFormalType->mayHaveSuperclass ()) {
1448
+ if (!BaseFormalType) {
1449
+ proj = SGF.maybeEmitValueOfLocalVarDecl (backingVar);
1450
+ } else if (BaseFormalType->mayHaveSuperclass ()) {
1438
1451
RefElementComponent REC (backingVar, LValueOptions (), varStorageType,
1439
1452
typeData);
1440
1453
proj = std::move (REC).project (SGF, loc, base);
@@ -1471,33 +1484,51 @@ namespace {
1471
1484
.SILFnType )
1472
1485
.getValue ();
1473
1486
1474
- } else
1487
+ } else {
1475
1488
setterFRef = SGF.emitGlobalFunctionRef (loc, setter, setterInfo);
1489
+ }
1490
+
1476
1491
CanSILFunctionType setterTy = setterFRef->getType ().castTo <SILFunctionType>();
1477
1492
SILFunctionConventions setterConv (setterTy, SGF.SGM .M );
1478
1493
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);
1486
1500
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);
1496
1527
}
1497
1528
1498
1529
PartialApplyInst *setterPAI =
1499
1530
SGF.B .createPartialApply (loc, setterFRef,
1500
- Substitutions, { capturedBase } ,
1531
+ Substitutions, capturedArgs ,
1501
1532
ParameterConvention::Direct_Guaranteed);
1502
1533
ManagedValue setterFn = SGF.emitManagedRValueWithCleanup (setterPAI);
1503
1534
0 commit comments