@@ -3268,8 +3268,17 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3268
3268
}
3269
3269
3270
3270
void tryPostfixOperator (Expr *expr, PostfixOperatorDecl *op) {
3271
- if (!expr->getType ())
3271
+ auto Ty = expr->getType ();
3272
+ if (!Ty)
3272
3273
return ;
3274
+
3275
+ SWIFT_DEFER {
3276
+ // Restore type.
3277
+ // FIXME: This is workaround for getTypeOfExpressionWithoutApplying()
3278
+ // modifies type of 'expr'.
3279
+ expr->setType (Ty);
3280
+ };
3281
+
3273
3282
// We allocate these expressions on the stack because we know they can't
3274
3283
// escape and there isn't a better way to allocate scratch Expr nodes.
3275
3284
UnresolvedDeclRefExpr UDRE (op->getName (), DeclRefKind::PostfixOperator,
@@ -3344,6 +3353,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3344
3353
LHS->getType ()->is <AnyFunctionType>()))
3345
3354
return ;
3346
3355
3356
+ // Preserve LHS type for restoring it.
3357
+ Type LHSTy = LHS->getType ();
3358
+
3347
3359
// We allocate these expressions on the stack because we know they can't
3348
3360
// escape and there isn't a better way to allocate scratch Expr nodes.
3349
3361
UnresolvedDeclRefExpr UDRE (op->getName (), DeclRefKind::BinaryOperator,
@@ -3356,13 +3368,20 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3356
3368
// Reset sequence.
3357
3369
SE->setElement (SE->getNumElements () - 1 , nullptr );
3358
3370
SE->setElement (SE->getNumElements () - 2 , nullptr );
3371
+ LHS->setType (LHSTy);
3359
3372
prepareForRetypechecking (SE);
3360
3373
3361
- // Reset any references to operators in types, so they are properly
3362
- // handled as operators by sequence folding.
3363
- //
3364
- // FIXME: Would be better to have some kind of 'OperatorRefExpr'?
3365
3374
for (auto &element : sequence.drop_back (2 )) {
3375
+ // Unfold AssignExpr for re-typechecking sequence.
3376
+ if (auto *AE = dyn_cast_or_null<AssignExpr>(element)) {
3377
+ AE->setSrc (nullptr );
3378
+ AE->setDest (nullptr );
3379
+ }
3380
+
3381
+ // Reset any references to operators in types, so they are properly
3382
+ // handled as operators by sequence folding.
3383
+ //
3384
+ // FIXME: Would be better to have some kind of 'OperatorRefExpr'?
3366
3385
if (auto operatorRef = element->getMemberOperatorRef ()) {
3367
3386
operatorRef->setType (nullptr );
3368
3387
element = operatorRef;
@@ -3396,20 +3415,20 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3396
3415
}
3397
3416
}
3398
3417
3399
- void flattenBinaryExpr (BinaryExpr *expr, SmallVectorImpl<Expr *> &sequence) {
3400
- auto LHS = expr-> getArg ()-> getElement ( 0 );
3401
- if ( auto binexpr = dyn_cast<BinaryExpr>(LHS))
3402
- flattenBinaryExpr (binexpr, sequence);
3403
- else
3404
- sequence. push_back (LHS);
3405
-
3406
- sequence.push_back (expr-> getFn () );
3407
-
3408
- auto RHS = expr-> getArg ()-> getElement ( 1 );
3409
- if ( auto binexpr = dyn_cast<BinaryExpr>(RHS))
3410
- flattenBinaryExpr (binexpr, sequence);
3411
- else
3412
- sequence. push_back (RHS);
3418
+ void flattenBinaryExpr (Expr *expr, SmallVectorImpl<Expr *> &sequence) {
3419
+ if ( auto binExpr = dyn_cast<BinaryExpr>(expr)) {
3420
+ flattenBinaryExpr (binExpr-> getArg ()-> getElement ( 0 ), sequence);
3421
+ sequence. push_back (binExpr-> getFn () );
3422
+ flattenBinaryExpr (binExpr-> getArg ()-> getElement ( 1 ), sequence);
3423
+ } else if ( auto assignExpr = dyn_cast<AssignExpr>(expr)) {
3424
+ flattenBinaryExpr (assignExpr-> getDest (), sequence);
3425
+ sequence.push_back (assignExpr );
3426
+ flattenBinaryExpr (assignExpr-> getSrc (), sequence);
3427
+ assignExpr-> setDest ( nullptr );
3428
+ assignExpr-> setSrc ( nullptr );
3429
+ } else {
3430
+ sequence. push_back (expr);
3431
+ }
3413
3432
}
3414
3433
3415
3434
void typeCheckLeadingSequence (SmallVectorImpl<Expr *> &sequence) {
@@ -3419,10 +3438,10 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3419
3438
// Take advantage of the fact the type-checker leaves the types on the AST.
3420
3439
if (!typeCheckExpression (const_cast <DeclContext *>(CurrDeclContext),
3421
3440
expr)) {
3422
- if (auto binexpr = dyn_cast<BinaryExpr >(expr)) {
3441
+ if (isa<BinaryExpr>(expr) || isa<AssignExpr >(expr)) {
3423
3442
// Rebuild the sequence from the type-checked version.
3424
3443
sequence.clear ();
3425
- flattenBinaryExpr (binexpr , sequence);
3444
+ flattenBinaryExpr (expr , sequence);
3426
3445
return ;
3427
3446
}
3428
3447
}
@@ -3448,6 +3467,9 @@ class CompletionLookup final : public swift::VisibleDeclConsumer {
3448
3467
if (sequence.size () > 1 )
3449
3468
typeCheckLeadingSequence (sequence);
3450
3469
3470
+ // Retrieve typechecked LHS.
3471
+ LHS = sequence.back ();
3472
+
3451
3473
// Create a single sequence expression, which we will modify for each
3452
3474
// operator, filling in the operator and dummy right-hand side.
3453
3475
sequence.push_back (nullptr ); // operator
0 commit comments