Skip to content

Commit 5c4bbf3

Browse files
Merge pull request swiftlang#31736 from aschwaighofer/fix_protocol_conformance_subst
Existentials don't always conform to a protocol via an abstract confo…
2 parents 39888b9 + b40b1be commit 5c4bbf3

File tree

7 files changed

+79
-18
lines changed

7 files changed

+79
-18
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -519,11 +519,7 @@ class GenericSignatureBuilder {
519519

520520
ProtocolConformanceRef operator()(CanType dependentType,
521521
Type conformingReplacementType,
522-
ProtocolDecl *conformedProtocol) const {
523-
return builder->lookupConformance(dependentType,
524-
conformingReplacementType,
525-
conformedProtocol);
526-
}
522+
ProtocolDecl *conformedProtocol) const;
527523
};
528524

529525
/// Retrieve a function that can perform conformance lookup for this

include/swift/AST/Type.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,7 @@ enum class SubstFlags {
147147
/// Map member types to their desugared witness type.
148148
DesugarMemberTypes = 0x02,
149149
/// Substitute types involving opaque type archetypes.
150-
SubstituteOpaqueArchetypes = 0x04,
151-
/// Force substitution of opened archetypes. Normally -- without these flag --
152-
/// opened archetype conformances are not substituted.
153-
ForceSubstituteOpenedExistentials = 0x08,
150+
SubstituteOpaqueArchetypes = 0x04
154151
};
155152

156153
/// Options for performing substitutions into a type.

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3501,6 +3501,19 @@ GenericSignatureBuilder::getLookupConformanceFn()
35013501
return LookUpConformanceInBuilder(this);
35023502
}
35033503

3504+
ProtocolConformanceRef
3505+
GenericSignatureBuilder::LookUpConformanceInBuilder::operator()(
3506+
CanType dependentType, Type conformingReplacementType,
3507+
ProtocolDecl *conformedProtocol) const {
3508+
// Lookup conformances for opened existential.
3509+
if (conformingReplacementType->isOpenedExistential()) {
3510+
return conformedProtocol->getModuleContext()->lookupConformance(
3511+
conformingReplacementType, conformedProtocol);
3512+
}
3513+
return builder->lookupConformance(dependentType, conformingReplacementType,
3514+
conformedProtocol);
3515+
}
3516+
35043517
ProtocolConformanceRef
35053518
GenericSignatureBuilder::lookupConformance(CanType dependentType,
35063519
Type conformingReplacementType,

lib/AST/ProtocolConformance.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,6 @@ ProtocolConformanceRef::subst(Type origType,
120120
// Otherwise, compute the substituted type.
121121
auto substType = origType.subst(subs, conformances, options);
122122

123-
// Opened existentials trivially conform and do not need to go through
124-
// substitution map lookup.
125-
if (substType->isOpenedExistential() &&
126-
!options.contains(SubstFlags::ForceSubstituteOpenedExistentials))
127-
return *this;
128-
129123
auto *proto = getRequirement();
130124

131125
// If the type is an existential, it must be self-conforming.

lib/AST/Type.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3548,6 +3548,11 @@ operator()(CanType dependentType, Type conformingReplacementType,
35483548
ProtocolConformanceRef LookUpConformanceInSubstitutionMap::
35493549
operator()(CanType dependentType, Type conformingReplacementType,
35503550
ProtocolDecl *conformedProtocol) const {
3551+
// Lookup conformances for opened existential.
3552+
if (conformingReplacementType->isOpenedExistential()) {
3553+
return conformedProtocol->getModuleContext()->lookupConformance(
3554+
conformingReplacementType, conformedProtocol);
3555+
}
35513556
return Subs.lookupConformance(dependentType, conformedProtocol);
35523557
}
35533558

@@ -3559,12 +3564,23 @@ operator()(CanType dependentType, Type conformingReplacementType,
35593564
|| conformingReplacementType->is<DependentMemberType>()
35603565
|| conformingReplacementType->is<TypeVariableType>())
35613566
&& "replacement requires looking up a concrete conformance");
3567+
// Lookup conformances for opened existential.
3568+
if (conformingReplacementType->isOpenedExistential()) {
3569+
return conformedProtocol->getModuleContext()->lookupConformance(
3570+
conformingReplacementType, conformedProtocol);
3571+
}
35623572
return ProtocolConformanceRef(conformedProtocol);
35633573
}
35643574

35653575
ProtocolConformanceRef LookUpConformanceInSignature::
35663576
operator()(CanType dependentType, Type conformingReplacementType,
35673577
ProtocolDecl *conformedProtocol) const {
3578+
// Lookup conformances for opened existential.
3579+
if (conformingReplacementType->isOpenedExistential()) {
3580+
return conformedProtocol->getModuleContext()->lookupConformance(
3581+
conformingReplacementType, conformedProtocol);
3582+
}
3583+
35683584
// FIXME: Should pass dependentType instead, once
35693585
// GenericSignature::lookupConformance() does the right thing
35703586
return Sig->lookupConformance(conformingReplacementType->getCanonicalType(),

lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,8 +952,7 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
952952
return CEI.lookupExistentialConformance(proto);
953953
}
954954
return ProtocolConformanceRef(proto);
955-
},
956-
SubstFlags::ForceSubstituteOpenedExistentials);
955+
});
957956
}
958957

