Skip to content

Commit e2e4865

Browse files
committed
Sema: Check requirements when calling a variadic generic function
1 parent 24030c1 commit e2e4865

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2603,10 +2603,9 @@ static ConstraintFix *fixRequirementFailure(ConstraintSystem &cs, Type type1,
26032603
Type type2,
26042604
ConstraintLocatorBuilder locator) {
26052605
SmallVector<LocatorPathElt, 4> path;
2606-
if (auto anchor = locator.getLocatorParts(path)) {
2607-
return fixRequirementFailure(cs, type1, type2, anchor, path);
2608-
}
2609-
return nullptr;
2606+
2607+
auto anchor = locator.getLocatorParts(path);
2608+
return fixRequirementFailure(cs, type1, type2, anchor, path);
26102609
}
26112610

26122611
static unsigned
@@ -4140,6 +4139,11 @@ static ConstraintFix *fixRequirementFailure(ConstraintSystem &cs, Type type1,
41404139
if (type1->isTypeVariableOrMember() || type2->isTypeVariableOrMember())
41414140
return nullptr;
41424141

4142+
// If we have something like ... -> type req # -> pack element #, we're
4143+
// solving a requirement of the form T : P where T is a type parameter pack
4144+
if (path.back().is<LocatorPathElt::PackElement>())
4145+
path = path.drop_back();
4146+
41434147
auto req = path.back().castTo<LocatorPathElt::AnyRequirement>();
41444148
if (req.isConditionalRequirement()) {
41454149
// path is - ... -> open generic -> type req # -> cond req #,
@@ -7630,6 +7634,11 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
76307634
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
76317635
}
76327636

7637+
// If we have something like ... -> type req # -> pack element #, we're
7638+
// solving a requirement of the form T : P where T is a type parameter pack
7639+
if (path.back().is<LocatorPathElt::PackElement>())
7640+
path.pop_back();
7641+
76337642
if (auto req = path.back().getAs<LocatorPathElt::AnyRequirement>()) {
76347643
// If this is a requirement associated with `Self` which is bound
76357644
// to `Any`, let's consider this "too incorrect" to continue.
@@ -13869,7 +13878,16 @@ void ConstraintSystem::addConstraint(Requirement req,
1386913878
case RequirementKind::Conformance:
1387013879
kind = ConstraintKind::ConformsTo;
1387113880
break;
13872-
case RequirementKind::Superclass:
13881+
case RequirementKind::Superclass: {
13882+
// FIXME: Should always use ConstraintKind::SubclassOf, but that breaks
13883+
// a couple of diagnostics
13884+
if (auto *typeVar = req.getFirstType()->getAs<TypeVariableType>()) {
13885+
if (typeVar->getImpl().canBindToPack()) {
13886+
kind = ConstraintKind::SubclassOf;
13887+
break;
13888+
}
13889+
}
13890+
1387313891
conformsToAnyObject = true;
1387413892
kind = ConstraintKind::Subtype;
1387513893
break;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-variadic-generics
2+
3+
// Test instantiation of constraint solver constraints from generic requirements
4+
// involving type pack parameters
5+
6+
protocol P {}
7+
8+
func takesP<T...: P>(_: T...) {} // expected-note {{where 'T' = 'DoesNotConformToP'}}
9+
10+
struct ConformsToP: P {}
11+
struct DoesNotConformToP {}
12+
13+
takesP() // ok
14+
takesP(ConformsToP(), ConformsToP(), ConformsToP()) // ok
15+
16+
// FIXME: Bad diagnostic
17+
takesP(ConformsToP(), DoesNotConformToP(), ConformsToP()) // expected-error {{global function 'takesP' requires that 'DoesNotConformToP' conform to 'P'}}
18+
19+
class C {}
20+
21+
class SubclassOfC: C {}
22+
class NotSubclassOfC {}
23+
24+
func takesC<T...: C>(_: T...) {} // expected-note {{where 'T' = 'NotSubclassOfC'}}
25+
26+
takesC() // ok
27+
takesC(SubclassOfC(), SubclassOfC(), SubclassOfC()) // ok
28+
29+
takesC(SubclassOfC(), NotSubclassOfC(), SubclassOfC()) // expected-error {{global function 'takesC' requires that 'NotSubclassOfC' inherit from 'C'}}

0 commit comments

Comments
 (0)