Skip to content

Commit c5718d5

Browse files
committed
SILGen: Fix crash with function conversions involving class-constrained protocols
If a protocol has a superclass constraint, the existential type can be upcast to the class type given by the constraint. This wasn't implemented in the function conversion code path, leading to a crash. Fixes <https://bugs.swift.org/browse/SR-12018> / <rdar://problem/58861162>.
1 parent b826b3c commit c5718d5

File tree

3 files changed

+39
-1
lines changed

3 files changed

+39
-1
lines changed

lib/SILGen/SILGenPoly.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ ManagedValue Transform::transform(ManagedValue v,
569569
instanceType = metatypeType.getInstanceType();
570570

571571
auto layout = instanceType.getExistentialLayout();
572-
if (layout.explicitSuperclass) {
572+
if (layout.getSuperclass()) {
573573
CanType openedType = OpenedArchetypeType::getAny(inputSubstType);
574574
SILType loweredOpenedType = SGF.getLoweredType(openedType);
575575

test/SILGen/protocol_with_superclass.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,25 @@ func passesRefinedProtocol(_ r: RefinedProto) {
269269
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
270270
// CHECK-NEXT: return [[RESULT]] : $()
271271

272+
func takesFuncTakingRefinedProto(arg: (RefinedProto) -> ()) {}
273+
274+
func passesFuncTakingBaseClass() {
275+
let closure: (BaseClass) -> () = { _ in }
276+
takesFuncTakingRefinedProto(arg: closure)
277+
}
278+
279+
// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass25passesFuncTakingBaseClassyyF : $@convention(thin) () -> ()
280+
281+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$s24protocol_with_superclass9BaseClassCIegg_AA12RefinedProto_pIegg_TR : $@convention(thin) (@guaranteed RefinedProto, @guaranteed @callee_guaranteed (@guaranteed BaseClass) -> ()) -> ()
282+
// CHECK: [[PAYLOAD:%.*]] = open_existential_ref %0 : $RefinedProto to $@opened("{{.*}}") RefinedProto
283+
// CHECK: [[COPY:%.*]] = copy_value [[PAYLOAD]]
284+
// CHECK: [[UPCAST:%.*]] = upcast [[COPY]] : $@opened("{{.*}}") RefinedProto to $BaseClass
285+
// CHECK: [[BORROW:%.*]] = begin_borrow [[UPCAST]]
286+
// CHECK: apply %1([[BORROW]])
287+
// CHECK: end_borrow [[BORROW]]
288+
// CHECK: destroy_value [[UPCAST]]
289+
// CHECK: return
290+
272291
// CHECK-LABEL: sil_witness_table hidden ConformsToSillyDefault: SillyDefault module protocol_with_superclass {
273292
// CHECK-NEXT: method #SillyDefault.makeT!1: <Self where Self : SillyDefault> (Self) -> () -> Int : @$s24protocol_with_superclass22ConformsToSillyDefaultCAA0fG0A2aDP5makeTSiyFTW
274293
// CHECK-NEXT: }

test/SILGen/protocol_with_superclass_where_clause.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,25 @@ func passesRefinedProtocol(_ r: RefinedProto) {
269269
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
270270
// CHECK-NEXT: return [[RESULT]] : $()
271271

272+
func takesFuncTakingRefinedProto(arg: (RefinedProto) -> ()) {}
273+
274+
func passesFuncTakingBaseClass() {
275+
let closure: (BaseClass) -> () = { _ in }
276+
takesFuncTakingRefinedProto(arg: closure)
277+
}
278+
279+
// CHECK-LABEL: sil hidden [ossa] @$s24protocol_with_superclass25passesFuncTakingBaseClassyyF : $@convention(thin) () -> ()
280+
281+
// CHECK-LABEL: sil shared [transparent] [serializable] [reabstraction_thunk] [ossa] @$s24protocol_with_superclass9BaseClassCIegg_AA12RefinedProto_pIegg_TR : $@convention(thin) (@guaranteed RefinedProto, @guaranteed @callee_guaranteed (@guaranteed BaseClass) -> ()) -> ()
282+
// CHECK: [[PAYLOAD:%.*]] = open_existential_ref %0 : $RefinedProto to $@opened("{{.*}}") RefinedProto
283+
// CHECK: [[COPY:%.*]] = copy_value [[PAYLOAD]]
284+
// CHECK: [[UPCAST:%.*]] = upcast [[COPY]] : $@opened("{{.*}}") RefinedProto to $BaseClass
285+
// CHECK: [[BORROW:%.*]] = begin_borrow [[UPCAST]]
286+
// CHECK: apply %1([[BORROW]])
287+
// CHECK: end_borrow [[BORROW]]
288+
// CHECK: destroy_value [[UPCAST]]
289+
// CHECK: return
290+
272291
// CHECK-LABEL: sil_witness_table hidden ConformsToSillyDefault: SillyDefault module protocol_with_superclass {
273292
// CHECK-NEXT: method #SillyDefault.makeT!1: <Self where Self : SillyDefault> (Self) -> () -> Int : @$s24protocol_with_superclass22ConformsToSillyDefaultCAA0fG0A2aDP5makeTSiyFTW
274293
// CHECK-NEXT: }

0 commit comments

Comments
 (0)