Skip to content

Commit 1231953

Browse files
authored
Merge pull request #66173 from xedin/rdar-109539394-5.9
[5.9][ConstraintSystem] Some more variadic generic fixes
2 parents 72718c0 + 7a1129c commit 1231953

File tree

8 files changed

+74
-8
lines changed

8 files changed

+74
-8
lines changed

include/swift/AST/PackConformance.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ class alignas(1 << DeclAlignInBits) PackConformance final
6868

6969
ArrayRef<ProtocolConformanceRef> getPatternConformances() const;
7070

71+
bool isInvalid() const;
72+
7173
bool isCanonical() const;
7274

7375
PackConformance *getCanonicalConformance() const;
@@ -103,4 +105,4 @@ void simple_display(llvm::raw_ostream &out, PackConformance *conformance);
103105

104106
} // end namespace swift
105107

106-
#endif // SWIFT_AST_PACKCONFORMANCE_H
108+
#endif // SWIFT_AST_PACKCONFORMANCE_H

include/swift/AST/PackExpansionMatcher.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,29 @@ class TypeListPackMatcher {
186186
}
187187
}
188188

189+
// If both sides have the same number of elements and all of
190+
// them are pack expansions there is not going to be any
191+
// expansion "absorption" and it's okay to match per-index.
192+
//
193+
// Like in all previous cases the callers are responsible
194+
// to check whether the element types actually line up,
195+
// this is a purely structural match.
196+
if (lhsElts.size() == rhsElts.size()) {
197+
for (unsigned i = 0, n = lhsElts.size(); i != n; ++i) {
198+
auto lhsType = getElementType(lhsElts[i]);
199+
auto rhsType = getElementType(rhsElts[i]);
200+
201+
if (IsPackExpansionType(lhsType) && IsPackExpansionType(rhsType)) {
202+
pairs.emplace_back(lhsType, rhsType, i, i);
203+
} else {
204+
pairs.clear();
205+
return true;
206+
}
207+
}
208+
209+
return false;
210+
}
211+
189212
// Otherwise, all remaining possibilities are invalid:
190213
// - Neither side has any pack expansions, and they have different lengths.
191214
// - One side has a pack expansion but the other side is too short, eg

lib/AST/Module.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,8 +1827,11 @@ static ProtocolConformanceRef getPackTypeConformance(
18271827
patternConformances.push_back(patternConformance);
18281828
}
18291829

1830-
return ProtocolConformanceRef(
1831-
PackConformance::get(type, protocol, patternConformances));
1830+
auto *conformance = PackConformance::get(type, protocol, patternConformances);
1831+
if (conformance->isInvalid())
1832+
return ProtocolConformanceRef::forInvalid();
1833+
1834+
return ProtocolConformanceRef(conformance);
18321835
}
18331836

18341837
ProtocolConformanceRef

lib/AST/PackConformance.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ size_t PackConformance::numTrailingObjects(
5555
return ConformingType->getNumElements();
5656
}
5757

58+
bool PackConformance::isInvalid() const {
59+
return llvm::any_of(getPatternConformances(),
60+
[&](const auto ref) { return ref.isInvalid(); });
61+
}
62+
5863
ArrayRef<ProtocolConformanceRef>
5964
PackConformance::getPatternConformances() const {
6065
return {getTrailingObjects<ProtocolConformanceRef>(),
@@ -244,6 +249,9 @@ PackConformance::subst(InFlightSubstitution &IFS) const {
244249

245250
auto substConformance = PackConformance::get(substConformingType, Protocol,
246251
expander.substConformances);
252+
if (substConformance->isInvalid())
253+
return ProtocolConformanceRef::forInvalid();
254+
247255
return ProtocolConformanceRef(substConformance);
248256
}
249257

lib/AST/Type.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4547,8 +4547,13 @@ operator()(CanType dependentType, Type conformingReplacementType,
45474547
(*this)(dependentType, conformingPackElt, conformedProtocol);
45484548
conformances.push_back(conformance);
45494549
}
4550-
return ProtocolConformanceRef(
4551-
PackConformance::get(conformingPack, conformedProtocol, conformances));
4550+
4551+
auto *conformance =
4552+
PackConformance::get(conformingPack, conformedProtocol, conformances);
4553+
if (conformance->isInvalid())
4554+
return ProtocolConformanceRef::forInvalid();
4555+
4556+
return ProtocolConformanceRef(conformance);
45524557
}
45534558

45544559
assert((conformingReplacementType->is<ErrorType>() ||

lib/Sema/CSSimplify.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8393,6 +8393,13 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
83938393
if (path.back().is<LocatorPathElt::PackElement>())
83948394
path.pop_back();
83958395

8396+
// This is similar to `PackElement` but locator points to the requirement
8397+
// associted with pack expansion pattern (i.e. `repeat each T: P`) where
8398+
// the path is something like:
8399+
// `... -> type req # -> pack expansion pattern`.
8400+
if (path.back().is<LocatorPathElt::PackExpansionPattern>())
8401+
path.pop_back();
8402+
83968403
if (auto req = path.back().getAs<LocatorPathElt::AnyRequirement>()) {
83978404
// If this is a requirement associated with `Self` which is bound
83988405
// to `Any`, let's consider this "too incorrect" to continue.

lib/Sema/ConstraintSystem.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6290,11 +6290,18 @@ Solution::getFunctionArgApplyInfo(ConstraintLocator *locator) const {
62906290
*choice, [this](Type type) -> Type { return simplifyType(type); }))
62916291
fnInterfaceType = fnInterfaceType->castTo<AnyFunctionType>()->getResult();
62926292

6293+
#ifndef NDEBUG
6294+
// If variadic generics are not involved, interface type should
6295+
// always match applied type.
62936296
if (auto *fn = fnInterfaceType->getAs<AnyFunctionType>()) {
6294-
assert(fn->getNumParams() == fnType->getNumParams() &&
6295-
"Parameter mismatch?");
6296-
(void)fn;
6297+
if (llvm::none_of(fn->getParams(), [&](const auto &param) {
6298+
return param.getPlainType()->hasParameterPack();
6299+
})) {
6300+
assert(fn->getNumParams() == fnType->getNumParams() &&
6301+
"Parameter mismatch?");
6302+
}
62976303
}
6304+
#endif
62986305
} else {
62996306
fnInterfaceType = resolveInterfaceType(rawFnType);
63006307
}

test/Constraints/pack-expansion-expressions.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,3 +529,14 @@ func test_pack_expansion_to_void_conv_for_closure_result<each T>(x: repeat each
529529
let _: (Int) -> Void = { repeat ($0, print(each x)) } // expected-warning {{'repeat (Int, ())' is unused}}
530530
let _: (Int, String) -> Void = { ($0, repeat ($1, print(each x))) } // expected-warning {{'(Int, repeat (String, ()))' is unused}}
531531
}
532+
533+
// rdar://109539394 - crash on passing multiple variadic lists to singly variadic callee
534+
do {
535+
func test1<each T>(_: repeat each T) {}
536+
func test2<each T>(_: repeat each T) where repeat each T: RawRepresentable {} // expected-note {{where 'each T' = 'each T2'}}
537+
538+
func caller<each T1, each T2>(t1: repeat each T1, t2: repeat each T2) {
539+
test1(repeat each t1, repeat each t2) // Ok
540+
test2(repeat each t2, repeat each t1) // expected-error {{local function 'test2' requires that 'each T2' conform to 'RawRepresentable'}}
541+
}
542+
}

0 commit comments

Comments
 (0)