959958
// We need to make sure that we can a) update Apply to use the new args and b)

test/SILOptimizer/inline_generics.sil

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline -sil-inline-generics=true | %FileCheck %s
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline -sil-inline-generics=true -sil-print-generic-specialization-info | %FileCheck %s
22
// RUN: %target-sil-opt -enable-sil-verify-all %s -inline -sil-inline-generics=false | %FileCheck --check-prefix=DISABLED-GENERIC-INLINING-CHECK %s
3+
// RUN: %target-swift-frontend -O -emit-ir %s
34

45
sil_stage canonical
56

@@ -178,3 +179,48 @@ bb0(%0 : $*T, %1 : $*T):
178179
sil_default_witness_table P {
179180
no_default
180181
}
182+
183+
protocol SomeProto : class {}
184+
protocol OtherProto {}
185+
186+
class MyObject {}
187+
extension MyObject : OtherProto {}
188+
189+
class MyNumber : MyObject {}
190+
extension MyNumber : SomeProto {}
191+
192+
sil_vtable MyObject {}
193+
sil_vtable MyNumber {}
194+
195+
// Make sure we subsitute the correct conformance when inlining. When
196+
// substituting we need to pick up the normal_conformance.
197+
198+
// CHECK-LABEL: sil @test_inlining : $@convention(objc_method) (@owned MyNumber) -> () {
199+
// CHECK-NOT: Generic specialization information for call-site dootherstuff <MyNumber & SomeProto> conformances <(abstract_conformance protocol=OtherProto)>
200+
// CHECK: Generic specialization information
201+
// CHECK: (normal_conformance type=MyObject protocol=OtherProto)
202+
// CHECK: end sil function 'test_inlining'
203+
204+
sil @test_inlining : $@convention(objc_method) (@owned MyNumber) -> () {
205+
bb0(%0 : $MyNumber):
206+
%12 = init_existential_ref %0 : $MyNumber : $MyNumber, $MyNumber & SomeProto
207+
%14 = open_existential_ref %12 : $MyNumber & SomeProto to $@opened("B9711AE4-946E-11EA-A871-ACDE48001122") MyNumber & SomeProto
208+
%15 = alloc_stack $OtherProto
209+
%16 = init_existential_addr %15 : $*OtherProto, $@opened("B9711AE4-946E-11EA-A871-ACDE48001122") MyNumber & SomeProto
210+
store %14 to %16 : $*@opened("B9711AE4-946E-11EA-A871-ACDE48001122") MyNumber & SomeProto
211+
%18 = function_ref @doStuff : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
212+
%20 = apply %18<@opened("B9711AE4-946E-11EA-A871-ACDE48001122") MyNumber & SomeProto>(%16) : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
213+
destroy_addr %15 : $*OtherProto
214+
dealloc_stack %15 : $*OtherProto
215+
%27 = tuple ()
216+
return %27 : $()
217+
}
218+
219+
sil @dootherstuff : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
220+
221+
sil shared [signature_optimized_thunk] [always_inline] @doStuff : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> () {
222+
bb0(%0 : $*τ_0_0):
223+
%2 = function_ref @dootherstuff : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
224+
%3 = apply %2<τ_0_0>(%0) : $@convention(thin) <τ_0_0 where τ_0_0 : OtherProto> (@in_guaranteed τ_0_0) -> ()
225+
return %3 : $()
226+
}

0 commit comments

Comments
 (0)