Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.3] SILCombine: Fix update of substitution map when substituting opened opaque archetypes #31385

Merged
merged 2 commits into from Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/swift/AST/ProtocolConformanceRef.h
Expand Up @@ -134,6 +134,8 @@ class ProtocolConformanceRef {
void dump(llvm::raw_ostream &out, unsigned indent = 0,
bool details = true) const;

void print(llvm::raw_ostream &out) const;

bool operator==(ProtocolConformanceRef other) const {
return Union == other.Union;
}
Expand Down
3 changes: 3 additions & 0 deletions include/swift/AST/Type.h
Expand Up @@ -148,6 +148,9 @@ enum class SubstFlags {
DesugarMemberTypes = 0x02,
/// Substitute types involving opaque type archetypes.
SubstituteOpaqueArchetypes = 0x04,
/// Force substitution of opened archetypes. Normally -- without these flag --
/// opened archetype conformances are not substituted.
ForceSubstituteOpenedExistentials = 0x08,
};

/// Options for performing substitutions into a type.
Expand Down
7 changes: 7 additions & 0 deletions lib/AST/ASTDumper.cpp
Expand Up @@ -3331,6 +3331,13 @@ void ProtocolConformanceRef::dump(llvm::raw_ostream &out, unsigned indent,

dumpProtocolConformanceRefRec(*this, out, indent, visited);
}

void ProtocolConformanceRef::print(llvm::raw_ostream &out) const {
llvm::SmallPtrSet<const ProtocolConformance *, 8> visited;
dumpProtocolConformanceRefRec(*this, out, 0, visited);

}

void ProtocolConformance::dump() const {
auto &out = llvm::errs();
dump(out);
Expand Down
3 changes: 2 additions & 1 deletion lib/AST/ProtocolConformance.cpp
Expand Up @@ -122,7 +122,8 @@ ProtocolConformanceRef::subst(Type origType,

// Opened existentials trivially conform and do not need to go through
// substitution map lookup.
if (substType->isOpenedExistential())
if (substType->isOpenedExistential() &&
!options.contains(SubstFlags::ForceSubstituteOpenedExistentials))
return *this;

auto *proto = getRequirement();
Expand Down
11 changes: 9 additions & 2 deletions lib/SIL/IR/SILPrinter.cpp
Expand Up @@ -375,7 +375,7 @@ static void printGenericSpecializationInfo(
raw_ostream &OS, StringRef Kind, StringRef Name,
const GenericSpecializationInformation *SpecializationInfo,
SubstitutionMap Subs = { }) {
if (!SpecializationInfo)
if (!SpecializationInfo && Subs.empty())
return;

auto PrintSubstitutions = [&](SubstitutionMap Subs) {
Expand All @@ -384,6 +384,11 @@ static void printGenericSpecializationInfo(
[&](Type type) { OS << type; },
[&] { OS << ", "; });
OS << '>';
OS << " conformances <";
interleave(Subs.getConformances(),
[&](ProtocolConformanceRef conf) { conf.print(OS); },
[&] { OS << ", ";});
OS << '>';
};

OS << "// Generic specialization information for " << Kind << " " << Name;
Expand Down Expand Up @@ -716,7 +721,9 @@ class SILPrinter : public SILInstructionVisitor<SILPrinter> {
Ctx.printInstructionCallBack(&I);
if (SILPrintGenericSpecializationInfo) {
if (auto AI = ApplySite::isa(const_cast<SILInstruction *>(&I)))
if (AI.getSpecializationInfo() && AI.getCalleeFunction())
if ((AI.getSpecializationInfo() ||
!AI.getSubstitutionMap().empty()) &&
AI.getCalleeFunction())
printGenericSpecializationInfo(
PrintState.OS, "call-site", AI.getCalleeFunction()->getName(),
AI.getSpecializationInfo(), AI.getSubstitutionMap());
Expand Down
3 changes: 2 additions & 1 deletion lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp
Expand Up @@ -859,7 +859,8 @@ SILInstruction *SILCombiner::createApplyWithConcreteType(
return CEI.lookupExistentialConformance(proto);
}
return ProtocolConformanceRef(proto);
});
},
SubstFlags::ForceSubstituteOpenedExistentials);
}

// We need to make sure that we can a) update Apply to use the new args and b)
Expand Down
91 changes: 90 additions & 1 deletion test/SILOptimizer/sil_combine_concrete_existential.sil
@@ -1,4 +1,5 @@
// RUN: %target-sil-opt -enable-objc-interop -enable-sil-verify-all %s -sil-combine | %FileCheck %s
// RUN: %target-sil-opt -enable-objc-interop -enable-sil-verify-all %s -sil-combine -sil-print-generic-specialization-info | %FileCheck %s
// RUN: %target-swift-frontend -O %s -emit-ir

// These tests exercise the same SILCombine optimization as
// existential_type_propagation.sil, but cover additional corner
Expand Down Expand Up @@ -615,3 +616,91 @@ bb0(%0 : $*τ_0_0, %1 : $*τ_0_2, %2 : $*τ_0_1):
dealloc_stack %5 : $*P1
return %25 : $()
}


