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