Skip to content

Commit e725a21

Browse files
authored
Merge pull request swiftlang#20380 from slavapestov/protocol-superclass-fix
Sema: A protocol with a class constraint is a subtype of any protocols the class conforms to
2 parents 2d93200 + 97cc601 commit e725a21

File tree

5 files changed

+62
-12
lines changed

5 files changed

+62
-12
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3956,9 +3956,8 @@ Optional<ProtocolConformanceRef> TypeChecker::containsProtocol(
39563956

39573957
// First, if we have a superclass constraint, the class may conform
39583958
// concretely.
3959-
if (layout.explicitSuperclass) {
3960-
if (auto result = conformsToProtocol(layout.explicitSuperclass, Proto,
3961-
DC, options)) {
3959+
if (auto superclass = layout.getSuperclass()) {
3960+
if (auto result = conformsToProtocol(superclass, Proto, DC, options)) {
39623961
return result;
39633962
}
39643963
}
@@ -3972,15 +3971,6 @@ Optional<ProtocolConformanceRef> TypeChecker::containsProtocol(
39723971
if (PD == Proto)
39733972
return ProtocolConformanceRef(Proto);
39743973

3975-
// If the protocol has a superclass constraint, we might conform
3976-
// concretely.
3977-
if (auto superclass = PD->getSuperclass()) {
3978-
if (auto result = conformsToProtocol(superclass, Proto,
3979-
DC, options)) {
3980-
return result;
3981-
}
3982-
}
3983-
39843974
// Now check refined protocols.
39853975
if (PD->inheritsFrom(Proto))
39863976
return ProtocolConformanceRef(Proto);

test/SILGen/protocol_with_superclass.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,30 @@ class ConformsToSillyDefault : ClassWithDefault<Int>, SillyDefault {}
245245
// CHECK: class_method %1 : $ClassWithDefault<Int>, #ClassWithDefault.makeT!1 : <T> (ClassWithDefault<T>) -> () -> T, $@convention(method) <τ_0_0> (@guaranteed ClassWithDefault<τ_0_0>) -> @out τ_0_0
246246
// CHECK: return
247247

248+
class BaseClass : BaseProto {}
249+
250+
protocol RefinedProto : BaseClass {}
251+
252+
func takesBaseProtocol(_: BaseProto) {}
253+
254+
func passesRefinedProtocol(_ r: RefinedProto) {
255+
takesBaseProtocol(r)
256+
}
257+
258+
// CHECK-LABEL: sil hidden @$s24protocol_with_superclass21passesRefinedProtocolyyAA0E5Proto_pF : $@convention(thin) (@guaranteed RefinedProto) -> ()
259+
// CHECK: bb0(%0 : @guaranteed $RefinedProto):
260+
// CHECK: [[OPENED:%.*]] = open_existential_ref %0 : $RefinedProto to $@opened("{{.*}}") RefinedProto
261+
// CHECK-NEXT: [[BASE:%.*]] = alloc_stack $BaseProto
262+
// CHECK-NEXT: [[BASE_PAYLOAD:%.*]] = init_existential_addr [[BASE]] : $*BaseProto, $@opened("{{.*}}") RefinedProto
263+
// CHECK-NEXT: [[OPENED_COPY:%.*]] = copy_value [[OPENED]] : $@opened("{{.*}}") RefinedProto
264+
// CHECK-NEXT: store [[OPENED_COPY]] to [init] [[BASE_PAYLOAD]] : $*@opened("{{.*}}") RefinedProto
265+
// CHECK: [[FUNC:%.*]] = function_ref @$s24protocol_with_superclass17takesBaseProtocolyyAA0E5Proto_pF : $@convention(thin) (@in_guaranteed BaseProto) -> ()
266+
// CHECK-NEXT: apply [[FUNC]]([[BASE]]) : $@convention(thin) (@in_guaranteed BaseProto) -> ()
267+
// CHECK-NEXT: destroy_addr [[BASE]] : $*BaseProto
268+
// CHECK-NEXT: dealloc_stack [[BASE]] : $*BaseProto
269+
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
270+
// CHECK-NEXT: return [[RESULT]] : $()
271+
248272
// CHECK-LABEL: sil_witness_table hidden ConformsToSillyDefault: SillyDefault module protocol_with_superclass {
249273
// CHECK-NEXT: method #SillyDefault.makeT!1: <Self where Self : SillyDefault> (Self) -> () -> Int : @$s24protocol_with_superclass22ConformsToSillyDefaultCAA0fG0A2aDP5makeTSiyFTW
250274
// CHECK-NEXT: }

test/SILGen/protocol_with_superclass_where_clause.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,30 @@ class ConformsToSillyDefault : ClassWithDefault<Int>, SillyDefault {}
245245
// CHECK: class_method %1 : $ClassWithDefault<Int>, #ClassWithDefault.makeT!1 : <T> (ClassWithDefault<T>) -> () -> T, $@convention(method) <τ_0_0> (@guaranteed ClassWithDefault<τ_0_0>) -> @out τ_0_0
246246
// CHECK: return
247247

248+
class BaseClass : BaseProto {}
249+
250+
protocol RefinedProto where Self : BaseClass {}
251+
252+
func takesBaseProtocol(_: BaseProto) {}
253+
254+
func passesRefinedProtocol(_ r: RefinedProto) {
255+
takesBaseProtocol(r)
256+
}
257+
258+
// CHECK-LABEL: sil hidden @$s24protocol_with_superclass21passesRefinedProtocolyyAA0E5Proto_pF : $@convention(thin) (@guaranteed RefinedProto) -> ()
259+
// CHECK: bb0(%0 : @guaranteed $RefinedProto):
260+
// CHECK: [[OPENED:%.*]] = open_existential_ref %0 : $RefinedProto to $@opened("{{.*}}") RefinedProto
261+
// CHECK-NEXT: [[BASE:%.*]] = alloc_stack $BaseProto
262+
// CHECK-NEXT: [[BASE_PAYLOAD:%.*]] = init_existential_addr [[BASE]] : $*BaseProto, $@opened("{{.*}}") RefinedProto
263+
// CHECK-NEXT: [[OPENED_COPY:%.*]] = copy_value [[OPENED]] : $@opened("{{.*}}") RefinedProto
264+
// CHECK-NEXT: store [[OPENED_COPY]] to [init] [[BASE_PAYLOAD]] : $*@opened("{{.*}}") RefinedProto
265+
// CHECK: [[FUNC:%.*]] = function_ref @$s24protocol_with_superclass17takesBaseProtocolyyAA0E5Proto_pF : $@convention(thin) (@in_guaranteed BaseProto) -> ()
266+
// CHECK-NEXT: apply [[FUNC]]([[BASE]]) : $@convention(thin) (@in_guaranteed BaseProto) -> ()
267+
// CHECK-NEXT: destroy_addr [[BASE]] : $*BaseProto
268+
// CHECK-NEXT: dealloc_stack [[BASE]] : $*BaseProto
269+
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
270+
// CHECK-NEXT: return [[RESULT]] : $()
271+
248272
// CHECK-LABEL: sil_witness_table hidden ConformsToSillyDefault: SillyDefault module protocol_with_superclass {
249273
// CHECK-NEXT: method #SillyDefault.makeT!1: <Self where Self : SillyDefault> (Self) -> () -> Int : @$s24protocol_with_superclass22ConformsToSillyDefaultCAA0fG0A2aDP5makeTSiyFTW
250274
// CHECK-NEXT: }

test/decl/protocol/protocol_with_superclass.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,12 @@ protocol RefinedProtocol : BaseClass {
294294
func takesT(_: T)
295295
}
296296

297+
func takesBaseProtocol(_: BaseProtocol) {}
298+
299+
func passesRefinedProtocol(_ r: RefinedProtocol) {
300+
takesBaseProtocol(r)
301+
}
302+
297303
class RefinedClass : BaseClass, RefinedProtocol {
298304
func takesT(_: T) {
299305
_ = T.self

test/decl/protocol/protocol_with_superclass_where_clause.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,12 @@ class RefinedClass : BaseClass, RefinedProtocol {
300300
}
301301
}
302302

303+
func takesBaseProtocol(_: BaseProtocol) {}
304+
305+
func passesRefinedProtocol(_ r: RefinedProtocol) {
306+
takesBaseProtocol(r)
307+
}
308+
303309
class LoopClass : LoopProto {}
304310
protocol LoopProto where Self : LoopClass {}
305311

0 commit comments

Comments
 (0)