Skip to content

Commit 46e623a

Browse files
committed
[SubstitutionMap] Handle conformance lookup via superclass requirements.
Conformances that discoverably for a type parameter via a superclass requirement occupy a bit of a gray area in the type checker and generic signature handling right now: we have a type parameter (so the paths that handle concrete conformances don't kick in), but the conformance itself isn't modeled as a requirement because it is available via lookup. Teach SubstitutionMap's conformance lookup to detect this case and perform conformance lookup in the generic signature (i.e., falling back to global lookup) in this case, replicating the hack that IRGen uses to address the same issue when accessing the conformance (see GenArchetype.cpp's TODO where we lookup a conformance on the superclass). The removal of that hack (as well as this one) are tracked by rdar://problem/34609744. For now, fixes SR-7072 / rdar://problem/37904576.
1 parent a62647f commit 46e623a

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

lib/AST/SubstitutionMap.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,9 +192,19 @@ SubstitutionMap::lookupConformance(CanType type, ProtocolDecl *proto) const {
192192

193193
auto genericSig = getGenericSignature();
194194

195-
// If the type doesn't conform to this protocol, fail.
196-
if (!genericSig->conformsToProtocol(type, proto))
195+
// If the type doesn't conform to this protocol, the result isn't formed
196+
// from these requirements.
197+
if (!genericSig->conformsToProtocol(type, proto)) {
198+
// Check whether the superclass conforms.
199+
if (auto superclass = genericSig->getSuperclassBound(type)) {
200+
return LookUpConformanceInSignature(*getGenericSignature())(
201+
type->getCanonicalType(),
202+
superclass,
203+
proto->getDeclaredType());
204+
}
205+
197206
return None;
207+
}
198208

199209
auto accessPath =
200210
genericSig->getConformanceAccessPath(type, proto);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %target-swift-frontend %s -emit-sil -o - | %FileCheck %s
2+
3+
public final class GenClass<Element: Cl> {
4+
public subscript(index: Int) -> Element {
5+
get { return unsafeBitCast(0, to: Element.self) }
6+
}
7+
}
8+
9+
public protocol Proto { }
10+
11+
public struct Iter<Element: Proto>: IteratorProtocol {
12+
public mutating func next() -> Element? { return nil }
13+
}
14+
15+
extension GenClass: RandomAccessCollection {
16+
public func makeIterator() -> Iter<Element> { return Iter() }
17+
public var startIndex: Int { return 0 }
18+
public var endIndex: Int { return 0 }
19+
}
20+
21+
open class Cl: Proto { }
22+
23+
class Bar: Cl {
24+
var x: Int?
25+
}
26+
27+
// CHECK-LABEL: sil hidden @$S4main5crash4barsSbAA8GenClassCyAA3BarCG_tF
28+
func crash(bars: GenClass<Bar>) -> Bool {
29+
// CHECK: apply [[FN:%.*]]<Bar, [Bar]>
30+
return Array(bars.filter { $0.x == nil }).isEmpty
31+
}

0 commit comments

Comments
 (0)