@@ -3368,8 +3368,17 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3368
3368
}
3369
3369
3370
3370
void tryPostfixOperator (Expr *expr, PostfixOperatorDecl *op) {
3371
- if (!expr->getType ())
3371
+ auto Ty = expr->getType ();
3372
+ if (!Ty)
3372
3373
return ;
3374
+
3375
+ SWIFT_DEFER {
3376
+ // Restore type.
3377
+ // FIXME: This is workaround for getTypeOfExpressionWithoutApplying()
3378
+ // modifies type of 'expr'.
3379
+ expr->setType (Ty);
3380
+ };
3381
+
3373
3382
// We allocate these expressions on the stack because we know they can't
3374
3383
// escape and there isn't a better way to allocate scratch Expr nodes.
3375
3384
UnresolvedDeclRefExpr UDRE (op->getName (), DeclRefKind::PostfixOperator,
@@ -3444,6 +3453,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3444
3453
LHS->getType ()->is <AnyFunctionType>()))
3445
3454
return ;
3446
3455
3456
+ // Preserve LHS type for restoring it.
3457
+ Type LHSTy = LHS->getType ();
3458
+
3447
3459
// We allocate these expressions on the stack because we know they can't
3448
3460
// escape and there isn't a better way to allocate scratch Expr nodes.
3449
3461
UnresolvedDeclRefExpr UDRE (op->getName (), DeclRefKind::BinaryOperator,
@@ -3456,13 +3468,20 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3456
3468
// Reset sequence.
3457
3469
SE->setElement (SE->getNumElements () - 1 , nullptr );
3458
3470
SE->setElement (SE->getNumElements () - 2 , nullptr );
3471
+ LHS->setType (LHSTy);
3459
3472
prepareForRetypechecking (SE);
3460
3473
3461
- // Reset any references to operators in types, so they are properly
3462
- // handled as operators by sequence folding.
3463
- //
3464
- // FIXME: Would be better to have some kind of 'OperatorRefExpr'?
3465
3474
for (auto &element : sequence.drop_back (2 )) {
3475
+ // Unfold AssignExpr for re-typechecking sequence.
3476
+ if (auto *AE = dyn_cast_or_null<AssignExpr>(element)) {
3477
+ AE->setSrc (nullptr );
3478
+ AE->setDest (nullptr );
3479
+ }
3480
+
3481
+ // Reset any references to operators in types, so they are properly
3482
+ // handled as operators by sequence folding.
3483
+ //
3484
+ // FIXME: Would be better to have some kind of 'OperatorRefExpr'?
3466
3485
if (auto operatorRef = element->getMemberOperatorRef ()) {
3467
3486
operatorRef->setType (nullptr );
3468
3487
element = operatorRef;
@@ -3496,20 +3515,20 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3496
3515
}
3497
3516
}
3498
3517
3499
- void flattenBinaryExpr (BinaryExpr *expr, SmallVectorImpl<Expr *> &sequence) {
3500
- auto LHS = expr-> getArg ()-> getElement ( 0 );
3501
- if ( auto binexpr = dyn_cast<BinaryExpr>(LHS))
3502
- flattenBinaryExpr (binexpr, sequence);
3503
- else
3504
- sequence. push_back (LHS);
3505
-
3506
- sequence.push_back (expr-> getFn () );
3507
-
3508
- auto RHS = expr-> getArg ()-> getElement ( 1 );
3509
- if ( auto binexpr = dyn_cast<BinaryExpr>(RHS))
3510
- flattenBinaryExpr (binexpr, sequence);
3511
- else
3512
- sequence. push_back (RHS);
3518
+ void flattenBinaryExpr (Expr *expr, SmallVectorImpl<Expr *> &sequence) {
3519
+ if ( auto binExpr = dyn_cast<BinaryExpr>(expr)) {
3520
+ flattenBinaryExpr (binExpr-> getArg ()-> getElement ( 0 ), sequence);
3521
+ sequence. push_back (binExpr-> getFn () );
3522
+ flattenBinaryExpr (binExpr-> getArg ()-> getElement ( 1 ), sequence);
3523
+ } else if ( auto assignExpr = dyn_cast<AssignExpr>(expr)) {
3524
+ flattenBinaryExpr (assignExpr-> getDest (), sequence);
3525
+ sequence.push_back (assignExpr );
3526
+ flattenBinaryExpr (assignExpr-> getSrc (), sequence);
3527
+ assignExpr-> setDest ( nullptr );
3528
+ assignExpr-> setSrc ( nullptr );
3529
+ } else {
3530
+ sequence. push_back (expr);
3531
+ }
3513
3532
}
3514
3533
3515
3534
void typeCheckLeadingSequence (SmallVectorImpl<Expr *> &sequence) {
@@ -3519,10 +3538,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3519
3538
// Take advantage of the fact the type-checker leaves the types on the AST.
3520
3539
if (!typeCheckExpression (const_cast <DeclContext *>(CurrDeclContext),
3521
3540
expr)) {
3522
- if (auto binexpr = dyn_cast<BinaryExpr >(expr)) {
3541
+ if (isa<BinaryExpr>(expr) || isa<AssignExpr >(expr)) {
3523
3542
// Rebuild the sequence from the type-checked version.
3524
3543
sequence.clear ();
3525
- flattenBinaryExpr (binexpr , sequence);
3544
+ flattenBinaryExpr (expr , sequence);
3526
3545
return ;
3527
3546
}
3528
3547
}
@@ -3548,6 +3567,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3548
3567
if (sequence.size () > 1 )
3549
3568
typeCheckLeadingSequence (sequence);
3550
3569
3570
+ // Retrieve typechecked LHS.
3571
+ LHS = sequence.back ();
3572
+
3551
3573
// Create a single sequence expression, which we will modify for each
3552
3574
// operator, filling in the operator and dummy right-hand side.
3553
3575
sequence.push_back (nullptr ); // operator
0 commit comments