Skip to content

Commit 775b4a4

Browse files
committed
AST: Inherit access level of opaque type decls from naming decl.
When an `OpaqueTypeDecl` is constructed, the access level attributes of the decl that names the opaque type were copied on to it. However, the `@usableFromInline` attribute is not permitted on every decl, so it does not get copied. This in turn causes access level computations for opaque types to fail to take `@usableFromInline` into account and that results in the emitted symbol getting the wrong linkage during IRGen. The fix is to make access level computations take this quirk of opaque types into account directly (like they already to for several other kinds of decls), instead of relying on copying of attributes. Resolves rdar://110544170
1 parent 9f51c06 commit 775b4a4

7 files changed

+49
-3
lines changed

Diff for: lib/AST/AccessRequests.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,13 @@ AccessLevelRequest::evaluate(Evaluator &evaluator, ValueDecl *D) const {
6767
}
6868
}
6969

70+
// Special case for opaque type decls, which inherit the access of their
71+
// naming decls.
72+
if (auto *opaqueType = dyn_cast<OpaqueTypeDecl>(D)) {
73+
if (auto *namingDecl = opaqueType->getNamingDecl())
74+
return namingDecl->getFormalAccess();
75+
}
76+
7077
DeclContext *DC = D->getDeclContext();
7178

7279
// Special case for generic parameters; we just give them a dummy

Diff for: lib/AST/Decl.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -3749,6 +3749,15 @@ bool ValueDecl::isUsableFromInline() const {
37493749
return true;
37503750
}
37513751

3752+
if (auto *opaqueType = dyn_cast<OpaqueTypeDecl>(this)) {
3753+
if (auto *namingDecl = opaqueType->getNamingDecl()) {
3754+
if (namingDecl->getAttrs().hasAttribute<UsableFromInlineAttr>() ||
3755+
namingDecl->getAttrs().hasAttribute<AlwaysEmitIntoClientAttr>() ||
3756+
namingDecl->getAttrs().hasAttribute<InlinableAttr>())
3757+
return true;
3758+
}
3759+
}
3760+
37523761
if (auto *EED = dyn_cast<EnumElementDecl>(this))
37533762
if (EED->getParentEnum()->getAttrs().hasAttribute<UsableFromInlineAttr>())
37543763
return true;

Diff for: lib/Sema/TypeCheckGeneric.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,6 @@ OpaqueResultTypeRequest::evaluate(Evaluator &evaluator,
213213
auto opaqueDecl = OpaqueTypeDecl::get(
214214
originatingDecl, genericParams, parentDC, interfaceSignature,
215215
opaqueReprs);
216-
opaqueDecl->copyFormalAccessFrom(originatingDecl);
217216
if (auto originatingSig = originatingDC->getGenericSignatureOfContext()) {
218217
opaqueDecl->setGenericSignature(originatingSig);
219218
} else {

Diff for: test/IRGen/Inputs/AlwaysInlineIntoWithOpaque.swift

+13
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,16 @@ public func testInlineWithOpaque() -> some P {
1414
}
1515
return 2.0
1616
}
17+
18+
@_alwaysEmitIntoClient
19+
public func testInlineWithOpaqueUsableFromInline() -> some P {
20+
if #available(macOS 9.0, *) {
21+
return usableFromInline()
22+
}
23+
return 4.0
24+
}
25+
26+
@usableFromInline
27+
func usableFromInline() -> some P {
28+
return 3
29+
}

Diff for: test/IRGen/Inputs/AlwaysInlineIntoWithOpaqueReplacement.swift

+5
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@ extension Int : P {
66

77
extension Double : P {
88
}
9+
10+
@usableFromInline
11+
func usableFromInline() -> some P {
12+
return 3
13+
}

Diff for: test/IRGen/opaque_result_alwaysInlineIntoClient.swift

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -emit-library -emit-module-path %t/AlwaysInlineIntoWithOpaque.swiftmodule -module-name AlwaysInlineIntoWithOpaque %S/Inputs/AlwaysInlineIntoWithOpaque.swift -o %t/%target-library-name(AlwaysInlineIntoWithOpaque)
2+
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -emit-library -emit-module-path %t/AlwaysInlineIntoWithOpaque.swiftmodule -module-name AlwaysInlineIntoWithOpaque -enable-library-evolution %S/Inputs/AlwaysInlineIntoWithOpaque.swift -o %t/%target-library-name(AlwaysInlineIntoWithOpaque)
33
// RUN: %target-codesign %t/%target-library-name(AlwaysInlineIntoWithOpaque)
44
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -lAlwaysInlineIntoWithOpaque -module-name main -I %t -L %t %s -o %t/a.out
55
// RUN: %target-codesign %t/a.out
66
// RUN: %target-run %t/a.out | %FileCheck %s
77

8-
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -emit-library -emit-module-path %t/AlwaysInlineIntoWithOpaque.swiftmodule -module-name AlwaysInlineIntoWithOpaque %S/Inputs/AlwaysInlineIntoWithOpaqueReplacement.swift -o %t/%target-library-name(AlwaysInlineIntoWithOpaque)
8+
// RUN: %target-build-swift -target %target-cpu-apple-macosx10.15 -parse-as-library -emit-library -emit-module-path %t/AlwaysInlineIntoWithOpaque.swiftmodule -module-name AlwaysInlineIntoWithOpaque -enable-library-evolution %S/Inputs/AlwaysInlineIntoWithOpaqueReplacement.swift -o %t/%target-library-name(AlwaysInlineIntoWithOpaque)
99
// RUN: %target-codesign %t/a.out
1010
// RUN: %target-run %t/a.out | %FileCheck %s
1111

@@ -27,3 +27,11 @@ public func test() {
2727

2828
test()
2929
// CHECK: 1
30+
31+
public func testUsableFromInline() {
32+
let p = testInlineWithOpaqueUsableFromInline()
33+
print(p)
34+
}
35+
36+
testUsableFromInline()
37+
// CHECK: 3

Diff for: test/TBD/opaque_result_type.swift

+5
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ public func dynReplacement(x: String) -> some P {
7777
return "replaced"
7878
}
7979

80+
@usableFromInline
81+
func ufi() -> some O {
82+
return 1
83+
}
84+
8085
extension String: P {
8186
public func poo() -> some O {
8287
return 0

0 commit comments

Comments
 (0)