mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Embedded: support existentials with inherited conformances
That means: derived classes where the base conforms to a protocol
This commit is contained in:
@@ -47,6 +47,16 @@ public struct Conformance: CustomStringConvertible, NoReflectionChildren {
|
||||
return bridged.getGenericConformance().conformance
|
||||
}
|
||||
|
||||
public var isInherited: Bool {
|
||||
assert(isConcrete)
|
||||
return bridged.isInheritedConformance()
|
||||
}
|
||||
|
||||
public var inheritedConformance: Conformance {
|
||||
assert(isInherited)
|
||||
return bridged.getInheritedConformance().conformance
|
||||
}
|
||||
|
||||
public var specializedSubstitutions: SubstitutionMap {
|
||||
assert(isSpecialized)
|
||||
return SubstitutionMap(bridged: bridged.getSpecializedSubstitutions())
|
||||
|
||||
@@ -271,7 +271,8 @@ private func shouldInline(apply: FullApplySite, callee: Function, alreadyInlined
|
||||
private func specializeWitnessTables(for initExRef: InitExistentialRefInst, _ context: ModulePassContext,
|
||||
_ worklist: inout FunctionWorklist)
|
||||
{
|
||||
for conformance in initExRef.conformances where conformance.isConcrete {
|
||||
for c in initExRef.conformances where c.isConcrete {
|
||||
let conformance = c.isInherited ? c.inheritedConformance : c
|
||||
let origWitnessTable = context.lookupWitnessTable(for: conformance)
|
||||
if conformance.isSpecialized {
|
||||
if origWitnessTable == nil {
|
||||
|
||||
@@ -2042,8 +2042,10 @@ struct BridgedConformance {
|
||||
BRIDGED_INLINE bool isConcrete() const;
|
||||
BRIDGED_INLINE bool isValid() const;
|
||||
BRIDGED_INLINE bool isSpecializedConformance() const;
|
||||
BRIDGED_INLINE bool isInheritedConformance() const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedASTType getType() const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance getGenericConformance() const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedConformance getInheritedConformance() const;
|
||||
SWIFT_IMPORT_UNSAFE BRIDGED_INLINE BridgedSubstitutionMap getSpecializedSubstitutions() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -163,6 +163,10 @@ bool BridgedConformance::isSpecializedConformance() const {
|
||||
return swift::isa<swift::SpecializedProtocolConformance>(unbridged().getConcrete());
|
||||
}
|
||||
|
||||
bool BridgedConformance::isInheritedConformance() const {
|
||||
return swift::isa<swift::InheritedProtocolConformance>(unbridged().getConcrete());
|
||||
}
|
||||
|
||||
BridgedASTType BridgedConformance::getType() const {
|
||||
return {unbridged().getConcrete()->getType().getPointer()};
|
||||
}
|
||||
@@ -172,6 +176,11 @@ BridgedConformance BridgedConformance::getGenericConformance() const {
|
||||
return {swift::ProtocolConformanceRef(specPC->getGenericConformance())};
|
||||
}
|
||||
|
||||
BridgedConformance BridgedConformance::getInheritedConformance() const {
|
||||
auto *inheritedConf = swift::cast<swift::InheritedProtocolConformance>(unbridged().getConcrete());
|
||||
return {swift::ProtocolConformanceRef(inheritedConf->getInheritedConformance())};
|
||||
}
|
||||
|
||||
BridgedSubstitutionMap BridgedConformance::getSpecializedSubstitutions() const {
|
||||
auto *specPC = swift::cast<swift::SpecializedProtocolConformance>(unbridged().getConcrete());
|
||||
return {specPC->getSubstitutionMap()};
|
||||
|
||||
@@ -2504,10 +2504,14 @@ IRGenModule::getConformanceInfo(const ProtocolDecl *protocol,
|
||||
|
||||
const ConformanceInfo *info;
|
||||
|
||||
auto *specConf = conformance;
|
||||
if (auto *inheritedC = dyn_cast<InheritedProtocolConformance>(conformance))
|
||||
specConf = inheritedC->getInheritedConformance();
|
||||
|
||||
// If there is a specialized SILWitnessTable for the specialized conformance,
|
||||
// directly use it.
|
||||
if (auto *sc = dyn_cast<SpecializedProtocolConformance>(conformance)) {
|
||||
SILWitnessTable *wt = getSILModule().lookUpWitnessTable(conformance);
|
||||
if (auto *sc = dyn_cast<SpecializedProtocolConformance>(specConf)) {
|
||||
SILWitnessTable *wt = getSILModule().lookUpWitnessTable(specConf);
|
||||
if (wt && wt->getConformance() == sc) {
|
||||
info = new SpecializedConformanceInfo(sc);
|
||||
Conformances.try_emplace(conformance, info);
|
||||
|
||||
@@ -541,6 +541,9 @@ SILModule::lookUpFunctionInWitnessTable(ProtocolConformanceRef C,
|
||||
linker.processConformance(C);
|
||||
}
|
||||
ProtocolConformance *conf = C.getConcrete();
|
||||
if (auto *inheritedC = dyn_cast<InheritedProtocolConformance>(conf))
|
||||
conf = inheritedC->getInheritedConformance();
|
||||
|
||||
if (!isa<SpecializedProtocolConformance>(conf) || !lookupInSpecializedWitnessTable) {
|
||||
conf = conf->getRootConformance();
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public protocol ProtoWithAssocConf: AnyObject {
|
||||
}
|
||||
|
||||
public class GenClass2<T>: Q {
|
||||
var t: T
|
||||
final var t: T
|
||||
|
||||
init(t : T) { self.t = t }
|
||||
|
||||
@@ -67,6 +67,14 @@ public class GenClass2<T>: Q {
|
||||
}
|
||||
}
|
||||
|
||||
public class DerivedFromGenClass2: GenClass2<Int> {
|
||||
init() { super.init(t: 42) }
|
||||
|
||||
public override func bar() {
|
||||
print("derived-bar")
|
||||
}
|
||||
}
|
||||
|
||||
final public class GenClass3<V>: ProtoWithAssocConf {
|
||||
public func foo() -> GenClass2<Int> {
|
||||
print("foo")
|
||||
@@ -74,6 +82,13 @@ final public class GenClass3<V>: ProtoWithAssocConf {
|
||||
}
|
||||
}
|
||||
|
||||
final public class OtherClass: ProtoWithAssocConf {
|
||||
public func foo() -> GenClass2<Int> {
|
||||
print("other-foo")
|
||||
return DerivedFromGenClass2()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func createExWithAssocConf() -> any ProtoWithAssocConf {
|
||||
return GenClass3<Int>()
|
||||
@@ -84,6 +99,63 @@ public func callExWithAssocConf(_ p: any ProtoWithAssocConf) {
|
||||
x.bar()
|
||||
}
|
||||
|
||||
public class Base<T>: ClassBound {
|
||||
public func foo() { print("Base.foo()") }
|
||||
public func bar() { print("Base.bar()") }
|
||||
}
|
||||
|
||||
public class Derived1: Base<Int> {
|
||||
public override func foo() { print("Derived1.foo()") }
|
||||
public override func bar() { print("Derived1.bar()") }
|
||||
}
|
||||
|
||||
public class Derived2<T>: Base<T> {
|
||||
public override func foo() { print("Derived2.foo()") }
|
||||
public override func bar() { print("Derived2.bar()") }
|
||||
}
|
||||
|
||||
public func takes_p1(_ p: P1) {
|
||||
p.normal()
|
||||
}
|
||||
|
||||
public protocol P1: AnyObject {
|
||||
func normal()
|
||||
}
|
||||
|
||||
public protocol P2 {
|
||||
func foo()
|
||||
}
|
||||
|
||||
public class ConditionalConformanceBase<A> {
|
||||
final var a: A
|
||||
|
||||
init(a: A) { self.a = a }
|
||||
}
|
||||
|
||||
extension ConditionalConformanceBase: P1 where A: P2 {
|
||||
public func normal() {
|
||||
a.foo()
|
||||
}
|
||||
}
|
||||
|
||||
public class ConditionalConformanceDerived<T>: ConditionalConformanceBase<T> {
|
||||
init(t: T) { super.init(a: t) }
|
||||
}
|
||||
|
||||
|
||||
public func testConditionalConformance<T: P2>(t: T) {
|
||||
takes_p1(ConditionalConformanceDerived(t: t))
|
||||
}
|
||||
|
||||
|
||||
struct S: P2 {
|
||||
var i: Int
|
||||
|
||||
func foo() {
|
||||
print(i)
|
||||
}
|
||||
}
|
||||
|
||||
@main
|
||||
struct Main {
|
||||
static func main() {
|
||||
@@ -98,6 +170,17 @@ struct Main {
|
||||
callExWithAssocConf(createExWithAssocConf())
|
||||
// CHECK: foo
|
||||
// CHECK: bar
|
||||
callExWithAssocConf(OtherClass())
|
||||
// CHECK: other-foo
|
||||
// CHECK: derived-bar
|
||||
test(existential: Derived1())
|
||||
// CHECK: Derived1.foo()
|
||||
// CHECK: Derived1.bar()
|
||||
test(existential: Derived2<Bool>())
|
||||
// CHECK: Derived2.foo()
|
||||
// CHECK: Derived2.bar()
|
||||
testConditionalConformance(t: S(i: 27))
|
||||
// CHECK: 27
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user