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