Skip to content

Commit 63e6636

Browse files
committed
[metadata prespecialization] Prespecialize canonically only in-module.
Previously, prespecialization was incorrectly being performed for non-resilient types defined by other modules. This is incorrect for statically canonical metadata records because in order to be canonical, they need to be returned from the metadata accessor which is emitted by the module which defines the type.
1 parent 49d76c3 commit 63e6636

5 files changed

+85
-2
lines changed

lib/IRGen/MetadataRequest.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,10 @@ bool irgen::isNominalGenericContextTypeMetadataAccessTrivial(
709709
}
710710

711711
if (IGM.getSILModule().isWholeModule()) {
712-
if (nominal.isResilient(IGM.getSwiftModule(),
713-
ResilienceExpansion::Maximal)) {
712+
// Canonical prespecializations can only be emitted within the module where
713+
// the generic type is itself defined, since it is the module where the
714+
// metadata accessor is defined.
715+
if (IGM.getSwiftModule() != nominal.getModuleContext()) {
714716
return false;
715717
}
716718
} else {
@@ -727,6 +729,11 @@ bool irgen::isNominalGenericContextTypeMetadataAccessTrivial(
727729
}
728730
}
729731

732+
if (nominal.isResilient(IGM.getSwiftModule(),
733+
ResilienceExpansion::Maximal)) {
734+
return false;
735+
}
736+
730737
if (isa<ClassType>(type) || isa<BoundGenericClassType>(type)) {
731738
// TODO: Support classes.
732739
return false;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public enum OneArgument<First> {
2+
case first(First)
3+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
public struct OneArgument<First> {
2+
public let first: First
3+
4+
public let line: UInt
5+
6+
public init(_ first: First, line: UInt = #line) {
7+
self.first = first
8+
self.line = line
9+
}
10+
}
11+
12+
extension OneArgument : CustomStringConvertible {
13+
public var description: String {
14+
"\(first) @ \(line)"
15+
}
16+
}
17+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/enum-public-nonfrozen-1argument.swift -emit-library -o %t/libArgument.dylib -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule
3+
// RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment
4+
5+
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu
6+
// UNSUPPORTED: CPU=i386 && OS=ios
7+
// UNSUPPORTED: CPU=armv7 && OS=ios
8+
// UNSUPPORTED: CPU=armv7s && OS=ios
9+
10+
// CHECK-NOT: @"$s8Argument03OneA0Oy4main03TheA0VGMf" =
11+
12+
@inline(never)
13+
func consume<T>(_ t: T) {
14+
withExtendedLifetime(t) { t in
15+
}
16+
}
17+
18+
import Argument
19+
20+
struct TheArgument {
21+
let value: Int
22+
}
23+
24+
func doit() {
25+
consume( Argument.OneArgument.first(TheArgument(value: 13)) )
26+
}
27+
doit()
28+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -Xfrontend -prespecialize-generic-metadata -target %module-target-future %S/Inputs/struct-public-nonfrozen-1argument.swift -emit-library -o %t/libArgument.dylib -emit-module -module-name Argument -emit-module-path %t/Argument.swiftmodule
3+
// RUN: %swift -prespecialize-generic-metadata -target %module-target-future -emit-ir %s -L %t -I %t -lArgument | %FileCheck %s -DINT=i%target-ptrsize -DALIGNMENT=%target-alignment
4+
5+
// REQUIRES: OS=macosx || OS=ios || OS=tvos || OS=watchos || OS=linux-gnu
6+
// UNSUPPORTED: CPU=i386 && OS=ios
7+
// UNSUPPORTED: CPU=armv7 && OS=ios
8+
// UNSUPPORTED: CPU=armv7s && OS=ios
9+
10+
// CHECK-NOT: @"$s8Argument03OneA0Vy4main03TheA0VGMf" =
11+
12+
@inline(never)
13+
func consume<T>(_ t: T) {
14+
withExtendedLifetime(t) { t in
15+
}
16+
}
17+
18+
import Argument
19+
20+
struct TheArgument {
21+
let value: Int
22+
}
23+
24+
func doit() {
25+
consume( OneArgument(TheArgument(value: 13)) )
26+
}
27+
doit()
28+

0 commit comments

Comments
 (0)