Skip to content

Commit 1290cc4

Browse files
committed
SIL: Lower closure functions' captures in their own expansion context.
The capture arguments are a private contract between the closure and its context, and will only ever be bound from the enclosing context, so there's no need to obscure opaque underlying types (unless it's serializable because it's in inlinable code, in which case we continue to use the minimal type expansion context to account for inlining as before.) Fixes rdar://83378116.
1 parent 7139184 commit 1290cc4

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

lib/SIL/IR/SILFunctionType.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2212,8 +2212,13 @@ static CanSILFunctionType getSILFunctionType(
22122212

22132213
// Lower the capture context parameters, if any.
22142214
if (constant && constant->getAnyFunctionRef()) {
2215+
// Lower in the context of the closure. Since the set of captures is a
2216+
// private contract between the closure and its enclosing context, we
2217+
// don't need to keep its capture types opaque.
22152218
auto expansion = TypeExpansionContext::maximal(
2216-
expansionContext.getContext(), expansionContext.isWholeModuleContext());
2219+
constant->getAnyFunctionRef()->getAsDeclContext(), false);
2220+
// ...unless it's inlinable, in which case it might get inlined into
2221+
// some place we need to keep opaque types opaque.
22172222
if (constant->isSerialized())
22182223
expansion = TypeExpansionContext::minimal();
22192224
lowerCaptureContextParameters(TC, *constant, genericSig, expansion, inputs);
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// RUN: %target-swift-emit-silgen -disable-availability-checking -verify %s
2+
// rdar://83378116
3+
4+
public protocol P {}
5+
public protocol Q {}
6+
7+
struct SP<T: P>: P { init(t: T) {} }
8+
struct SQ: Q {}
9+
10+
struct Tubb<C: Q, T, F> {
11+
}
12+
13+
extension Tubb: P where T: P, F: P {
14+
init(c: C, t: () -> T, f: () -> F) {}
15+
}
16+
17+
struct SP2: P {}
18+
19+
func bar() -> some P { return SP2() }
20+
21+
public struct Butt {
22+
public func foo() -> some P {
23+
let sp = SP(t: bar())
24+
return Tubb(c: SQ(), t: { sp }, f: { sp })
25+
}
26+
}

0 commit comments

Comments
 (0)