Skip to content

Commit 493db43

Browse files
authored
Merge pull request #7914 from slavapestov/super-wrong-upcast-fix-3.1
Sema: Fix 'super' calls from methods returning 'Self' [3.1]
2 parents 2eb0101 + 51bf3f9 commit 493db43

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

lib/Sema/CSGen.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2506,8 +2506,13 @@ namespace {
25062506
if (!selfDecl->hasType())
25072507
return ErrorType::get(tc.Context);
25082508

2509-
Type declaredType = selfDecl->getType()->getRValueInstanceType();
2510-
Type superclassTy = declaredType->getSuperclass(&tc);
2509+
// If the method returns 'Self', the type of 'self' is a
2510+
// DynamicSelfType. Unwrap it before getting the superclass.
2511+
auto selfTy = selfDecl->getType()->getRValueInstanceType();
2512+
if (auto *dynamicSelfTy = selfTy->getAs<DynamicSelfType>())
2513+
selfTy = dynamicSelfTy->getSelfType();
2514+
2515+
auto superclassTy = selfTy->getSuperclass(&tc);
25112516

25122517
if (selfDecl->getType()->is<MetatypeType>())
25132518
superclassTy = MetatypeType::get(superclassTy);

test/SILGen/dynamic_self.swift

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,61 @@ func partialApplySelfReturn(c: Factory, t: Factory.Type) {
240240
_ = Factory.staticNewInstance
241241
}
242242

243+
// Super call to a method returning Self
244+
class Base {
245+
required init() {}
246+
247+
func returnsSelf() -> Self {
248+
return self
249+
}
250+
251+
static func returnsSelfStatic() -> Self {
252+
return self.init()
253+
}
254+
}
255+
256+
class Derived : Base {
257+
// CHECK-LABEL: sil hidden @_TFC12dynamic_self7Derived9superCallfT_T_ : $@convention(method) (@guaranteed Derived) -> ()
258+
// CHECK: [[SELF:%.*]] = copy_value %0
259+
// CHECK: [[SUPER:%.*]] = upcast [[SELF]] : $Derived to $Base
260+
// CHECK: [[METHOD:%.*]] = function_ref @_TFC12dynamic_self4Base11returnsSelffT_DS0_
261+
// CHECK: apply [[METHOD]]([[SUPER]])
262+
// CHECK: return
263+
func superCall() {
264+
super.returnsSelf()
265+
}
266+
267+
// CHECK-LABEL: sil hidden @_TZFC12dynamic_self7Derived15superCallStaticfT_T_ : $@convention(method) (@thick Derived.Type) -> ()
268+
// CHECK: [[SUPER:%.*]] = upcast %0 : $@thick Derived.Type to $@thick Base.Type
269+
// CHECK: [[METHOD:%.*]] = function_ref @_TZFC12dynamic_self4Base17returnsSelfStaticfT_DS0_
270+
// CHECK: apply [[METHOD]]([[SUPER]])
271+
// CHECK: return
272+
static func superCallStatic() {
273+
super.returnsSelfStatic()
274+
}
275+
276+
// CHECK-LABEL: sil hidden @_TFC12dynamic_self7Derived32superCallFromMethodReturningSelffT_DS0_ : $@convention(method) (@guaranteed Derived) -> @owned Derived
277+
// CHECK: [[SELF:%.*]] = copy_value %0
278+
// CHECK: [[SUPER:%.*]] = upcast [[SELF]] : $Derived to $Base
279+
// CHECK: [[METHOD:%.*]] = function_ref @_TFC12dynamic_self4Base11returnsSelffT_DS0_
280+
// CHECK: apply [[METHOD]]([[SUPER]])
281+
// CHECK: return
282+
func superCallFromMethodReturningSelf() -> Self {
283+
super.returnsSelf()
284+
return self
285+
}
286+
287+
// CHECK-LABEL: sil hidden @_TZFC12dynamic_self7Derived38superCallFromMethodReturningSelfStaticfT_DS0_ : $@convention(method) (@thick Derived.Type) -> @owned Derived
288+
// CHECK: [[SUPER:%.*]] = upcast %0 : $@thick Derived.Type to $@thick Base.Type
289+
// CHECK: [[METHOD:%.*]] = function_ref @_TZFC12dynamic_self4Base17returnsSelfStaticfT_DS0_
290+
// CHECK: apply [[METHOD]]([[SUPER]])
291+
// CHECK: return
292+
static func superCallFromMethodReturningSelfStatic() -> Self {
293+
super.returnsSelfStatic()
294+
return self.init()
295+
}
296+
}
297+
243298
// CHECK-LABEL: sil_witness_table hidden X: P module dynamic_self {
244299
// CHECK: method #P.f!1: @_TTWC12dynamic_self1XS_1PS_FS1_1f
245300

0 commit comments

Comments
 (0)