Fix two bugs related to the casts optimizations.

The protocol_lookup the testcase from Interpreter test-cases exposed two bugs, once I tried to compiler with with -O:
 - SILCloner was generating an open_existential_ref from an open_existential_metatype instruction during cloning even if the existential in question was not a class existential.
 - DynamicCasts was not considering the fact that subclasses of a given class may implement a protocol, even if the class does not implement it.

Swift SVN r27260
This commit is contained in:
Roman Levenstein
2015-04-13 22:12:54 +00:00
parent eaeaf5dfd3
commit 194aed3df2
4 changed files with 62 additions and 4 deletions

View File

@@ -1223,6 +1223,15 @@ visitOpenExistentialMetatypeInst(OpenExistentialMetatypeInst *inst) {
OpenedExistentialSubs[archetypeTy]
= ArchetypeType::getOpened(archetypeTy->getOpenedExistentialType());
if (!inst->getOperand().getType().canUseExistentialRepresentation(
inst->getModule(), ExistentialRepresentation::Class)) {
doPostProcess(inst, getBuilder().createOpenExistentialMetatype(
getOpLocation(inst->getLoc()),
getOpValue(inst->getOperand()),
getOpType(inst->getType())));
return;
}
doPostProcess(inst,
getBuilder().createOpenExistentialRef(getOpLocation(inst->getLoc()),
getOpValue(inst->getOperand()),

View File

@@ -130,6 +130,13 @@ classifyDynamicCastToProtocol(CanType source,
if (auto *CD = source.getClassOrBoundGenericClass()) {
if (canClassOrSuperclassesHaveExtensions(CD, isWholeModuleOpts))
return DynamicCastFeasibility::MaySucceed;
// Derived types may conform to the protocol.
if (!CD->isFinal()) {
// TODO: If it is a private type or internal type and we
// can prove that there are no derived types conforming to a
// protocol, then we can still return WillFail.
return DynamicCastFeasibility::MaySucceed;
}
}
// If the source type is private or target protocol is private,

View File

@@ -62,6 +62,8 @@ public protocol CP2: class {}
// and it cannot be extended elsewhere as it is private
private class D: CP1 {}
private final class F: CP1 {}
// Class E implements both class protocols at once
class E: CP1, CP2 {}
@@ -668,10 +670,8 @@ func test27() -> Bool {
}
// CHECK-LABEL: sil hidden [noinline] @_TF12cast_folding8test28_1FT_Sb
// CHECK: bb0
// CHECK-NEXT: %0 = integer_literal $Builtin.Int1, 0
// CHECK-NEXT: %1 = struct $Bool
// CHECK-NEXT: return %1
// CHECK: checked_cast
// CHECK: return
@inline(never)
func test28_1() -> Bool {
return cast28(D.self)
@@ -687,6 +687,16 @@ func test28_2() -> Bool {
return cast28(E.self)
}
// CHECK-LABEL: sil hidden [noinline] @_TF12cast_folding8test28_3FT_Sb
// CHECK: bb0
// CHECK-NEXT: %0 = integer_literal $Builtin.Int1, 0
// CHECK-NEXT: %1 = struct $Bool
// CHECK-NEXT: return %1
@inline(never)
func test28_3() -> Bool {
return cast28(F.self)
}
// CHECK-LABEL: sil hidden [noinline] @_TF12cast_folding6test29FT_Sb
// CHECK: bb0
// Check that cast is not elmiminated even though cast29 is a conversion

View File

@@ -0,0 +1,32 @@
// RUN: %target-swift-frontend -O -emit-sil -primary-file %s | FileCheck %s
// Check that this file can be compiled using -O at all (it used to crash due to a bug in the SILCloner)
// Check that it can be compiled correctly.
// Protocol lookup for metatypes.
protocol StaticFoo {
static func foo() -> String
}
class StaticBar {
// Check that the cast is not folded as a failing cast.
// CHECK-LABEL: sil hidden [noinline] @_TZFC15protocol_lookup9StaticBar12mightHaveFoofMS0_FT_SS
// Check that the cast was not eliminated.
// CHECK: checked_cast_addr_br
@inline(never)
class func mightHaveFoo() -> String {
if let selfAsFoo? = self as? StaticFoo.Type {
return selfAsFoo.foo()
} else {
return "no Foo for you"
}
}
}
class StaticWibble : StaticBar, StaticFoo {
static func foo() -> String { return "StaticWibble.foo" }
}
// CHECK: StaticWibble.foo
println(StaticWibble.mightHaveFoo())