Skip to content

[Devirtualize] Support devirtualization of witness methods when we have a polymorphic type and no substitutions required #15064

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

Merged
merged 1 commit into from
Mar 8, 2018
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/SIL/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2438,7 +2438,9 @@ CanSILFunctionType
SILFunctionType::substGenericArgs(SILModule &silModule,
SubstitutionList subs) {
if (subs.empty()) {
assert(!isPolymorphic() && "no args for polymorphic substitution");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the right assertion is (!isPolymorphic() || getGenericSignature()->areAllParamsConcrete())

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

assert(
(!isPolymorphic() || getGenericSignature()->areAllParamsConcrete()) &&
"no args for non-concrete polymorphic substitution");
return CanSILFunctionType(this);
}

Expand Down
90 changes: 90 additions & 0 deletions test/SILOptimizer/devirt_witness_method_empty_conformance.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// RUN: %target-swift-frontend -O -emit-ir -primary-file %s | %FileCheck %s

public struct PublicStruct {
}

public enum PublicEnum {
}

struct RegStruct {
enum EnumInRegStruct {
case case1
case case2
}

private var optNode: Any?
private var ClassInRegStructs = [ClassInRegStruct]()

var isEmpty: Bool {
return optNode == nil && ClassInRegStructs.isEmpty
}

private func funcInRegStruct() -> RegStruct? {
var funcInRegStruct = RegStruct()
return funcInRegStruct
}

func func2InRegStruct(boolParam: Bool = false,
_ body: (inout Bool) -> Void) {
var finished = false
func2InRegStruct(body, boolParam: boolParam, &finished)
}

private func func2InRegStruct(_ body: (inout Bool) -> Void,
boolParam: Bool = false, _ finished: inout Bool) {
funcInRegStruct()?.func2InRegStruct(body, boolParam: boolParam, &finished)
}

private static func func2InRegStruct(_ ClassInRegStructs: [ClassInRegStruct],
_ body: (inout Bool) -> Void,
boolParam: Bool, _ finished: inout Bool) {
}

func funcInStructAndProtAndExt(_ EnumInRegStruct: EnumInRegStruct, space: PublicEnum,
_ body: () -> Void) {
guard !isEmpty else { return }

func2InRegStruct(boolParam: !EnumInRegStruct.isDownwards) { finished in
}
}

final private class ClassInRegStruct {
}
}

extension RegStruct.EnumInRegStruct {
fileprivate var isDownwards: Bool {
switch self {
case .case1:
return true
case .case2:
return false
}
}
}

private protocol ApplyRegStruct {
mutating func applyTransform()
}

protocol RegStructable {
mutating func funcInStructAndProtAndExt(from space: PublicEnum, transform: RegStruct)
}

extension ApplyRegStruct {
mutating func funcInStructAndProtAndExt(
from space: PublicEnum, transform: RegStruct
) {
transform.funcInStructAndProtAndExt(.case2, space: space) {
// CHECK-LABEL: define hidden swiftcc void @"$SSa39devirt_witness_method_empty_conformanceAA12PublicStructVRszlE14applyTransformyyF"(%TSa* nocapture swiftself dereferenceable
// CHECK-NEXT: entry
// CHECK-NEXT: ret void
applyTransform()
}
}
}

extension Array : ApplyRegStruct, RegStructable where Element == PublicStruct {
mutating func applyTransform() {
}
}