@@ -1503,87 +1503,109 @@ void SILGenFunction::emitMemberInitializationViaInitAccessor(
15031503 B.createEndAccess (loc, selfRef.getValue (), /* aborted=*/ false );
15041504}
15051505
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+
15061576void SILGenFunction::emitMemberInitializers (DeclContext *dc,
15071577 VarDecl *selfDecl,
15081578 NominalTypeDecl *nominal) {
15091579 auto subs = getSubstitutionsForPropertyInitializer (dc, nominal);
15101580
1581+ llvm::SmallPtrSet<PatternBindingDecl *, 4 > alreadyInitialized;
15111582 for (auto member : nominal->getImplementationContext ()->getAllMembers ()) {
15121583 // Find instance pattern binding declarations that have initializers.
15131584 if (auto pbd = dyn_cast<PatternBindingDecl>(member)) {
15141585 if (pbd->isStatic ()) continue ;
15151586
1587+ if (alreadyInitialized.count (pbd))
1588+ continue ;
1589+
15161590 // Emit default initialization for an init accessor property.
15171591 if (auto *var = pbd->getSingleVar ()) {
15181592 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+
15191603 emitMemberInitializationViaInitAccessor (dc, selfDecl, pbd, subs);
15201604 continue ;
15211605 }
15221606 }
15231607
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);
15871609 }
15881610 }
15891611}
0 commit comments