@@ -1588,6 +1588,15 @@ namespace {
1588
1588
return Mval;
1589
1589
};
1590
1590
1591
+ auto getTupleFieldIndex =
1592
+ [&](VarDecl *var, Identifier fieldName) -> Optional<unsigned > {
1593
+ auto *tupleType = var->getInterfaceType ()->castTo <TupleType>();
1594
+ int fieldIdx = tupleType->getNamedElementId (fieldName);
1595
+ if (fieldIdx < 0 )
1596
+ return None;
1597
+ return fieldIdx;
1598
+ };
1599
+
1591
1600
if (canRewriteSetAsTypeWrapperInit (SGF)) {
1592
1601
auto *ctor = cast<ConstructorDecl>(SGF.FunctionDC ->getAsDecl ());
1593
1602
auto *field = cast<VarDecl>(Storage);
@@ -1599,20 +1608,19 @@ namespace {
1599
1608
auto *localVar = ctor->getLocalTypeWrapperStorageVar ();
1600
1609
1601
1610
// First, we need to find index of the current field in `_storage.
1602
- auto *tempType = localVar->getInterfaceType ()->castTo <TupleType>();
1603
- int fieldIdx = tempType->getNamedElementId (field->getName ());
1604
- assert (fieldIdx >= 0 );
1611
+ auto fieldIdx = getTupleFieldIndex (localVar, field->getName ());
1612
+ assert (fieldIdx.hasValue ());
1605
1613
1606
1614
// Load `_storage.<name>`
1607
- auto storageBase =
1615
+ auto localVarRef =
1608
1616
SGF.maybeEmitValueOfLocalVarDecl (localVar, AccessKind::Write);
1609
1617
1610
1618
auto typeData = getLogicalStorageTypeData (
1611
1619
SGF.getTypeExpansionContext (), SGF.SGM , getTypeData ().AccessKind ,
1612
1620
FieldType->getCanonicalType ());
1613
1621
1614
- TupleElementComponent TEC (fieldIdx, typeData);
1615
- auto storage = std::move (TEC).project (SGF, loc, storageBase );
1622
+ TupleElementComponent TEC (* fieldIdx, typeData);
1623
+ auto storage = std::move (TEC).project (SGF, loc, localVarRef );
1616
1624
1617
1625
// Partially apply the setter so it could be used by assign_by_wrapper
1618
1626
@@ -1653,29 +1661,51 @@ namespace {
1653
1661
ValType = ValType.subst (Substitutions);
1654
1662
}
1655
1663
1656
- // TODO: revist minimal
1657
- SILType varStorageType = SGF.SGM .Types .getSubstitutedStorageType (
1658
- TypeExpansionContext::minimal (), backingVar,
1664
+ auto typeData = getLogicalStorageTypeData (
1665
+ SGF.getTypeExpansionContext (), SGF.SGM , getTypeData ().AccessKind ,
1659
1666
ValType->getCanonicalType ());
1660
- auto typeData =
1661
- getLogicalStorageTypeData (SGF.getTypeExpansionContext (), SGF.SGM ,
1662
- getTypeData ().AccessKind ,
1663
- ValType->getCanonicalType ());
1664
1667
1665
- // Get the address of the storage property.
1668
+ // Stores the address of the storage property.
1666
1669
ManagedValue proj;
1667
- if (!BaseFormalType) {
1668
- proj = SGF.maybeEmitValueOfLocalVarDecl (
1669
- backingVar, AccessKind::Write);
1670
- } else if (BaseFormalType->mayHaveSuperclass ()) {
1671
- RefElementComponent REC (backingVar, LValueOptions (), varStorageType,
1672
- typeData, /* actorIsolation=*/ None);
1673
- proj = std::move (REC).project (SGF, loc, base);
1670
+
1671
+ // If this is a type wrapper managed property, we emit everything
1672
+ // through local `_storage` variable because wrapper property
1673
+ // in this case is backed by `$storage` which has to get initialized
1674
+ // first.
1675
+ if (backingVar->isAccessedViaTypeWrapper ()) {
1676
+ auto *ctor = cast<ConstructorDecl>(SGF.FunctionDC ->getAsDecl ());
1677
+ auto *localVar = ctor->getLocalTypeWrapperStorageVar ();
1678
+
1679
+ // First, we need to find index of the backing storage field in
1680
+ // `_storage`.
1681
+ auto fieldIdx = getTupleFieldIndex (localVar, backingVar->getName ());
1682
+ assert (fieldIdx.hasValue ());
1683
+
1684
+ // Load `_storage.<name>`
1685
+ auto localVarRef =
1686
+ SGF.maybeEmitValueOfLocalVarDecl (localVar, AccessKind::Write);
1687
+
1688
+ TupleElementComponent TEC (*fieldIdx, typeData);
1689
+ proj = std::move (TEC).project (SGF, loc, localVarRef);
1674
1690
} else {
1675
- assert (BaseFormalType->getStructOrBoundGenericStruct ());
1676
- StructElementComponent SEC (backingVar, varStorageType,
1677
- typeData, /* actorIsolation=*/ None);
1678
- proj = std::move (SEC).project (SGF, loc, base);
1691
+ // TODO: revist minimal
1692
+ SILType varStorageType = SGF.SGM .Types .getSubstitutedStorageType (
1693
+ TypeExpansionContext::minimal (), backingVar,
1694
+ ValType->getCanonicalType ());
1695
+
1696
+ if (!BaseFormalType) {
1697
+ proj =
1698
+ SGF.maybeEmitValueOfLocalVarDecl (backingVar, AccessKind::Write);
1699
+ } else if (BaseFormalType->mayHaveSuperclass ()) {
1700
+ RefElementComponent REC (backingVar, LValueOptions (), varStorageType,
1701
+ typeData, /* actorIsolation=*/ None);
1702
+ proj = std::move (REC).project (SGF, loc, base);
1703
+ } else {
1704
+ assert (BaseFormalType->getStructOrBoundGenericStruct ());
1705
+ StructElementComponent SEC (backingVar, varStorageType, typeData,
1706
+ /* actorIsolation=*/ None);
1707
+ proj = std::move (SEC).project (SGF, loc, base);
1708
+ }
1679
1709
}
1680
1710
1681
1711
// The property wrapper backing initializer forms an instance of
0 commit comments