@@ -411,18 +411,57 @@ FunctionType *ConstraintSystem::openFunctionType(
411
411
return funcType->castTo <FunctionType>();
412
412
}
413
413
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);
414
436
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
+ }
415
455
416
456
// / Does a var or subscript produce an l-value?
417
457
// /
418
458
// / \param baseType - the type of the base on which this object
419
459
// / is being accessed; must be null if and only if this is not
420
460
// / a type member
421
- static bool
422
- doesStorageProduceLValue (
461
+ static bool doesStorageProduceLValue (
423
462
AbstractStorageDecl *storage, Type baseType,
424
463
DeclContext *useDC,
425
- llvm::function_ref< bool (Expr *)> isAssignTarget ,
464
+ ConstraintSystem &cs ,
426
465
ConstraintLocator *locator) {
427
466
const DeclRefExpr *base = nullptr ;
428
467
if (locator) {
@@ -456,7 +495,7 @@ doesStorageProduceLValue(
456
495
457
496
// If the anchor isn't known to be the target of an assignment,
458
497
// treat as immutable.
459
- if (!isAssignTarget ( anchor))
498
+ if (!isInLeftHandSideOfAssignment (cs, anchor))
460
499
return false ;
461
500
462
501
break ;
@@ -541,9 +580,7 @@ Type ConstraintSystem::getUnopenedTypeOfReference(
541
580
542
581
// Qualify storage declarations with an lvalue when appropriate.
543
582
// 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) &&
547
584
!requestedType->hasError ()) {
548
585
return LValueType::get (requestedType);
549
586
}
@@ -1391,48 +1428,6 @@ Type ConstraintSystem::getMemberReferenceTypeFromOpenedType(
1391
1428
return type;
1392
1429
}
1393
1430
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
-
1436
1431
DeclReferenceType ConstraintSystem::getTypeOfMemberReference (
1437
1432
Type baseTy, ValueDecl *value, DeclContext *useDC, bool isDynamicLookup,
1438
1433
FunctionRefKind functionRefKind, ConstraintLocator *locator,
@@ -1535,9 +1530,7 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
1535
1530
if (auto *subscript = dyn_cast<SubscriptDecl>(value)) {
1536
1531
auto elementTy = subscript->getElementInterfaceType ();
1537
1532
1538
- if (doesStorageProduceLValue (
1539
- subscript, baseTy, useDC,
1540
- IsInLeftHandSideOfAssignment{*this }, locator))
1533
+ if (doesStorageProduceLValue (subscript, baseTy, useDC, *this , locator))
1541
1534
elementTy = LValueType::get (elementTy);
1542
1535
1543
1536
auto indices = subscript->getInterfaceType ()
@@ -1791,9 +1784,7 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator,
1791
1784
auto elementTy = subscript->getElementInterfaceType ();
1792
1785
1793
1786
if (doesStorageProduceLValue (subscript, overload.getBaseType (),
1794
- useDC,
1795
- IsInLeftHandSideOfAssignment{*this },
1796
- locator))
1787
+ useDC, *this , locator))
1797
1788
elementTy = LValueType::get (elementTy);
1798
1789
else if (elementTy->hasDynamicSelfType ()) {
1799
1790
elementTy = withDynamicSelfResultReplaced (elementTy,
@@ -1818,8 +1809,7 @@ Type ConstraintSystem::getEffectiveOverloadType(ConstraintLocator *locator,
1818
1809
} else if (auto var = dyn_cast<VarDecl>(decl)) {
1819
1810
type = var->getValueInterfaceType ();
1820
1811
if (doesStorageProduceLValue (
1821
- var, overload.getBaseType (), useDC,
1822
- IsInLeftHandSideOfAssignment{*this }, locator)) {
1812
+ var, overload.getBaseType (), useDC, *this , locator)) {
1823
1813
type = LValueType::get (type);
1824
1814
} else if (type->hasDynamicSelfType ()) {
1825
1815
type = withDynamicSelfResultReplaced (type, /* uncurryLevel=*/ 0 );
0 commit comments