Skip to content

Commit 1f652bc

Browse files
committed
Sema: Don't derive witnesses in swiftinterface files
This fixes a regression from #36752. Previously, a RawRepresentable enum would use the default implementation of == from a protocol extension in the standard library. After the above PR, we began synthesizing the == operator, just like we do for ordinary enums. However, when type checking an older swiftinterface file, we would still synthesize the declaration and try to use it, even though it would not have existed in the older dylib built with the older compiler. Fix this by not deriving witnesses in swiftinterface files at all. The interface should already explicitly list out all derived witnesses; if one is not listed, it should not be derived, because it does not exist in the dylib. Fixes rdar://problem/80466745.
1 parent 5ea28a7 commit 1f652bc

File tree

2 files changed

+67
-16
lines changed

2 files changed

+67
-16
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3963,22 +3963,25 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
39633963
// Determine whether we can derive a witness for this requirement.
39643964
bool canDerive = false;
39653965

3966-
// Can a witness for this requirement be derived for this nominal type?
3967-
if (auto derivable = DerivedConformance::getDerivableRequirement(
3968-
nominal,
3969-
requirement)) {
3970-
if (derivable == requirement) {
3971-
// If it's the same requirement, we can derive it here.
3972-
canDerive = true;
3973-
} else {
3974-
// Otherwise, go satisfy the derivable requirement, which can introduce
3975-
// a member that could in turn satisfy *this* requirement.
3976-
auto derivableProto = cast<ProtocolDecl>(derivable->getDeclContext());
3977-
auto conformance =
3978-
TypeChecker::conformsToProtocol(Adoptee, derivableProto,
3979-
DC->getParentModule());
3980-
if (conformance.isConcrete()) {
3981-
(void)conformance.getConcrete()->getWitnessDecl(derivable);
3966+
auto *SF = DC->getParentSourceFile();
3967+
if (!(SF == nullptr || SF->Kind == SourceFileKind::Interface)) {
3968+
// Can a witness for this requirement be derived for this nominal type?
3969+
if (auto derivable = DerivedConformance::getDerivableRequirement(
3970+
nominal,
3971+
requirement)) {
3972+
if (derivable == requirement) {
3973+
// If it's the same requirement, we can derive it here.
3974+
canDerive = true;
3975+
} else {
3976+
// Otherwise, go satisfy the derivable requirement, which can introduce
3977+
// a member that could in turn satisfy *this* requirement.
3978+
auto derivableProto = cast<ProtocolDecl>(derivable->getDeclContext());
3979+
auto conformance =
3980+
TypeChecker::conformsToProtocol(Adoptee, derivableProto,
3981+
DC->getParentModule());
3982+
if (conformance.isConcrete()) {
3983+
(void)conformance.getConcrete()->getWitnessDecl(derivable);
3984+
}
39823985
}
39833986
}
39843987
}
@@ -4288,6 +4291,10 @@ ResolveWitnessResult ConformanceChecker::resolveWitnessViaDerivation(
42884291
ValueDecl *requirement) {
42894292
assert(!isa<AssociatedTypeDecl>(requirement) && "Use resolveTypeWitnessVia*");
42904293

4294+
auto *SF = DC->getParentSourceFile();
4295+
if (SF != nullptr && SF->Kind == SourceFileKind::Interface)
4296+
return ResolveWitnessResult::Missing;
4297+
42914298
// Find the declaration that derives the protocol conformance.
42924299
NominalTypeDecl *derivingTypeDecl = nullptr;
42934300
auto *nominal = Adoptee->getAnyNominal();
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %target-swift-frontend -emit-silgen %s | %FileCheck %s
2+
3+
// swift-interface-format-version: 1.0
4+
// swift-compiler-version: Apple Swift version 5.5 (swiftlang-1300.0.29.102 clang-1300.0.28.1)
5+
// swift-module-flags: -target x86_64-apple-macosx11.0 -enable-objc-interop -enable-library-evolution -module-name DerivedWitnesses
6+
import Swift
7+
8+
public enum HasSynthesizedEquals : Int {
9+
case x
10+
case y
11+
12+
public static func == (a: HasSynthesizedEquals, b: HasSynthesizedEquals) -> Bool
13+
public func hash(into hasher: inout Hasher)
14+
public var hashValue: Int {
15+
get
16+
}
17+
18+
public init?(rawValue: Int)
19+
public typealias RawValue = Int
20+
public var rawValue: Int {
21+
get
22+
}
23+
}
24+
25+
public enum UsesDefaultEquals : Int {
26+
case x
27+
case y
28+
29+
public init?(rawValue: Int)
30+
public typealias RawValue = Int
31+
public var rawValue: Int {
32+
get
33+
}
34+
}
35+
36+
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] [ossa] @$s16DerivedWitnesses20HasSynthesizedEqualsOSQAASQ2eeoiySbx_xtFZTW : $@convention(witness_method: Equatable) (@in_guaranteed HasSynthesizedEquals, @in_guaranteed HasSynthesizedEquals, @thick HasSynthesizedEquals.Type) -> Bool {
37+
// CHECK: bb0(%0 : $*HasSynthesizedEquals, %1 : $*HasSynthesizedEquals, %2 : $@thick HasSynthesizedEquals.Type):
38+
// CHECK: function_ref @$s16DerivedWitnesses20HasSynthesizedEqualsO2eeoiySbAC_ACtFZ : $@convention(method) (HasSynthesizedEquals, HasSynthesizedEquals, @thin HasSynthesizedEquals.Type) -> Bool
39+
// CHECK: return
40+
41+
// CHECK-LABEL: sil shared [transparent] [serialized] [thunk] [ossa] @$s16DerivedWitnesses17UsesDefaultEqualsOSQAASQ2eeoiySbx_xtFZTW : $@convention(witness_method: Equatable) (@in_guaranteed UsesDefaultEquals, @in_guaranteed UsesDefaultEquals, @thick UsesDefaultEquals.Type) -> Bool {
42+
// CHECK: bb0(%0 : $*UsesDefaultEquals, %1 : $*UsesDefaultEquals, %2 : $@thick UsesDefaultEquals.Type):
43+
// CHECK: function_ref @$ss2eeoiySbx_xtSYRzSQ8RawValueRpzlF : $@convention(thin) <τ_0_0 where τ_0_0 : RawRepresentable, τ_0_0.RawValue : Equatable> (@in_guaranteed τ_0_0, @in_guaranteed τ_0_0) -> Bool
44+
// CHECK: return

0 commit comments

Comments
 (0)