Skip to content

Commit 9a1d252

Browse files
committed
[silgen] When transforming values into an existential box representation, do it at +1.
In general, SILGen assumes that only +1 values are "forwarded" into memory. This is because we want any value that is stored in memory to not be dependent on other values and for the forwarded object to be able to maintain its own liveness. So this assert was correct to fire. The specific test case that exposed this issue is: What happened here is that we needed to reabstract a loadable value into an existential and tried to maximally abstract it and thus store it into memory. The That code was never updated to make sure the value was at +1. So we would store a guaranteed value into memory and hope that whereever we stored it doesn't escape the current function. In this case, I believe that we would be safe... but past returns are not indicators of future results. rdar://40773543 SR-7858 (cherry picked from commit d2e1bcd)
1 parent 52ee4ff commit 9a1d252

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

lib/SILGen/SILGenConvert.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ ManagedValue SILGenFunction::emitExistentialErasure(
726726
ExistentialRepresentation::Boxed, *this);
727727
ManagedValue mv = F(SGFContext(&init));
728728
if (!mv.isInContext()) {
729-
mv.forwardInto(*this, loc, init.getAddress());
729+
mv.ensurePlusOne(*this, loc).forwardInto(*this, loc, init.getAddress());
730730
init.finishInitialization(*this);
731731
}
732732

test/SILGen/function_conversion.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,3 +641,27 @@ func rdar35702810_anyhashable() {
641641
// CHECK: convert_escape_to_noescape [not_guaranteed] [[PA]] : $@callee_guaranteed (@guaranteed Set<B>) -> () to $@noescape @callee_guaranteed (@guaranteed Set<B>) -> ()
642642
bar_set(type: B.self, fn_set)
643643
}
644+
645+
// ==== Function conversion with parameter substToOrig reabstraction.
646+
647+
struct FunctionConversionParameterSubstToOrigReabstractionTest {
648+
typealias SelfTy = FunctionConversionParameterSubstToOrigReabstractionTest
649+
650+
class Klass: Error {}
651+
652+
struct Foo<T> {
653+
static func enum1Func(_ : (T) -> Foo<Error>) -> Foo<Error> {
654+
// Just to make it compile.
655+
return Optional<Foo<Error>>.none!
656+
}
657+
}
658+
659+
static func bar<T>(t: T) -> Foo<T> {
660+
// Just to make it compile.
661+
return Optional<Foo<T>>.none!
662+
}
663+
664+
static func testFunc() -> Foo<Error> {
665+
return Foo<Klass>.enum1Func(SelfTy.bar)
666+
}
667+
}

0 commit comments

Comments
 (0)