@@ -3929,10 +3929,23 @@ class SILTypeSubstituter :
39293929 CanGenericSignature Sig;
39303930
39313931 struct PackExpansion {
3932- CanType ExpandedShape;
3932+ // / The shape class of pack parameters that are expanded by this
3933+ // / expansion. Set during construction and not changed.
3934+ CanType OrigShapeClass;
3935+
3936+ // / The count type of the pack expansion in the current lane of
3937+ // / expansion, if any. Pack elements in this lane should be
3938+ // / expansions with this shape.
3939+ CanType SubstPackExpansionCount;
3940+
3941+ // / The index of the current lane of expansion. Basic
3942+ // / substitution of pack parameters with the same shape as
3943+ // / OrigShapeClass should yield a pack, and lanewise
3944+ // / substitution should produce this element of that pack.
39333945 unsigned Index;
39343946
3935- PackExpansion (CanType shape) : ExpandedShape(shape), Index(0 ) {}
3947+ PackExpansion (CanType origShapeClass)
3948+ : OrigShapeClass(origShapeClass), Index(0 ) {}
39363949 };
39373950 SmallVector<PackExpansion> ActivePackExpansions;
39383951
@@ -4253,7 +4266,7 @@ class SILTypeSubstituter :
42534266
42544267 CanType visitPackExpansionType (CanPackExpansionType origType) {
42554268 CanType patternType = visit (origType.getPatternType ());
4256- CanType countType = visit (origType.getCountType ());
4269+ CanType countType = substASTType (origType.getCountType ());
42574270
42584271 return CanType (PackExpansionType::get (patternType, countType));
42594272 }
@@ -4264,21 +4277,24 @@ class SILTypeSubstituter :
42644277 CanType origPatternType = origType.getPatternType ();
42654278
42664279 // Substitute the count type (as an AST type).
4267- CanType substCountType = visitType (origCountType);
4280+ CanType substCountType = substASTType (origCountType);
42684281
42694282 // If that produces a pack type, expand the pattern element-wise.
42704283 if (auto substCountPackType = dyn_cast<PackType>(substCountType)) {
42714284 // Set up for element-wise expansion.
42724285 ActivePackExpansions.emplace_back (origCountType);
42734286
42744287 for (CanType substCountEltType : substCountPackType.getElementTypes ()) {
4288+ auto expansionType = dyn_cast<PackExpansionType>(substCountEltType);
4289+ ActivePackExpansions.back ().SubstPackExpansionCount =
4290+ (expansionType ? expansionType.getCountType () : CanType ());
4291+
42754292 // Expand the pattern type in the element-wise context.
42764293 CanType expandedType = visit (origPatternType);
42774294
42784295 // Turn that into a pack expansion if appropriate for the
42794296 // count element.
4280- if (auto expansionType =
4281- dyn_cast<PackExpansionType>(substCountEltType)) {
4297+ if (expansionType) {
42824298 expandedType =
42834299 CanPackExpansionType::get (expandedType,
42844300 expansionType.getCountType ());
@@ -4317,11 +4333,44 @@ class SILTypeSubstituter :
43174333 SmallVector<TupleTypeElt, 8 > substElts;
43184334 substElts.reserve (origType->getNumElements ());
43194335 for (auto &origElt : origType->getElements ()) {
4320- auto substEltType = visit (CanType (origElt.getType ()));
4321- substElts.push_back (origElt.getWithType (substEltType));
4336+ CanType origEltType = CanType (origElt.getType ());
4337+ if (auto origExpansion = dyn_cast<PackExpansionType>(origEltType)) {
4338+ bool first = true ;
4339+ substPackExpansion (origExpansion, [&](CanType substEltType) {
4340+ auto substElt = origElt.getWithType (substEltType);
4341+ if (first) {
4342+ first = false ;
4343+ } else {
4344+ substElt = substElt.getWithoutName ();
4345+ }
4346+ substElts.push_back (substElt);
4347+ });
4348+ } else {
4349+ auto substEltType = visit (origEltType);
4350+ substElts.push_back (origElt.getWithType (substEltType));
4351+ }
43224352 }
4353+
4354+ // Turn unlabeled singleton scalar tuples into their underlying types.
4355+ // The AST type substituter doesn't actually implement this rule yet,
4356+ // but we need to implement it in SIL in order to support testing,
4357+ // since the type parser can't parse a singleton tuple.
4358+ //
4359+ // For compatibility with previous behavior, don't do this if the
4360+ // original tuple type was singleton. AutoDiff apparently really
4361+ // likes making singleton tuples.
4362+ if (isParenType (substElts) && !isParenType (origType->getElements ()))
4363+ return CanType (substElts[0 ].getType ());
4364+
43234365 return CanType (TupleType::get (substElts, TC.Context ));
43244366 }
4367+
4368+ static bool isParenType (ArrayRef<TupleTypeElt> elts) {
4369+ return (elts.size () == 1 &&
4370+ !elts[0 ].hasName () &&
4371+ !isa<PackExpansionType>(CanType (elts[0 ].getType ())));
4372+ }
4373+
43254374 // Block storage types need to substitute their capture type by these same
43264375 // rules.
43274376 CanType visitSILBlockStorageType (CanSILBlockStorageType origType) {
@@ -4375,11 +4424,21 @@ class SILTypeSubstituter :
43754424 [&](SubstitutableType *origType) -> Type {
43764425 auto substType = Subst (origType);
43774426 if (!substType) return substType;
4378- auto substPackType = substType-> getAs <PackType>();
4427+ auto substPackType = dyn_cast <PackType>(substType-> getCanonicalType () );
43794428 if (!substPackType) return substType;
4380- auto index = getPackExpansionIndex (CanType (origType));
4381- if (!index) return substType;
4382- return substPackType->getElementType (*index);
4429+ auto activeExpansion = getActivePackExpansion (CanType (origType));
4430+ if (!activeExpansion) return substType;
4431+ auto substEltType =
4432+ substPackType.getElementType (activeExpansion->Index );
4433+ auto substExpansion = dyn_cast<PackExpansionType>(substEltType);
4434+ assert ((bool ) substExpansion ==
4435+ (bool ) activeExpansion->SubstPackExpansionCount );
4436+ if (substExpansion) {
4437+ assert (hasSameShape (substExpansion.getCountType (),
4438+ activeExpansion->SubstPackExpansionCount ));
4439+ return substExpansion.getPatternType ();
4440+ }
4441+ return substEltType;
43834442 },
43844443 [&](CanType dependentType,
43854444 Type conformingReplacementType,
@@ -4388,23 +4447,27 @@ class SILTypeSubstituter :
43884447 conformingReplacementType,
43894448 conformingProtocol);
43904449 if (!conformance || !conformance.isPack ()) return conformance;
4391- auto index = getPackExpansionIndex (dependentType);
4392- if (!index ) return conformance;
4450+ auto activeExpansion = getActivePackExpansion (dependentType);
4451+ if (!activeExpansion ) return conformance;
43934452 auto pack = conformance.getPack ();
4394- return pack->getPatternConformances ()[*index];
4453+ auto substEltConf =
4454+ pack->getPatternConformances ()[activeExpansion->Index ];
4455+ // There isn't currently a ProtocolConformanceExpansion that
4456+ // we would need to look through here.
4457+ return substEltConf;
43954458 },
43964459 substOptions)->getCanonicalType ();
43974460 }
43984461
4399- Optional< size_t > getPackExpansionIndex (CanType dependentType) {
4462+ PackExpansion * getActivePackExpansion (CanType dependentType) {
44004463 // We push new expansions onto the end of this vector, and we
44014464 // want to honor the innermost expansion, so we have to traverse
44024465 // in it reverse.
44034466 for (auto &entry : reverse (ActivePackExpansions)) {
4404- if (hasSameShape (dependentType, entry.ExpandedShape ))
4405- return entry. Index ;
4467+ if (hasSameShape (dependentType, entry.OrigShapeClass ))
4468+ return & entry;
44064469 }
4407- return None ;
4470+ return nullptr ;
44084471 }
44094472
44104473 bool hasSameShape (CanType lhs, CanType rhs) {
0 commit comments