Skip to content

Commit c728c2a

Browse files
committed
Sema: Simplify doesStorageProduceLValue()
1 parent 6c02529 commit c728c2a

File tree

2 files changed

+47
-65
lines changed

2 files changed

+47
-65
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,14 +2075,6 @@ struct ClosureIsolatedByPreconcurrency {
20752075
bool operator()(const ClosureExpr *expr) const;
20762076
};
20772077

2078-
/// Determine whether the given expression is part of the left-hand side
2079-
/// of an assignment expression.
2080-
struct IsInLeftHandSideOfAssignment {
2081-
ConstraintSystem &cs;
2082-
2083-
bool operator()(Expr *expr) const;
2084-
};
2085-
20862078
/// Describes the type produced when referencing a declaration.
20872079
struct DeclReferenceType {
20882080
/// The "opened" type, which is the type of the declaration where any

lib/Sema/TypeOfReference.cpp

Lines changed: 47 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -411,18 +411,57 @@ FunctionType *ConstraintSystem::openFunctionType(
411411
return funcType->castTo<FunctionType>();
412412
}
413413

414+
static bool isInLeftHandSideOfAssignment(ConstraintSystem &cs, Expr *expr) {
415+
// Walk up the parent tree.
416+
auto parent = cs.getParentExpr(expr);
417+
if (!parent)
418+
return false;
419+
420+
// If the parent is an assignment expression, check whether we are
421+
// the left-hand side.
422+
if (auto assignParent = dyn_cast<AssignExpr>(parent)) {
423+
return expr == assignParent->getDest();
424+
}
425+
426+
// Always look up through these parent kinds.
427+
if (isa<TupleExpr>(parent) || isa<IdentityExpr>(parent) ||
428+
isa<AnyTryExpr>(parent) || isa<BindOptionalExpr>(parent)) {
429+
return isInLeftHandSideOfAssignment(cs, parent);
430+
}
431+
432+
// If the parent is a lookup expression, only follow from the base.
433+
if (auto lookupParent = dyn_cast<LookupExpr>(parent)) {
434+
if (lookupParent->getBase() == expr)
435+
return isInLeftHandSideOfAssignment(cs, parent);
414436

437+
// The expression wasn't in the base, so this isn't part of the
438+
// left-hand side.
439+
return false;
440+
}
441+
442+
// If the parent is an unresolved member reference a.b, only follow
443+
// from the base.
444+
if (auto dotParent = dyn_cast<UnresolvedDotExpr>(parent)) {
445+
if (dotParent->getBase() == expr)
446+
return isInLeftHandSideOfAssignment(cs, parent);
447+
448+
// The expression wasn't in the base, so this isn't part of the
449+
// left-hand side.
450+
return false;
451+
}
452+
453+
return false;
454+
}
415455

416456
/// Does a var or subscript produce an l-value?
417457
///
418458
/// \param baseType - the type of the base on which this object
419459
/// is being accessed; must be null if and only if this is not
420460
/// a type member
421-
static bool
422-
doesStorageProduceLValue(
461+
static bool doesStorageProduceLValue(
423462
AbstractStorageDecl *storage, Type baseType,
424463
DeclContext *useDC,
425-
llvm::function_ref<bool(Expr *)> isAssignTarget,
464+
ConstraintSystem &cs,
426465
ConstraintLocator *locator) {
427466
const DeclRefExpr *base = nullptr;
428467
if (locator) {
@@ -456,7 +495,7 @@ doesStorageProduceLValue(
456495

457496
// If the anchor isn't known to be the target of an assignment,
458497
// treat as immutable.
459-
if (!isAssignTarget(anchor))
498+
if (!isInLeftHandSideOfAssignment(cs, anchor))
460499
return false;
461500

462501
break;
@@ -541,9 +580,7 @@ Type ConstraintSystem::getUnopenedTypeOfReference(
541580

542581
// Qualify storage declarations with an lvalue when appropriate.
543582
// Otherwise, they yield rvalues (and the access must be a load).
544-
if (doesStorageProduceLValue(value, baseType, UseDC,
545-
IsInLeftHandSideOfAssignment{*this},
546-
locator) &&
583+
if (doesStorageProduceLValue(value, baseType, UseDC, *this, locator) &&
547584
!requestedType->hasError()) {
548585
return LValueType::get(requestedType);
549586
}
@@ -1391,48 +1428,6 @@ Type ConstraintSystem::getMemberReferenceTypeFromOpenedType(
13911428
return type;
13921429
}
13931430

1394-
bool IsInLeftHandSideOfAssignment::operator()(Expr *expr) const {
1395-
// Walk up the parent tree.
1396-
auto parent = cs.getParentExpr(expr);
1397-
if (!parent)
1398-
return false;
1399-
1400-
// If the parent is an assignment expression, check whether we are
1401-
// the left-hand side.
1402-
if (auto assignParent = dyn_cast<AssignExpr>(parent)) {
1403-
return expr == assignParent->getDest();
1404-
}
1405-
1406-
// Always look up through these parent kinds.
1407-
if (isa<TupleExpr>(parent) || isa<IdentityExpr>(parent) ||
1408-
isa<AnyTryExpr>(parent) || isa<BindOptionalExpr>(parent)) {
1409-
return (*this)(parent);
1410-
}
1411-
1412-
// If the parent is a lookup expression, only follow from the base.
1413-
if (auto lookupParent = dyn_cast<LookupExpr>(parent)) {
1414-
if (lookupParent->getBase() == expr)
1415-
return (*this)(parent);
1416-
1417-
// The expression wasn't in the base, so this isn't part of the
1418-
// left-hand side.
1419-
return false;
1420-
}
1421-
1422-
// If the parent is an unresolved member reference a.b, only follow
1423-
// from the base.
1424-
if (auto dotParent = dyn_cast<UnresolvedDotExpr>(parent)) {
1425-
if (dotParent->getBase() == expr)
1426-
return (*this)(parent);
1427-
1428-
// The expression wasn't in the base, so this isn't part of the
1429-
// left-hand side.
1430-
return false;
1431-
}
1432-
1433-
return false;
1434-
}
1435-
14361431
DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
14371432
Type baseTy, ValueDecl *value, DeclContext *useDC, bool isDynamicLookup,
14381433
FunctionRefKind functionRefKind, ConstraintLocator *locator,
@@ -1535,9 +1530,7 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
15351530
if (auto *subscript = dyn_cast<SubscriptDecl>(value)) {
15361531
auto elementTy = subscript->getElementInterfaceType();
15371532

1538-
if (doesStorageProduceLValue(
1539-
subscript, baseTy, useDC,
1540-
IsInLeftHandSideOfAssignment{*this}, locator))
1533+
if (doesStorageProduceLValue(subscript, baseTy, useDC, *this, locator))
15411534
elementTy = LValueType::get(elementTy);
15421535

15431536
auto indices = subscript->getInterfaceType()
@@ -1791,9 +1784,7 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator,
17911784
auto elementTy = subscript->getElementInterfaceType();
17921785

17931786
if (doesStorageProduceLValue(subscript, overload.getBaseType(),
1794-
useDC,
1795-
IsInLeftHandSideOfAssignment{*this},
1796-
locator))
1787+
useDC, *this, locator))
17971788
elementTy = LValueType::get(elementTy);
17981789
else if (elementTy->hasDynamicSelfType()) {
17991790
elementTy = withDynamicSelfResultReplaced(elementTy,
@@ -1818,8 +1809,7 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator,
18181809
} else if (auto var = dyn_cast<VarDecl>(decl)) {
18191810
type = var->getValueInterfaceType();
18201811
if (doesStorageProduceLValue(
1821-
var, overload.getBaseType(), useDC,
1822-
IsInLeftHandSideOfAssignment{*this}, locator)) {
1812+
var, overload.getBaseType(), useDC, *this, locator)) {
18231813
type = LValueType::get(type);
18241814
} else if (type->hasDynamicSelfType()) {
18251815
type = withDynamicSelfResultReplaced(type, /*uncurryLevel=*/0);

0 commit comments

Comments
 (0)