Skip to content

Commit e0a1a11

Browse files
committed
SIL: Fix substituted function type visitor for PackExpansionType with concrete pattern type
If the pattern doesn't have any pack parameters in it anymore, we need to recover the substituted count type from the original count type. Fixes rdar://problem/112065340.
1 parent e89de6e commit e0a1a11

File tree

3 files changed

+72
-10
lines changed

3 files changed

+72
-10
lines changed

include/swift/SIL/AbstractionPattern.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,13 +1472,12 @@ class AbstractionPattern {
14721472

14731473
/// Given that the value being abstracted is a pack expansion type,
14741474
/// return the underlying pattern type.
1475-
///
1476-
/// If you're looking for getPackExpansionCountType(), it deliberately
1477-
/// does not exist. Count types are not lowered types, and the original
1478-
/// count types are not relevant to lowering. Only the substituted
1479-
/// components and expansion counts are significant.
14801475
AbstractionPattern getPackExpansionPatternType() const;
14811476

1477+
/// Given that the value being abstracted is a pack expansion type,
1478+
/// return the underlying count type.
1479+
AbstractionPattern getPackExpansionCountType() const;
1480+
14821481
/// Given that the value being abstracted is a pack expansion type,
14831482
/// return the appropriate pattern type for the given expansion
14841483
/// component.

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,49 @@ AbstractionPattern AbstractionPattern::getPackExpansionPatternType() const {
795795
llvm_unreachable("bad kind");
796796
}
797797

798+
static CanType getPackExpansionCountType(CanType type) {
799+
return cast<PackExpansionType>(type).getCountType();
800+
}
801+
802+
AbstractionPattern AbstractionPattern::getPackExpansionCountType() const {
803+
switch (getKind()) {
804+
case Kind::Invalid:
805+
llvm_unreachable("querying invalid abstraction pattern!");
806+
case Kind::ObjCMethodType:
807+
case Kind::CurriedObjCMethodType:
808+
case Kind::PartialCurriedObjCMethodType:
809+
case Kind::CFunctionAsMethodType:
810+
case Kind::CurriedCFunctionAsMethodType:
811+
case Kind::PartialCurriedCFunctionAsMethodType:
812+
case Kind::CXXMethodType:
813+
case Kind::CurriedCXXMethodType:
814+
case Kind::PartialCurriedCXXMethodType:
815+
case Kind::Tuple:
816+
case Kind::OpaqueFunction:
817+
case Kind::OpaqueDerivativeFunction:
818+
case Kind::ObjCCompletionHandlerArgumentsType:
819+
case Kind::ClangType:
820+
llvm_unreachable("pattern for function or tuple cannot be for "
821+
"pack expansion type");
822+
823+
case Kind::Opaque:
824+
return *this;
825+
826+
case Kind::Type:
827+
if (isTypeParameterOrOpaqueArchetype())
828+
return AbstractionPattern::getOpaque();
829+
return AbstractionPattern(getGenericSubstitutions(),
830+
getGenericSignature(),
831+
::getPackExpansionCountType(getType()));
832+
833+
case Kind::Discard:
834+
return AbstractionPattern::getDiscard(
835+
getGenericSubstitutions(), getGenericSignature(),
836+
::getPackExpansionCountType(getType()));
837+
}
838+
llvm_unreachable("bad kind");
839+
}
840+
798841
size_t AbstractionPattern::getNumPackExpandedComponents() const {
799842
assert(isPackExpansion());
800843
assert(getKind() == Kind::Type || getKind() == Kind::Discard);
@@ -2267,7 +2310,7 @@ class SubstFunctionTypePatternVisitor
22672310
// Recursively visit the pattern type.
22682311
auto patternTy = visit(substPatternType, origPatternType);
22692312

2270-
// Find a pack parameter from the pattern to expand over.
2313+
// If the pattern contains a pack parameter, use that as the count type.
22712314
CanType countParam;
22722315
patternTy->walkPackReferences([&](Type t) {
22732316
if (t->isTypeParameter()) {
@@ -2281,10 +2324,22 @@ class SubstFunctionTypePatternVisitor
22812324
return false;
22822325
});
22832326

2284-
// If that didn't work, we should be able to find an expansion
2285-
// to use from either the substituted type or the subs. At worst,
2286-
// we can make one.
2287-
assert(countParam && "implementable but lazy");
2327+
// If the pattern was fully substituted, substitute the original
2328+
// count type and use that instead.
2329+
if (!countParam) {
2330+
auto origCountType = origExpansion.getPackExpansionCountType();
2331+
CanType substCountType;
2332+
if (origExpansion.getGenericSubstitutions()) {
2333+
substCountType = cast<PackExpansionType>(origExpansion.getType())
2334+
.getCountType();
2335+
} else {
2336+
assert(candidateSubstType);
2337+
substCountType =
2338+
cast<PackExpansionType>(candidateSubstType).getCountType();
2339+
}
2340+
2341+
countParam = visit(substCountType, origCountType);
2342+
}
22882343

22892344
return CanPackExpansionType::get(patternTy, countParam);
22902345
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-swift-frontend -emit-ir %s
2+
3+
public func test<each T: BinaryInteger>(_ values: repeat each T) {
4+
var values = (repeat UInt32(truncatingIfNeeded: each values))
5+
withUnsafePointer(to: &values) { ptr in
6+
_ = ptr[0]
7+
}
8+
}

0 commit comments

Comments
 (0)