Skip to content

Commit 6139c49

Browse files
committed
Merge pull request #1150 from gregomni/tuple-element-lvalue
[SR-628][Sema] Improved handling of mixed lvalues & rvalues in tuple exprs
2 parents e0c028d + 37d05ea commit 6139c49

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)