Skip to content

Commit 00df48c

Browse files
authored
Merge pull request #37972 from al45tair/problem/73364629
[Runtime] Detect and log redundant subclass/superclass conformances.
2 parents 359f051 + c995942 commit 00df48c

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

stdlib/public/runtime/ProtocolConformance.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -906,10 +906,20 @@ swift_conformsToProtocolImpl(const Metadata *const type,
906906
const WitnessTable *foundWitness = nullptr;
907907
const Metadata *foundType = nullptr;
908908
for (auto searchType : iterateMaybeIncompleteSuperclasses(type)) {
909-
foundWitness = foundWitnesses.lookup(searchType);
910-
if (foundWitness) {
911-
foundType = searchType;
912-
break;
909+
const WitnessTable *witness = foundWitnesses.lookup(searchType);
910+
if (witness) {
911+
if (!foundType) {
912+
foundWitness = witness;
913+
foundType = searchType;
914+
} else {
915+
swift::warning(RuntimeErrorFlagNone,
916+
"Warning: '%s' conforms to protocol '%s', but it also "
917+
"inherits conformance from '%s'. Relying on a "
918+
"particular conformance is undefined behaviour.\n",
919+
foundType->getDescription()->Name.get(),
920+
protocol->Name.get(),
921+
searchType->getDescription()->Name.get());
922+
}
913923
}
914924
}
915925

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
public protocol Hello {
2+
func hello()
3+
}
4+
5+
open class Super {
6+
public init() {}
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import Def
2+
3+
extension Super : Hello {
4+
public func hello() {
5+
print("Hello")
6+
}
7+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Def)) -module-name Def -emit-module -emit-module-path %t/Def.swiftmodule %S/Inputs/protocol-conformance-redundant-def.swift
3+
// RUN: %target-build-swift-dylib(%t/%target-library-name(Ext)) -module-name Ext -emit-module -emit-module-path %t/Ext.swiftmodule -I%t -L%t -lDef %S/Inputs/protocol-conformance-redundant-ext.swift
4+
// RUN: %target-build-swift -I%t -L%t -lDef -o %t/main %target-rpath(%t) %s
5+
// RUN: %target-codesign %t/main %t/%target-library-name(Def) %t/%target-library-name(Ext)
6+
// RUN: %target-run %t/main %t/%target-library-name(Ext) 2>&1 | %FileCheck %s
7+
8+
// REQUIRES: executable_test
9+
// XFAIL: windows
10+
11+
// CHECK: Warning: 'Sub' conforms to protocol 'Hello', but it also inherits conformance from 'Super'. Relying on a particular conformance is undefined behaviour.
12+
// CHECK: Hello
13+
14+
import StdlibUnittest
15+
16+
#if canImport(Darwin)
17+
import Darwin
18+
#elseif canImport(Glibc)
19+
import Glibc
20+
#else
21+
#error("Unsupported platform")
22+
#endif
23+
24+
import Def
25+
26+
let dylibPath = CommandLine.arguments.last!
27+
let openRes = dlopen(dylibPath, RTLD_NOW|RTLD_LOCAL)
28+
assert(openRes != nil, "unable to open extension dylib")
29+
30+
class Sub : Super, Hello {
31+
func hello() {
32+
print("Hello")
33+
}
34+
}
35+
36+
let s = Sub() as AnyObject as! Hello
37+
38+
s.hello()
39+

0 commit comments

Comments
 (0)