@@ -1502,87 +1502,109 @@ void SILGenFunction::emitMemberInitializationViaInitAccessor(
1502
1502
B.createEndAccess (loc, selfRef.getValue (), /* aborted=*/ false );
1503
1503
}
1504
1504
1505
+ void SILGenFunction::emitMemberInitializer (DeclContext *dc, VarDecl *selfDecl,
1506
+ PatternBindingDecl *field,
1507
+ SubstitutionMap substitutions) {
1508
+ assert (!field->isStatic ());
1509
+
1510
+ for (auto i : range (field->getNumPatternEntries ())) {
1511
+ auto init = field->getExecutableInit (i);
1512
+ if (!init)
1513
+ continue ;
1514
+
1515
+ auto *varPattern = field->getPattern (i);
1516
+
1517
+ // Cleanup after this initialization.
1518
+ FullExpr scope (Cleanups, varPattern);
1519
+
1520
+ // Get the type of the initialization result, in terms
1521
+ // of the constructor context's archetypes.
1522
+ auto resultType =
1523
+ getInitializationTypeInContext (field->getDeclContext (), dc, varPattern);
1524
+ AbstractionPattern origType = resultType.first ;
1525
+ CanType substType = resultType.second ;
1526
+
1527
+ // Figure out what we're initializing.
1528
+ auto memberInit = emitMemberInit (*this , selfDecl, varPattern);
1529
+
1530
+ // This whole conversion thing is about eliminating the
1531
+ // paired orig-to-subst subst-to-orig conversions that
1532
+ // will happen if the storage is at a different abstraction
1533
+ // level than the constructor. When emitApply() is used
1534
+ // to call the stored property initializer, it naturally
1535
+ // wants to convert the result back to the most substituted
1536
+ // abstraction level. To undo this, we use a converting
1537
+ // initialization and rely on the peephole that optimizes
1538
+ // out the redundant conversion.
1539
+ SILType loweredResultTy;
1540
+ SILType loweredSubstTy;
1541
+
1542
+ // A converting initialization isn't necessary if the member is
1543
+ // a property wrapper. Though the initial value can have a
1544
+ // reabstractable type, the result of the initialization is
1545
+ // always the property wrapper type, which is never reabstractable.
1546
+ bool needsConvertingInit = false ;
1547
+ auto *singleVar = varPattern->getSingleVar ();
1548
+ if (!(singleVar && singleVar->getOriginalWrappedProperty ())) {
1549
+ loweredResultTy = getLoweredType (origType, substType);
1550
+ loweredSubstTy = getLoweredType (substType);
1551
+ needsConvertingInit = loweredResultTy != loweredSubstTy;
1552
+ }
1553
+
1554
+ if (needsConvertingInit) {
1555
+ Conversion conversion =
1556
+ Conversion::getSubstToOrig (origType, substType, loweredResultTy);
1557
+
1558
+ ConvertingInitialization convertingInit (conversion,
1559
+ SGFContext (memberInit.get ()));
1560
+
1561
+ emitAndStoreInitialValueInto (*this , varPattern, field, i, substitutions,
1562
+ origType, substType, &convertingInit);
1563
+
1564
+ auto finalValue = convertingInit.finishEmission (
1565
+ *this , varPattern, ManagedValue::forInContext ());
1566
+ if (!finalValue.isInContext ())
1567
+ finalValue.forwardInto (*this , varPattern, memberInit.get ());
1568
+ } else {
1569
+ emitAndStoreInitialValueInto (*this , varPattern, field, i, substitutions,
1570
+ origType, substType, memberInit.get ());
1571
+ }
1572
+ }
1573
+ }
1574
+
1505
1575
void SILGenFunction::emitMemberInitializers (DeclContext *dc,
1506
1576
VarDecl *selfDecl,
1507
1577
NominalTypeDecl *nominal) {
1508
1578
auto subs = getSubstitutionsForPropertyInitializer (dc, nominal);
1509
1579
1580
+ llvm::SmallPtrSet<PatternBindingDecl *, 4 > alreadyInitialized;
1510
1581
for (auto member : nominal->getImplementationContext ()->getAllMembers ()) {
1511
1582
// Find instance pattern binding declarations that have initializers.
1512
1583
if (auto pbd = dyn_cast<PatternBindingDecl>(member)) {
1513
1584
if (pbd->isStatic ()) continue ;
1514
1585
1586
+ if (alreadyInitialized.count (pbd))
1587
+ continue ;
1588
+
1515
1589
// Emit default initialization for an init accessor property.
1516
1590
if (auto *var = pbd->getSingleVar ()) {
1517
1591
if (var->hasInitAccessor ()) {
1592
+ auto initAccessor = var->getAccessor (AccessorKind::Init);
1593
+
1594
+ // Make sure that initializations for the accessed properties
1595
+ // are emitted before the init accessor that uses them.
1596
+ for (auto *property : initAccessor->getAccessedProperties ()) {
1597
+ auto *PBD = property->getParentPatternBinding ();
1598
+ if (alreadyInitialized.insert (PBD).second )
1599
+ emitMemberInitializer (dc, selfDecl, PBD, subs);
1600
+ }
1601
+
1518
1602
emitMemberInitializationViaInitAccessor (dc, selfDecl, pbd, subs);
1519
1603
continue ;
1520
1604
}
1521
1605
}
1522
1606
1523
- for (auto i : range (pbd->getNumPatternEntries ())) {
1524
- auto init = pbd->getExecutableInit (i);
1525
- if (!init) continue ;
1526
-
1527
- auto *varPattern = pbd->getPattern (i);
1528
-
1529
- // Cleanup after this initialization.
1530
- FullExpr scope (Cleanups, varPattern);
1531
-
1532
- // Get the type of the initialization result, in terms
1533
- // of the constructor context's archetypes.
1534
- auto resultType = getInitializationTypeInContext (
1535
- pbd->getDeclContext (), dc, varPattern);
1536
- AbstractionPattern origType = resultType.first ;
1537
- CanType substType = resultType.second ;
1538
-
1539
- // Figure out what we're initializing.
1540
- auto memberInit = emitMemberInit (*this , selfDecl, varPattern);
1541
-
1542
- // This whole conversion thing is about eliminating the
1543
- // paired orig-to-subst subst-to-orig conversions that
1544
- // will happen if the storage is at a different abstraction
1545
- // level than the constructor. When emitApply() is used
1546
- // to call the stored property initializer, it naturally
1547
- // wants to convert the result back to the most substituted
1548
- // abstraction level. To undo this, we use a converting
1549
- // initialization and rely on the peephole that optimizes
1550
- // out the redundant conversion.
1551
- SILType loweredResultTy;
1552
- SILType loweredSubstTy;
1553
-
1554
- // A converting initialization isn't necessary if the member is
1555
- // a property wrapper. Though the initial value can have a
1556
- // reabstractable type, the result of the initialization is
1557
- // always the property wrapper type, which is never reabstractable.
1558
- bool needsConvertingInit = false ;
1559
- auto *singleVar = varPattern->getSingleVar ();
1560
- if (!(singleVar && singleVar->getOriginalWrappedProperty ())) {
1561
- loweredResultTy = getLoweredType (origType, substType);
1562
- loweredSubstTy = getLoweredType (substType);
1563
- needsConvertingInit = loweredResultTy != loweredSubstTy;
1564
- }
1565
-
1566
- if (needsConvertingInit) {
1567
- Conversion conversion = Conversion::getSubstToOrig (
1568
- origType, substType,
1569
- loweredResultTy);
1570
-
1571
- ConvertingInitialization convertingInit (conversion,
1572
- SGFContext (memberInit.get ()));
1573
-
1574
- emitAndStoreInitialValueInto (*this , varPattern, pbd, i, subs,
1575
- origType, substType, &convertingInit);
1576
-
1577
- auto finalValue = convertingInit.finishEmission (
1578
- *this , varPattern, ManagedValue::forInContext ());
1579
- if (!finalValue.isInContext ())
1580
- finalValue.forwardInto (*this , varPattern, memberInit.get ());
1581
- } else {
1582
- emitAndStoreInitialValueInto (*this , varPattern, pbd, i, subs,
1583
- origType, substType, memberInit.get ());
1584
- }
1585
- }
1607
+ emitMemberInitializer (dc, selfDecl, pbd, subs);
1586
1608
}
1587
1609
}
1588
1610
}
0 commit comments