mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
SILGen: Open existential lvalues on entry into an OpenExistentialExpr again.
4b25945 changed codegen for lvalue OpenExistentialExprs so that the existential was not opened until the OpaqueValue's lvalue was evaluated, but this is incorrect—we need to open the dynamic type of the existential immediately since it can be used arbitrarily within the subexpression. This caused a regression when evaluating default argument generators on protocol extension methods (rdar://problem/37031037), and would become a bigger problem when we generalize the ability to open existentials.
This commit is contained in:
@@ -5090,15 +5090,34 @@ RValue RValueEmitter::emitForceValue(ForceValueExpr *loc, Expr *E,
|
||||
void SILGenFunction::emitOpenExistentialExprImpl(
|
||||
OpenExistentialExpr *E,
|
||||
llvm::function_ref<void(Expr *)> emitSubExpr) {
|
||||
Optional<FormalEvaluationScope> writebackScope;
|
||||
|
||||
// Emit the existential value.
|
||||
if (E->getExistentialValue()->getType()->is<LValueType>()) {
|
||||
bool inserted = OpaqueValueExprs.insert({E->getOpaqueValue(), E}).second;
|
||||
// Open the existential container right away. We need the dynamic type
|
||||
// to be opened in order to evaluate the subexpression.
|
||||
AccessKind accessKind;
|
||||
if (E->hasLValueAccessKind())
|
||||
accessKind = E->getLValueAccessKind();
|
||||
else
|
||||
accessKind = E->getExistentialValue()->getLValueAccessKind();
|
||||
auto lv = emitLValue(E->getExistentialValue(), accessKind);
|
||||
auto formalOpenedType = E->getOpaqueValue()->getType()
|
||||
->getWithoutSpecifierType()
|
||||
->getCanonicalType();
|
||||
lv = emitOpenExistentialLValue(E, std::move(lv),
|
||||
CanArchetypeType(E->getOpenedArchetype()),
|
||||
formalOpenedType,
|
||||
accessKind);
|
||||
|
||||
auto addr = emitAddressOfLValue(E, std::move(lv), accessKind);
|
||||
bool inserted = OpaqueLValues.insert({E->getOpaqueValue(),
|
||||
{addr.getValue(), formalOpenedType}})
|
||||
.second;
|
||||
(void)inserted;
|
||||
assert(inserted && "already have this opened existential?");
|
||||
|
||||
emitSubExpr(E->getSubExpr());
|
||||
assert(OpaqueLValues.count(E->getOpaqueValue()) == 0
|
||||
&& "opened existential not removed?");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5125,6 +5144,12 @@ RValue RValueEmitter::visitOpenExistentialExpr(OpenExistentialExpr *E,
|
||||
return RValue(SGF, E, *result);
|
||||
}
|
||||
|
||||
Optional<FormalEvaluationScope> scope;
|
||||
// Begin an evaluation scope for an lvalue existential opened into an
|
||||
// rvalue expression.
|
||||
if (E->getExistentialValue()->getType()->is<LValueType>())
|
||||
scope.emplace(SGF);
|
||||
|
||||
return SGF.emitOpenExistentialExpr<RValue>(E,
|
||||
[&](Expr *subExpr) -> RValue {
|
||||
return visit(subExpr, C);
|
||||
|
||||
Reference in New Issue
Block a user