Skip to content

Commit 5e2f7c9

Browse files
committed
Sema: Harden 'for ... in ...' with existential type
Avoid calling lookupMemberType() with an existential base altogether. With the previous resolveTypeInContext() patch, a compiler_crasher regressed and hit this, because the behavior of lookupMemberType() changed to return nullptr in fewer cases.
1 parent e8abf54 commit 5e2f7c9

File tree

2 files changed

+43
-27
lines changed

2 files changed

+43
-27
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,11 +1846,11 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
18461846
cs.addConstraint(ConstraintKind::ConformsTo, SequenceType,
18471847
sequenceProto->getDeclaredType(), Locator);
18481848

1849-
auto generatorLocator =
1849+
auto iteratorLocator =
18501850
cs.getConstraintLocator(Locator,
18511851
ConstraintLocator::SequenceIteratorProtocol);
18521852
auto elementLocator =
1853-
cs.getConstraintLocator(generatorLocator,
1853+
cs.getConstraintLocator(iteratorLocator,
18541854
ConstraintLocator::GeneratorElementType);
18551855

18561856
// Collect constraints from the element pattern.
@@ -1859,48 +1859,58 @@ bool TypeChecker::typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt) {
18591859
if (!InitType)
18601860
return true;
18611861

1862-
// Manually search for the generator witness. If no generator/element pair
1862+
// Manually search for the iterator witness. If no iterator/element pair
18631863
// exists, solve for them.
1864-
// FIXME: rename generatorType to iteratorType due to the protocol
1865-
// renaming
1866-
Type generatorType;
1864+
Type iteratorType;
18671865
Type elementType;
18681866

18691867
NameLookupOptions lookupOptions = defaultMemberTypeLookupOptions;
18701868
if (isa<AbstractFunctionDecl>(cs.DC))
18711869
lookupOptions |= NameLookupFlags::KnownPrivate;
1872-
auto member = cs.TC.lookupMemberType(cs.DC,
1873-
expr->getType()->getRValueType(),
1874-
tc.Context.Id_Iterator,
1875-
lookupOptions);
1870+
1871+
auto sequenceType = expr->getType()->getRValueType();
1872+
1873+
// If the sequence type is an existential, we should not attempt to
1874+
// look up the member type at all, since we cannot represent associated
1875+
// types of existentials.
1876+
//
1877+
// We will diagnose it later.
1878+
if (!sequenceType->isExistentialType()) {
1879+
auto member = cs.TC.lookupMemberType(cs.DC,
1880+
sequenceType,
1881+
tc.Context.Id_Iterator,
1882+
lookupOptions);
18761883

1877-
if (member) {
1878-
generatorType = member.front().second;
1879-
1880-
member = cs.TC.lookupMemberType(cs.DC,
1881-
generatorType,
1882-
tc.Context.Id_Element,
1883-
lookupOptions);
1884-
1885-
if (member)
1886-
elementType = member.front().second;
1884+
if (member) {
1885+
iteratorType = member.front().second;
1886+
1887+
member = cs.TC.lookupMemberType(cs.DC,
1888+
iteratorType,
1889+
tc.Context.Id_Element,
1890+
lookupOptions);
1891+
1892+
if (member)
1893+
elementType = member.front().second;
1894+
}
18871895
}
1888-
1896+
1897+
// If the type lookup failed, just add some constraints we can
1898+
// try to solve later.
18891899
if (elementType.isNull()) {
18901900

1891-
// Determine the generator type of the sequence.
1892-
generatorType = cs.createTypeVariable(Locator, /*options=*/0);
1901+
// Determine the iterator type of the sequence.
1902+
iteratorType = cs.createTypeVariable(Locator, /*options=*/0);
18931903
cs.addConstraint(Constraint::create(
18941904
cs, ConstraintKind::TypeMember,
1895-
SequenceType, generatorType,
1896-
tc.Context.Id_Iterator, generatorLocator));
1905+
SequenceType, iteratorType,
1906+
tc.Context.Id_Iterator, iteratorLocator));
18971907

1898-
// Determine the element type of the generator.
1908+
// Determine the element type of the iterator.
18991909
// FIXME: Should look up the type witness.
19001910
elementType = cs.createTypeVariable(Locator, /*options=*/0);
19011911
cs.addConstraint(Constraint::create(
19021912
cs, ConstraintKind::TypeMember,
1903-
generatorType, elementType,
1913+
iteratorType, elementType,
19041914
tc.Context.Id_Element, elementLocator));
19051915
}
19061916

test/stmt/foreach.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,3 +172,9 @@ func testOptionalSequence() {
172172
}
173173
}
174174

175+
// Crash with (invalid) for each over an existential
176+
func testExistentialSequence(s: Sequence) { // expected-error {{protocol 'Sequence' can only be used as a generic constraint because it has Self or associated type requirements}}
177+
for x in s { // expected-error {{using 'Sequence' as a concrete type conforming to protocol 'Sequence' is not supported}}
178+
_ = x
179+
}
180+
}

0 commit comments

Comments
 (0)