Skip to content

Commit 4ada917

Browse files
Merge pull request #17434 from aschwaighofer/silgen_without_actually_escaping_fix_4.2
[4.2] SILGen: createWithoutActuallyEscapingClosure needs to use a sub…
2 parents 1e07724 + 7357bb2 commit 4ada917

File tree

2 files changed

+39
-7
lines changed

2 files changed

+39
-7
lines changed

lib/SILGen/SILGenPoly.cpp

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2939,13 +2939,13 @@ static ManagedValue createThunk(SILGenFunction &SGF,
29392939

29402940
static CanSILFunctionType buildWithoutActuallyEscapingThunkType(
29412941
SILGenFunction &SGF, CanSILFunctionType &noEscapingType,
2942-
CanSILFunctionType &escapingType, GenericEnvironment *&genericEnv) {
2942+
CanSILFunctionType &escapingType, GenericEnvironment *&genericEnv,
2943+
SubstitutionMap &interfaceSubs) {
29432944

29442945
assert(escapingType->getExtInfo() ==
29452946
noEscapingType->getExtInfo().withNoEscape(false));
29462947

29472948
CanType inputSubstType, outputSubstType;
2948-
SubstitutionMap interfaceSubs;
29492949
return SGF.buildThunkType(noEscapingType, escapingType,
29502950
inputSubstType, outputSubstType,
29512951
genericEnv, interfaceSubs,
@@ -3000,12 +3000,13 @@ SILGenFunction::createWithoutActuallyEscapingClosure(
30003000
->getExtInfo()
30013001
.withNoEscape(false));
30023002

3003+
SubstitutionMap interfaceSubs;
30033004
GenericEnvironment *genericEnv = nullptr;
30043005
auto noEscapingFnTy =
30053006
noEscapingFunctionValue.getType().castTo<SILFunctionType>();
30063007

30073008
auto thunkType = buildWithoutActuallyEscapingThunkType(
3008-
*this, noEscapingFnTy, escapingFnTy, genericEnv);
3009+
*this, noEscapingFnTy, escapingFnTy, genericEnv, interfaceSubs);
30093010

30103011
auto *thunk = SGM.getOrCreateReabstractionThunk(
30113012
thunkType, noEscapingFnTy, escapingFnTy, F.isSerialized());
@@ -3016,17 +3017,24 @@ SILGenFunction::createWithoutActuallyEscapingClosure(
30163017
buildWithoutActuallyEscapingThunkBody(thunkSGF);
30173018
}
30183019

3019-
CanSILFunctionType substFnType = thunkType->substGenericArgs(
3020-
F.getModule(), thunk->getForwardingSubstitutions());
3020+
CanSILFunctionType substFnTy = thunkType;
3021+
// Use the subsitution map in the context of the current function.
3022+
// thunk->getForwardingSubstitutionMap() / thunk might have been created in a
3023+
// different function's generic enviroment.
3024+
SmallVector<Substitution, 4> subs;
3025+
if (auto genericSig = thunkType->getGenericSignature()) {
3026+
genericSig->getSubstitutions(interfaceSubs, subs);
3027+
substFnTy = thunkType->substGenericArgs(F.getModule(), interfaceSubs);
3028+
}
30213029

30223030
// Create it in our current function.
30233031
auto thunkValue = B.createFunctionRef(loc, thunk);
30243032
SILValue noEscapeValue =
30253033
noEscapingFunctionValue.ensurePlusOne(*this, loc).forward(*this);
30263034
SingleValueInstruction *thunkedFn = B.createPartialApply(
30273035
loc, thunkValue,
3028-
SILType::getPrimitiveObjectType(substFnType),
3029-
thunk->getForwardingSubstitutions(),
3036+
SILType::getPrimitiveObjectType(substFnTy),
3037+
subs,
30303038
noEscapeValue,
30313039
SILType::getPrimitiveObjectType(escapingFnTy));
30323040
// We need to ensure the 'lifetime' of the trivial values context captures. As

test/SILGen/without_actually_escaping.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,27 @@ func letEscape(f: () -> ()) -> () -> () {
4343
func letEscapeThrow(f: () throws -> () -> ()) throws -> () -> () {
4444
return try withoutActuallyEscaping(f) { return try $0() }
4545
}
46+
47+
// We used to crash on this example because we would use the wrong substitution
48+
// map.
49+
struct DontCrash {
50+
private func firstEnv<L1>(
51+
closure1: (L1) -> Bool,
52+
closure2: (L1) -> Bool
53+
) {
54+
withoutActuallyEscaping(closure1) { closure1 in
55+
secondEnv(
56+
closure1: closure1,
57+
closure2: closure2
58+
)
59+
}
60+
}
61+
62+
private func secondEnv<L2>(
63+
closure1: @escaping (L2) -> Bool,
64+
closure2: (L2) -> Bool
65+
) {
66+
withoutActuallyEscaping(closure2) { closure2 in
67+
}
68+
}
69+
}

0 commit comments

Comments
 (0)