Skip to content

Commit 37d05ea

Browse files
committed
Improved handling of mixed lvalues & rvalues in tuple exprs
My previous commit here didn’t work correctly for nested tuples, both because it didn’t recurse into them to propagate access kind correctly and because an outer TupleIndex overload (when indexing into the nested tuple) could still be expecting an lvalue type. This fix is much better. ConstraintSystem::resolveOverload now correctly always expects rvalue types from rvalue tuples. And during applyMemberRefExpr, if the overload expects an rvalue but the tuple contains lvalues, coerceToType() correctly does any recursive munging of the tuple expr required.
1 parent e0c028d commit 37d05ea

File tree

3 files changed

+14
-28
lines changed

3 files changed

+14
-28
lines changed

lib/Sema/CSApply.cpp

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2416,35 +2416,16 @@ namespace {
24162416

24172417
Type toType = simplifyType(expr->getType());
24182418

2419-
// Don't allow lvalues when indexing into a tuple expr.
2420-
// If we get any lvalues, add load exprs to convert the tuple to be all rvalues.
2421-
if (auto *tupleExpr = dyn_cast<TupleExpr>(base)) {
2422-
unsigned count = tupleExpr->getNumElements();
2423-
unsigned lvalues = 0;
2424-
auto &tc = cs.getTypeChecker();
2425-
SmallVector<TupleTypeElt, 4> tupleElts;
2426-
for (unsigned i = 0; i < count; i++) {
2427-
Expr *elementExpr = tupleExpr->getElement(i);
2428-
Type elementType = elementExpr->getType();
2429-
if (elementType->isLValueType()) {
2430-
lvalues++;
2431-
elementExpr->propagateLValueAccessKind(AccessKind::Read, true);
2432-
elementExpr = new (tc.Context) LoadExpr(elementExpr, elementType->getRValueType());
2433-
tupleExpr->setElement(i, elementExpr);
2434-
}
2435-
tupleElts.push_back(elementExpr->getType());
2436-
}
2437-
2438-
if (lvalues > 0) {
2439-
auto &Context = tupleExpr->getType()->getASTContext();
2440-
tupleExpr->setType(TupleType::get(tupleElts, Context));
2441-
toType = toType->getRValueType();
2442-
}
2443-
}
2419+
// If the result type is an rvalue and the base contains lvalues, need a full
2420+
// tuple coercion to properly load & set access kind on all underlying elements
2421+
// before taking a single element.
2422+
baseTy = base->getType();
2423+
if (!toType->isLValueType() && baseTy->isLValueType())
2424+
base = coerceToType(base, baseTy->getRValueType(), cs.getConstraintLocator(base));
24442425

24452426
return new (cs.getASTContext()) TupleElementExpr(base, dotLoc,
2446-
selected.choice.getTupleIndex(),
2447-
nameLoc.getBaseNameLoc(), toType);
2427+
selected.choice.getTupleIndex(),
2428+
nameLoc.getBaseNameLoc(), toType);
24482429
}
24492430

24502431
case OverloadChoiceKind::BaseType: {
@@ -4834,6 +4815,9 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
48344815
}
48354816

48364817
case ConversionRestrictionKind::LValueToRValue: {
4818+
if (toType->is<TupleType>() || fromType->is<TupleType>())
4819+
break;
4820+
48374821
// Load from the lvalue.
48384822
expr->propagateLValueAccessKind(AccessKind::Read);
48394823
expr = new (tc.Context) LoadExpr(expr, fromType->getRValueType());

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1385,7 +1385,7 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
13851385
} else {
13861386
// When the base is a tuple rvalue, the member is always an rvalue.
13871387
auto tuple = choice.getBaseType()->castTo<TupleType>();
1388-
refType = tuple->getElementType(choice.getTupleIndex());
1388+
refType = tuple->getElementType(choice.getTupleIndex())->getRValueType();
13891389
}
13901390
break;
13911391
}

test/expr/expressions.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,3 +842,5 @@ let _ = (x, 3).1
842842
(x,y) = (2,3)
843843
(x,4) = (1,2) // expected-error {{cannot assign to value: function call returns immutable value}}
844844
(x,y).1 = 7 // expected-error {{cannot assign to immutable expression of type 'Int'}}
845+
x = (x,(3,y)).1.1
846+

0 commit comments

Comments
 (0)