@@ -251,9 +251,15 @@ getImplicitMemberReferenceAccessSemantics(Expr *base, VarDecl *member,
251
251
return member->getAccessSemanticsFromContext (DC);
252
252
}
253
253
254
- void ConstraintSystem::propagateLValueAccessKind (Expr *E,
255
- AccessKind accessKind ,
254
+ void ConstraintSystem::propagateLValueAccessKind (Expr *E, AccessKind accessKind,
255
+ bool isShallow ,
256
256
bool allowOverwrite) {
257
+ // If solver is set up in "shallow" mode we expect that some of the
258
+ // sub-expressions are already type-checked which means that they
259
+ // already have access kind set.
260
+ if (isShallow && E->hasLValueAccessKind () && !allowOverwrite)
261
+ return ;
262
+
257
263
E->propagateLValueAccessKind (accessKind,
258
264
[&](Expr *E) -> Type {
259
265
return getType (E);
@@ -434,6 +440,7 @@ namespace {
434
440
DeclContext *dc;
435
441
const Solution &solution;
436
442
bool SuppressDiagnostics;
443
+ bool IsShallow;
437
444
438
445
// / Recognize used conformances from an imported type when we must emit
439
446
// / the witness table.
@@ -885,7 +892,8 @@ namespace {
885
892
// will handle this.
886
893
if (record.OpaqueValue && record.OpaqueValue ->hasLValueAccessKind ())
887
894
cs.propagateLValueAccessKind (record.ExistentialValue ,
888
- record.OpaqueValue ->getLValueAccessKind ());
895
+ record.OpaqueValue ->getLValueAccessKind (),
896
+ IsShallow);
889
897
890
898
// Form the open-existential expression.
891
899
result = new (tc.Context ) OpenExistentialExpr (
@@ -1846,9 +1854,9 @@ namespace {
1846
1854
1847
1855
public:
1848
1856
ExprRewriter (ConstraintSystem &cs, const Solution &solution,
1849
- bool suppressDiagnostics)
1850
- : cs(cs), dc(cs.DC), solution(solution),
1851
- SuppressDiagnostics(suppressDiagnostics) { }
1857
+ bool suppressDiagnostics, bool shallow = false )
1858
+ : cs(cs), dc(cs.DC), solution(solution),
1859
+ SuppressDiagnostics(suppressDiagnostics), IsShallow(shallow) { }
1852
1860
1853
1861
ConstraintSystem &getConstraintSystem () const { return cs; }
1854
1862
@@ -3095,7 +3103,8 @@ namespace {
3095
3103
// case (when we turn the inout into an UnsafePointer) than to try to
3096
3104
// discover that we're in that case right now.
3097
3105
if (!cs.getType (expr->getSubExpr ())->is <UnresolvedType>())
3098
- cs.propagateLValueAccessKind (expr->getSubExpr (), AccessKind::ReadWrite);
3106
+ cs.propagateLValueAccessKind (expr->getSubExpr (), AccessKind::ReadWrite,
3107
+ IsShallow);
3099
3108
auto objectTy = cs.getType (expr->getSubExpr ())->getRValueType ();
3100
3109
3101
3110
// The type is simply inout of whatever the lvalue's object type was.
@@ -3805,7 +3814,8 @@ namespace {
3805
3814
auto destTy = cs.computeAssignDestType (expr->getDest (), expr->getLoc ());
3806
3815
if (!destTy)
3807
3816
return nullptr ;
3808
- cs.propagateLValueAccessKind (expr->getDest (), AccessKind::Write);
3817
+ cs.propagateLValueAccessKind (expr->getDest (), AccessKind::Write,
3818
+ IsShallow);
3809
3819
3810
3820
// Convert the source to the simplified destination type.
3811
3821
auto locator =
@@ -4114,7 +4124,7 @@ namespace {
4114
4124
4115
4125
if (cs.getType (subExpr)->hasLValueType ()) {
4116
4126
// Treat this like a read of the property.
4117
- cs.propagateLValueAccessKind (subExpr, AccessKind::Read);
4127
+ cs.propagateLValueAccessKind (subExpr, AccessKind::Read, IsShallow );
4118
4128
}
4119
4129
4120
4130
// Check that we requested a property getter or setter.
@@ -6341,7 +6351,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6341
6351
6342
6352
// Load from the lvalue. If we're loading the result of a force,
6343
6353
// swap the order so that we load first and force the result.
6344
- cs.propagateLValueAccessKind (expr, AccessKind::Read);
6354
+ cs.propagateLValueAccessKind (expr, AccessKind::Read, IsShallow );
6345
6355
if (auto *forceExpr = dyn_cast<ForceValueExpr>(expr)) {
6346
6356
fromType = cs.getType (forceExpr->getSubExpr ())->getRValueType ();
6347
6357
auto *loadExpr = cs.cacheType (
@@ -6450,8 +6460,8 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6450
6460
// Overwrite the l-value access kind to be read-only if we're
6451
6461
// converting to a non-mutable pointer type.
6452
6462
auto *E = cast<InOutExpr>(expr->getValueProvidingExpr ())->getSubExpr ();
6453
- cs.propagateLValueAccessKind (E,
6454
- AccessKind::Read, /* overwrite*/ true );
6463
+ cs.propagateLValueAccessKind (E, AccessKind::Read, IsShallow,
6464
+ /* overwrite*/ true );
6455
6465
}
6456
6466
6457
6467
tc.requirePointerArgumentIntrinsics (expr->getLoc ());
@@ -6554,7 +6564,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6554
6564
// In an 'inout' operator like "i += 1", the operand is converted from
6555
6565
// an implicit lvalue to an inout argument.
6556
6566
assert (toIO->getObjectType ()->isEqual (fromLValue->getObjectType ()));
6557
- cs.propagateLValueAccessKind (expr, AccessKind::ReadWrite);
6567
+ cs.propagateLValueAccessKind (expr, AccessKind::ReadWrite, IsShallow );
6558
6568
return cs.cacheType (new (tc.Context )
6559
6569
InOutExpr (expr->getStartLoc (), expr,
6560
6570
toIO->getObjectType (),
@@ -6573,7 +6583,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType,
6573
6583
6574
6584
if (performLoad) {
6575
6585
// Load from the lvalue.
6576
- cs.propagateLValueAccessKind (expr, AccessKind::Read);
6586
+ cs.propagateLValueAccessKind (expr, AccessKind::Read, IsShallow );
6577
6587
expr = cs.cacheType (new (tc.Context )
6578
6588
LoadExpr (expr, fromLValue->getObjectType ()));
6579
6589
@@ -6830,7 +6840,7 @@ ExprRewriter::coerceObjectArgumentToType(Expr *expr,
6830
6840
6831
6841
// Use InOutExpr to convert it to an explicit inout argument for the
6832
6842
// receiver.
6833
- cs.propagateLValueAccessKind (expr, AccessKind::ReadWrite);
6843
+ cs.propagateLValueAccessKind (expr, AccessKind::ReadWrite, IsShallow );
6834
6844
return cs.cacheType (new (ctx) InOutExpr (expr->getStartLoc (), expr,
6835
6845
toInOutTy->getInOutObjectType (),
6836
6846
/* isImplicit*/ true ));
@@ -8003,7 +8013,7 @@ Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr,
8003
8013
Expr *ConstraintSystem::applySolutionShallow (const Solution &solution,
8004
8014
Expr *expr,
8005
8015
bool suppressDiagnostics) {
8006
- ExprRewriter rewriter (*this , solution, suppressDiagnostics);
8016
+ ExprRewriter rewriter (*this , solution, suppressDiagnostics, true );
8007
8017
rewriter.walkToExprPre (expr);
8008
8018
Expr *result = rewriter.walkToExprPost (expr);
8009
8019
if (result)
0 commit comments