Skip to content

Commit dc8b970

Browse files
committed
[SE-0143] Eliminate assertions blocking the use of conditional conformances.
Early on in the development of conditional conformances, we put in a bunch of assertions for code that uses `conformsToProtocol()` but wasn't handling conditional conformances. Now, `conformsToProtocol()` handles conditional conformances by default, and these assertions are tripping up code that would work. Remove the assertions and add test cases that used to trip up the assertions (but now work).
1 parent 04a9714 commit dc8b970

File tree

6 files changed

+60
-21
lines changed

6 files changed

+60
-21
lines changed

lib/Sema/CSApply.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,6 @@ static DeclTy *findNamedWitnessImpl(
161161
if (!conformance)
162162
return nullptr;
163163
}
164-
assert(conformance->getConditionalRequirements().empty() &&
165-
"unhandled conditional conformance");
166164

167165
// For a type with dependent conformance, just return the requirement from
168166
// the protocol. There are no protocol conformance tables.
@@ -6608,8 +6606,6 @@ Expr *ExprRewriter::convertLiteral(Expr *literal,
66086606
auto conformance = tc.conformsToProtocol(type, protocol, cs.DC,
66096607
ConformanceCheckFlags::InExpression);
66106608
assert(conformance && "must conform to literal protocol");
6611-
assert(conformance->getConditionalRequirements().empty() &&
6612-
"unexpected conditional requirements");
66136609

66146610
// Figure out the (non-builtin) argument type if there is one.
66156611
Type argType;
@@ -6752,8 +6748,6 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal,
67526748
auto conformance = tc.conformsToProtocol(type, protocol, cs.DC,
67536749
ConformanceCheckFlags::InExpression);
67546750
assert(conformance && "must conform to literal protocol");
6755-
assert(conformance->getConditionalRequirements().empty() &&
6756-
"unexpected conditional requirements");
67576751

67586752
// Dig out the literal type and perform a builtin literal conversion to it.
67596753
if (!literalType.empty()) {

lib/Sema/TypeCheckDecl.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3002,13 +3002,7 @@ static void checkEnumRawValues(TypeChecker &TC, EnumDecl *ED) {
30023002
// primitive literal protocols.
30033003
auto conformsToProtocol = [&](KnownProtocolKind protoKind) {
30043004
ProtocolDecl *proto = TC.getProtocol(ED->getLoc(), protoKind);
3005-
auto conformance =
3006-
TC.conformsToProtocol(rawTy, proto, ED->getDeclContext(), None);
3007-
if (conformance)
3008-
assert(conformance->getConditionalRequirements().empty() &&
3009-
"conditionally conforming to literal protocol not currently "
3010-
"supported");
3011-
return conformance;
3005+
return TC.conformsToProtocol(rawTy, proto, ED->getDeclContext(), None);
30123006
};
30133007

30143008
static auto otherLiteralProtocolKinds = {

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6209,9 +6209,6 @@ void TypeChecker::useBridgedNSErrorConformances(DeclContext *dc, Type type) {
62096209
(ConformanceCheckFlags::SuppressDependencyTracking|
62106210
ConformanceCheckFlags::Used));
62116211
if (conformance && conformance->isConcrete()) {
6212-
assert(conformance->getConditionalRequirements().empty() &&
6213-
"cannot conform condtionally to _ErrorCodeProtocol");
6214-
62156212
if (Type errorType = ProtocolConformanceRef::getTypeWitnessByName(
62166213
type, *conformance, Context.Id_ErrorType, this)) {
62176214
(void)conformsToProtocol(errorType, bridgedStoredNSError, dc,

lib/Sema/TypeCheckStmt.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -670,9 +670,6 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
670670
sequence->getLoc());
671671
if (!genConformance)
672672
return nullptr;
673-
assert(
674-
genConformance->getConditionalRequirements().empty() &&
675-
"conditionally conforming to IteratorProtocol not currently supported");
676673

677674
Type elementTy = TC.getWitnessType(generatorTy, generatorProto,
678675
*genConformance, TC.Context.Id_Element,

test/Constraints/array_literal.swift

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances
22

33
struct IntList : ExpressibleByArrayLiteral {
44
typealias Element = Int
@@ -322,3 +322,21 @@ let routerFruit = Company(
322322
// accident.
323323
let SR3786a: [Int] = [1, 2, 3]
324324
let SR3786aa = [SR3786a.reversed(), SR3786a]
325+
326+
// Conditional conformance
327+
protocol P { }
328+
329+
struct PArray<T> { }
330+
331+
extension PArray : ExpressibleByArrayLiteral where T: P {
332+
typealias ArrayLiteralElement = T
333+
334+
init(arrayLiteral elements: T...) { }
335+
}
336+
337+
extension Int: P { }
338+
339+
func testConditional(i: Int, s: String) {
340+
let _: PArray<Int> = [i, i, i]
341+
let _: PArray<String> = [s, s, s] // expected-error{{contextual type 'PArray<String>' cannot be used with array literal}}
342+
}

test/stmt/foreach.swift

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-conditional-conformances
22

33
// Bad containers and ranges
44
struct BadContainer1 {
@@ -178,3 +178,42 @@ func testExistentialSequence(s: Sequence) { // expected-error {{protocol 'Sequen
178178
_ = x
179179
}
180180
}
181+
182+
// Conditional conformance to Sequence and IteratorProtocol.
183+
protocol P { }
184+
185+
struct RepeatedSequence<T> {
186+
var value: T
187+
var count: Int
188+
}
189+
190+
struct RepeatedIterator<T> {
191+
var value: T
192+
var count: Int
193+
}
194+
195+
extension RepeatedIterator: IteratorProtocol where T: P {
196+
typealias Element = T
197+
198+
mutating func next() -> T? {
199+
if count == 0 { return nil }
200+
count = count - 1
201+
return value
202+
}
203+
}
204+
205+
extension RepeatedSequence: Sequence where T: P {
206+
typealias Element = T
207+
typealias Iterator = RepeatedIterator<T>
208+
typealias SubSequence = AnySequence<T>
209+
210+
func makeIterator() -> RepeatedIterator<T> {
211+
return Iterator(value: value, count: count)
212+
}
213+
}
214+
215+
extension Int : P { }
216+
217+
func testRepeated(ri: RepeatedSequence<Int>) {
218+
for x in ri { _ = x }
219+
}

0 commit comments

Comments
 (0)