@@ -283,7 +283,7 @@ LayoutConstraint AbstractionPattern::getLayoutConstraint() const {
283
283
}
284
284
}
285
285
286
- bool AbstractionPattern::matchesTuple (CanTupleType substType) const {
286
+ bool AbstractionPattern::matchesTuple (CanType substType) const {
287
287
switch (getKind ()) {
288
288
case Kind::Invalid:
289
289
llvm_unreachable (" querying invalid abstraction pattern!" );
@@ -311,11 +311,19 @@ bool AbstractionPattern::matchesTuple(CanTupleType substType) const {
311
311
return false ;
312
312
LLVM_FALLTHROUGH;
313
313
case Kind::Tuple: {
314
+ if (getVanishingTupleElementPatternType ()) {
315
+ // TODO: recurse into elements.
316
+ return true ;
317
+ }
318
+
319
+ auto substTupleType = dyn_cast<TupleType>(substType);
320
+ if (!substTupleType) return false ;
321
+
314
322
size_t nextSubstIndex = 0 ;
315
323
auto nextComponentIsAcceptable = [&](bool isPackExpansion) -> bool {
316
- if (nextSubstIndex == substType ->getNumElements ())
324
+ if (nextSubstIndex == substTupleType ->getNumElements ())
317
325
return false ;
318
- auto substComponentType = substType .getElementType (nextSubstIndex++);
326
+ auto substComponentType = substTupleType .getElementType (nextSubstIndex++);
319
327
return (isPackExpansion == isa<PackExpansionType>(substComponentType));
320
328
};
321
329
for (auto elt : getTupleElementTypes ()) {
@@ -333,7 +341,7 @@ bool AbstractionPattern::matchesTuple(CanTupleType substType) const {
333
341
return false ;
334
342
}
335
343
}
336
- return nextSubstIndex == substType ->getNumElements ();
344
+ return nextSubstIndex == substTupleType ->getNumElements ();
337
345
}
338
346
}
339
347
llvm_unreachable (" bad kind" );
@@ -469,7 +477,63 @@ bool AbstractionPattern::doesTupleContainPackExpansionType() const {
469
477
llvm_unreachable (" bad kind" );
470
478
}
471
479
472
- void AbstractionPattern::forEachTupleElement (CanTupleType substType,
480
+ Optional<AbstractionPattern>
481
+ AbstractionPattern::getVanishingTupleElementPatternType () const {
482
+ if (!isTuple ()) return None;
483
+ if (!GenericSubs) return None;
484
+
485
+ // Substitution causes tuples to vanish when substituting the elements
486
+ // produces a singleton tuple and it didn't start that way.
487
+
488
+ auto numOrigElts = getNumTupleElements ();
489
+
490
+ // Track whether we've found a single element.
491
+ Optional<AbstractionPattern> singletonEltType;
492
+ bool hadOrigExpansion = false ;
493
+ for (auto index : range (numOrigElts)) {
494
+ auto eltType = getTupleElementType (index);
495
+
496
+ // If this pattern isn't a pack expansion, we've got a new candidate
497
+ // singleton. If this is the second such candidate, of course, it's
498
+ // not a singleton.
499
+ if (!eltType.isPackExpansion ()) {
500
+ if (singletonEltType) return None;
501
+ singletonEltType = eltType;
502
+
503
+ // Otherwise, check what the expansion shape expands to.
504
+ } else {
505
+ hadOrigExpansion = true ;
506
+
507
+ auto expansionType = cast<PackExpansionType>(eltType.getType ());
508
+ auto substShape = cast<PackType>(
509
+ expansionType.getCountType ().subst (GenericSubs)->getCanonicalType ());
510
+ auto expansionCount = substShape->getNumElements ();
511
+
512
+ // If it expands to multiple elements or to a single expansion, we
513
+ // won't have a singleton tuple. If it expands to a single scalar
514
+ // element, this is a singleton candidate.
515
+ if (expansionCount > 1 ) {
516
+ return None;
517
+ } else if (expansionCount == 1 ) {
518
+ auto substExpansion =
519
+ dyn_cast<PackExpansionType>(substShape.getElementType (0 ));
520
+ if (substExpansion)
521
+ return None;
522
+ if (singletonEltType)
523
+ return None;
524
+ singletonEltType = eltType.getPackExpansionPatternType ();
525
+ }
526
+ }
527
+ }
528
+
529
+ // If we found a singleton scalar element, and we didn't start with
530
+ // a singleton element, that's the index we want to return.
531
+ if (singletonEltType && !(numOrigElts == 1 && !hadOrigExpansion))
532
+ return singletonEltType;
533
+ return None;
534
+ }
535
+
536
+ void AbstractionPattern::forEachTupleElement (CanType substType,
473
537
llvm::function_ref<void (TupleElementGenerator &)> handleElement) const {
474
538
TupleElementGenerator elt (*this , substType);
475
539
for (; !elt.isFinished (); elt.advance ()) {
@@ -480,35 +544,46 @@ void AbstractionPattern::forEachTupleElement(CanTupleType substType,
480
544
481
545
TupleElementGenerator::TupleElementGenerator (
482
546
AbstractionPattern origTupleType,
483
- CanTupleType substTupleType )
484
- : origTupleType(origTupleType), substTupleType(substTupleType ) {
547
+ CanType substType )
548
+ : origTupleType(origTupleType), substType(substType ) {
485
549
assert (origTupleType.isTuple ());
486
- assert (origTupleType.matchesTuple (substTupleType ));
550
+ assert (origTupleType.matchesTuple (substType ));
487
551
552
+ origTupleVanishes =
553
+ origTupleType.getVanishingTupleElementPatternType ().hasValue ();
488
554
origTupleTypeIsOpaque = origTupleType.isOpaqueTuple ();
489
555
numOrigElts = origTupleType.getNumTupleElements ();
490
556
491
557
if (!isFinished ()) loadElement ();
492
558
}
493
559
494
- void AbstractionPattern::forEachExpandedTupleElement (CanTupleType substType,
560
+ void AbstractionPattern::forEachExpandedTupleElement (CanType substType,
495
561
llvm::function_ref<void (AbstractionPattern origEltType,
496
562
CanType substEltType,
497
563
const TupleTypeElt &elt)>
498
564
handleElement) const {
499
565
assert (matchesTuple (substType));
500
566
501
- auto substEltTypes = substType.getElementTypes ();
502
-
503
567
// Handle opaque patterns by just iterating the substituted components.
504
568
if (!isTuple ()) {
569
+ auto substTupleType = cast<TupleType>(substType);
570
+ auto substEltTypes = substTupleType.getElementTypes ();
505
571
for (auto i : indices (substEltTypes)) {
506
572
handleElement (getTupleElementType (i), substEltTypes[i],
507
- substType ->getElement (i));
573
+ substTupleType ->getElement (i));
508
574
}
509
575
return ;
510
576
}
511
577
578
+ // For vanishing tuples, just call the callback once.
579
+ if (auto origEltType = getVanishingTupleElementPatternType ()) {
580
+ handleElement (*origEltType, substType, TupleTypeElt (substType));
581
+ return ;
582
+ }
583
+
584
+ auto substTupleType = cast<TupleType>(substType);
585
+ auto substEltTypes = substTupleType.getElementTypes ();
586
+
512
587
// For non-opaque patterns, we have to iterate the original components
513
588
// in order to match things up properly, but we'll still end up calling
514
589
// once per substituted element.
@@ -517,7 +592,7 @@ void AbstractionPattern::forEachExpandedTupleElement(CanTupleType substType,
517
592
auto origEltType = getTupleElementType (origEltIndex);
518
593
if (!origEltType.isPackExpansion ()) {
519
594
handleElement (origEltType, substEltTypes[substEltIndex],
520
- substType ->getElement (substEltIndex));
595
+ substTupleType ->getElement (substEltIndex));
521
596
substEltIndex++;
522
597
} else {
523
598
auto origPatternType = origEltType.getPackExpansionPatternType ();
@@ -532,7 +607,8 @@ void AbstractionPattern::forEachExpandedTupleElement(CanTupleType substType,
532
607
// be misleading in one way or another.
533
608
handleElement (isa<PackExpansionType>(substEltType)
534
609
? origEltType : origPatternType,
535
- substEltType, substType->getElement (substEltIndex));
610
+ substEltType,
611
+ substTupleType->getElement (substEltIndex));
536
612
substEltIndex++;
537
613
}
538
614
}
0 commit comments