Skip to content

Commit a162c6b

Browse files
authored
Merge pull request #4990 from jckarter/rdar28279269
SILGen: Properly calculate substitutions to invoke _bridgeToObjectiveC.
2 parents cb15745 + c698da6 commit a162c6b

File tree

2 files changed

+101
-3
lines changed

2 files changed

+101
-3
lines changed

lib/SILGen/SILGenBridging.cpp

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "swift/AST/AST.h"
1818
#include "swift/AST/DiagnosticsSIL.h"
1919
#include "swift/AST/ForeignErrorConvention.h"
20+
#include "swift/AST/GenericEnvironment.h"
2021
#include "swift/AST/ParameterList.h"
2122
#include "swift/Basic/Fallthrough.h"
2223
#include "swift/SIL/SILArgument.h"
@@ -61,9 +62,50 @@ emitBridgeNativeToObjectiveC(SILGenFunction &gen,
6162
auto witnessFnTy = witnessRef->getType();
6263

6364
// Compute the substitutions.
64-
ArrayRef<Substitution> substitutions =
65-
swiftValueType->gatherAllSubstitutions(
66-
gen.SGM.SwiftModule, nullptr);
65+
ArrayRef<Substitution> witnessSubstitutions = witness.getSubstitutions();
66+
ArrayRef<Substitution> typeSubstitutions =
67+
swiftValueType->gatherAllSubstitutions(gen.SGM.SwiftModule, nullptr);
68+
69+
// FIXME: Methods of generic types don't have substitutions in their
70+
// ConcreteDeclRefs for some reason. Furthermore,
71+
// SubsitutedProtocolConformances don't substitute their witness
72+
// ConcreteDeclRefs, so we need to do it ourselves.
73+
ArrayRef<Substitution> substitutions;
74+
SmallVector<Substitution, 4> substitutionsBuf;
75+
if (typeSubstitutions.empty()) {
76+
substitutions = witnessSubstitutions;
77+
} else if (witnessSubstitutions.empty()) {
78+
substitutions = typeSubstitutions;
79+
} else {
80+
// FIXME: The substitutions in a witness ConcreteDeclRef really ought to
81+
// be interface types. Instead, we get archetypes from a generic environment
82+
// that's either the extension method's generic environment, for a witness
83+
// from a nominal extension, or the conforming type's original declaration
84+
// generic environment, for a witness from a protocol extension.
85+
auto swiftValueTypeDecl = swiftValueType->getAnyNominal();
86+
GenericEnvironment *witnessEnv;
87+
GenericSignature *witnessSig;
88+
89+
if (witness.getDecl()->getDeclContext()->getDeclaredTypeOfContext()
90+
->isExistentialType()) {
91+
witnessEnv = swiftValueTypeDecl->getGenericEnvironment();
92+
witnessSig = swiftValueTypeDecl->getGenericSignature();
93+
} else {
94+
witnessEnv = witness.getDecl()->getDeclContext()
95+
->getGenericEnvironmentOfContext();
96+
witnessSig = witness.getDecl()->getDeclContext()
97+
->getGenericSignatureOfContext();
98+
}
99+
100+
SubstitutionMap typeSubMap = witnessEnv
101+
->getSubstitutionMap(gen.SGM.SwiftModule,
102+
witnessSig,
103+
typeSubstitutions);
104+
for (auto sub : witnessSubstitutions) {
105+
substitutionsBuf.push_back(sub.subst(gen.SGM.SwiftModule, typeSubMap));
106+
}
107+
substitutions = substitutionsBuf;
108+
}
67109

68110
if (!substitutions.empty()) {
69111
// Substitute into the witness function type.
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-silgen %s | %FileCheck %s
2+
// REQUIRES: objc_interop
3+
4+
import Foundation
5+
6+
protocol Fooable {}
7+
8+
extension Fooable where Self: _ObjectiveCBridgeable {
9+
func _bridgeToObjectiveC() -> _ObjectiveCType {
10+
fatalError()
11+
}
12+
13+
static func _forceBridgeFromObjectiveC(
14+
_ source: _ObjectiveCType,
15+
result: inout Self?
16+
) {
17+
fatalError()
18+
}
19+
20+
static func _conditionallyBridgeFromObjectiveC(
21+
_ source: _ObjectiveCType,
22+
result: inout Self?
23+
) -> Bool {
24+
fatalError()
25+
}
26+
27+
static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?)
28+
-> Self {
29+
fatalError()
30+
}
31+
}
32+
33+
struct Foo: Fooable, _ObjectiveCBridgeable {
34+
typealias _ObjectiveCType = NSObject
35+
}
36+
struct Gen<T, U>: Fooable, _ObjectiveCBridgeable {
37+
typealias _ObjectiveCType = NSObject
38+
}
39+
40+
class Bar: NSObject {
41+
dynamic func bar(_: Any) {}
42+
}
43+
44+
// CHECK-LABEL: sil hidden @_TF42objc_bridged_using_protocol_extension_impl7callBarFT3barCS_3Bar3fooVS_3Foo_T_
45+
func callBar(bar: Bar, foo: Foo) {
46+
// CHECK: [[BRIDGE:%.*]] = function_ref @_TFe42objc_bridged_using_protocol_extension_implRxs21_ObjectiveCBridgeablexS_7FooablerS1_19_bridgeToObjectiveCfT_wxPS0_15_ObjectiveCType
47+
// CHECK: apply [[BRIDGE]]<Foo, NSObject>
48+
bar.bar(foo)
49+
}
50+
51+
// CHECK-LABEL:sil hidden @_TF42objc_bridged_using_protocol_extension_impl7callBarFT3barCS_3Bar3genGVS_3GenSiSS__T_
52+
func callBar(bar: Bar, gen: Gen<Int, String>) {
53+
// CHECK: [[BRIDGE:%.*]] = function_ref @_TFe42objc_bridged_using_protocol_extension_implRxs21_ObjectiveCBridgeablexS_7FooablerS1_19_bridgeToObjectiveCfT_wxPS0_15_ObjectiveCType
54+
// CHECK: apply [[BRIDGE]]<Gen<Int, String>, NSObject>
55+
bar.bar(gen)
56+
}

0 commit comments

Comments
 (0)