Skip to content

Commit db9380f

Browse files
committed
SILGen: Fix latent bugs in emitApplyAllocatingInitializer()
The condition we want to test for emitting a downcast is isRequired(), not isInheritable(). The latter is only true for convenience initializers. The other fix is that we actually have to emit a class_method dispatch here to support class hierarchies conforming to literal protocols.
1 parent fc99de4 commit db9380f

File tree

3 files changed

+46
-26
lines changed

3 files changed

+46
-26
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4541,6 +4541,8 @@ static RValue emitApplyAllocatingInitializer(SILGenFunction &SGF,
45414541
callee.emplace(Callee::forWitnessMethod(
45424542
SGF, selfMetaVal.getType().getSwiftRValueType(),
45434543
initRef, subs, loc));
4544+
} else if (getMethodDispatch(ctor) == MethodDispatch::Class) {
4545+
callee.emplace(Callee::forClassMethod(SGF, initRef, subs, loc));
45444546
} else {
45454547
callee.emplace(Callee::forDirect(SGF, initRef, subs, loc));
45464548
}
@@ -4550,7 +4552,7 @@ static RValue emitApplyAllocatingInitializer(SILGenFunction &SGF,
45504552
// For an inheritable initializer, determine whether we'll need to adjust the
45514553
// result type.
45524554
bool requiresDowncast = false;
4553-
if (ctor->isInheritable() && overriddenSelfType) {
4555+
if (ctor->isRequired() && overriddenSelfType) {
45544556
CanType substResultType = substFormalType;
45554557
for (unsigned i : range(ctor->getNumParameterLists())) {
45564558
(void)i;

test/SILGen/literals.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %target-swift-emit-silgen -enable-sil-ownership %s | %FileCheck %s
2+
3+
func takesOptionalFunction(_: (() -> ())?) {}
4+
5+
struct CustomNull : ExpressibleByNilLiteral {
6+
init(nilLiteral: ()) {}
7+
}
8+
9+
func takesANull(_: CustomNull) {}
10+
11+
// CHECK-LABEL: sil hidden @$S8literals4testyyF : $@convention(thin) () -> ()
12+
func test() {
13+
// CHECK: [[NIL:%.*]] = enum $Optional<@callee_guaranteed () -> ()>, #Optional.none!enumelt
14+
// CHECK: [[FN:%.*]] = function_ref @$S8literals21takesOptionalFunctionyyyycSgF
15+
// CHECK: apply [[FN]]([[NIL]])
16+
_ = takesOptionalFunction(nil)
17+
18+
// CHECK: [[METATYPE:%.*]] = metatype $@thin CustomNull.Type
19+
// CHECK: [[NIL_FN:%.*]] = function_ref @$S8literals10CustomNullV10nilLiteralACyt_tcfC
20+
// CHECK: [[NIL:%.*]] = apply [[NIL_FN]]([[METATYPE]])
21+
// CHECK: [[FN:%.*]] = function_ref @$S8literals10takesANullyyAA10CustomNullVF
22+
// CHECK: apply [[FN]]([[NIL]])
23+
_ = takesANull(nil)
24+
}
25+
26+
class CustomStringClass : ExpressibleByStringLiteral {
27+
required init(stringLiteral value: String) {}
28+
required init(extendedGraphemeClusterLiteral value: String) {}
29+
required init(unicodeScalarLiteral value: String) {}
30+
}
31+
32+
class CustomStringSubclass : CustomStringClass {}
33+
34+
// CHECK-LABEL: sil hidden @$S8literals27returnsCustomStringSubclassAA0cdE0CyF : $@convention(thin) () -> @owned CustomStringSubclass
35+
// CHECK: [[METATYPE:%.*]] = metatype $@thick CustomStringSubclass.Type
36+
// CHECK: [[UPCAST:%.*]] = upcast [[METATYPE]] : $@thick CustomStringSubclass.Type to $@thick CustomStringClass.Type
37+
// CHECK: [[CTOR:%.*]] = class_method [[UPCAST]] : $@thick CustomStringClass.Type, #CustomStringClass.init!allocator.1 : (CustomStringClass.Type) -> (String) -> CustomStringClass, $@convention(method) (@owned String, @thick CustomStringClass.Type) -> @owned CustomStringClass
38+
// CHECK: [[RESULT:%.*]] = apply [[CTOR]]({{%.*}}, [[UPCAST]])
39+
// CHECK: [[DOWNCAST:%.*]] = unchecked_ref_cast [[RESULT]] : $CustomStringClass to $CustomStringSubclass
40+
// CHECK: return [[DOWNCAST]]
41+
func returnsCustomStringSubclass() -> CustomStringSubclass {
42+
return "hello world"
43+
}

test/SILGen/nil_literal.swift

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)