public class MyObject {
deinit
init()
}

public protocol SubscriptionViewControllerDelegate { }

public class SubscriptionViewController {
deinit
init()
}

public protocol ResourceKitProtocol : MyObject { }

public protocol ResourceKitDelegate {
func subscriptionViewController(for resourceKit: ResourceKitProtocol)
}

class ViewController : ResourceKitDelegate {
func subscriptionViewController(for resourceKit: ResourceKitProtocol)
deinit
init()
}

class SubscriptionViewControllerBuilder {
@_hasStorage final let delegate: SubscriptionViewControllerDelegate { get }
init(delegate: SubscriptionViewControllerDelegate)
deinit
}

extension MyObject : SubscriptionViewControllerDelegate { }

// Make sure that we correctly update the substitution map of the apply.
// To satisfy ``τ_0_0 : SubscriptionViewControllerDelegate`` the updated
// substitution map of
// apply %10<$@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol>
// needs to contain the concrete conformance
// ``(normal_conformance type=NSObject protocol=SubscriptionViewControllerDelegate)``
// not ``(abstract_conformance protocol=SubscriptionViewControllerDelegate)``

sil @callee2 : $@convention(thin) <τ_0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder

// CHECK: sil @test_opend_archeype_concrete_conformance_substitution : $@convention(method) (@guaranteed ResourceKitProtocol, @guaranteed ViewController) -> () {
// CHECK: bb0([[ARG:%.*]] : $ResourceKitProtocol, [[ARG2:%.*]] : $ViewController):
// CHECK: [[T1:%.*]] = metatype $@thick SubscriptionViewControllerBuilder.Type
// CHECK: [[T2:%.*]] = open_existential_ref [[ARG]] : $ResourceKitProtocol to $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: [[T3:%.*]] = alloc_stack $SubscriptionViewControllerDelegate
// CHECK: [[T4:%.*]] = init_existential_addr [[T3]] : $*SubscriptionViewControllerDelegate, $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: store [[T2]] to [[T4]] : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: [[T5:%.*]] = function_ref @callee2 : $@convention(thin) <τ_0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder
// CHECK: [[T6:%.*]] = alloc_stack $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: copy_addr [[T4]] to [initialization] [[T6]] : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
// CHECK: Generic specialization information for call-site callee2 <ResourceKitProtocol> conformances <(inherited_conformance type=ResourceKitProtocol protocol=SubscriptionViewControllerDelegate
// CHECK: (normal_conformance type=MyObject protocol=SubscriptionViewControllerDelegate))>:
// CHECK: apply [[T5]]<@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol>([[T6]], [[T1]])

sil @test_opend_archeype_concrete_conformance_substitution : $@convention(method) (@guaranteed ResourceKitProtocol, @guaranteed ViewController) -> () {
bb0(%0 : $ResourceKitProtocol, %1 : $ViewController):
%4 = metatype $@thick SubscriptionViewControllerBuilder.Type
%5 = open_existential_ref %0 : $ResourceKitProtocol to $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
%6 = alloc_stack $SubscriptionViewControllerDelegate
%7 = init_existential_addr %6 : $*SubscriptionViewControllerDelegate, $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
strong_retain %5 : $@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
store %5 to %7 : $*@opened("E4D92D2A-8893-11EA-9C89-ACDE48001122") ResourceKitProtocol
%10 = function_ref @callee2: $@convention(thin) <τ_0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder
%11 = open_existential_addr mutable_access %6 : $*SubscriptionViewControllerDelegate to $*@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate
%12 = alloc_stack $@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate
copy_addr %11 to [initialization] %12 : $*@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate
%14 = apply %10<@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate>(%12, %4) : $@convention(thin) <τ_0_0 where τ_0_0 : SubscriptionViewControllerDelegate> (@in τ_0_0, @thick SubscriptionViewControllerBuilder.Type) -> @owned SubscriptionViewControllerBuilder
destroy_addr %6 : $*SubscriptionViewControllerDelegate
dealloc_stack %12 : $*@opened("FAA82796-8893-11EA-9C89-ACDE48001122") SubscriptionViewControllerDelegate
dealloc_stack %6 : $*SubscriptionViewControllerDelegate
strong_release %14 : $SubscriptionViewControllerBuilder
%19 = tuple ()
return %19 : $()
}

sil_vtable SubscriptionViewControllerBuilder {}
sil_vtable SubscriptionViewController {}
sil_vtable ViewController {}
sil_vtable CCCC {}
sil_vtable CC {}
sil_vtable C {}
sil_vtable C_PQ {}
sil_vtable CDefaultStatic {}
sil_vtable MyObject {}