@@ -402,15 +402,108 @@ static BinaryExpr *getCompositionExpr(Expr *expr) {
402
402
return nullptr ;
403
403
}
404
404
405
+ // / Diagnoses an unqualified `init` expression.
406
+ // /
407
+ // / \param initExpr The \c init expression.
408
+ // / \param dc The declaration context of \p initExpr.
409
+ // /
410
+ // / \returns An expression matching `self.init` or `super.init` that can be used
411
+ // / to recover, or `nullptr` if cannot recover.
412
+ static UnresolvedDotExpr *
413
+ diagnoseUnqualifiedInit (UnresolvedDeclRefExpr *initExpr, DeclContext *dc,
414
+ ASTContext &ctx) {
415
+ const auto loc = initExpr->getLoc ();
416
+
417
+ enum class Suggestion : unsigned {
418
+ None = 0 ,
419
+ Self = 1 ,
420
+ Super = 2 ,
421
+ };
422
+
423
+ Suggestion suggestion = [dc]() {
424
+ NominalTypeDecl *nominal = nullptr ;
425
+ {
426
+ auto *typeDC = dc->getInnermostTypeContext ();
427
+ if (!typeDC) {
428
+ // No type context--no suggestion.
429
+ return Suggestion::None;
430
+ }
431
+
432
+ nominal = typeDC->getSelfNominalTypeDecl ();
433
+ }
434
+
435
+ auto *classDecl = dyn_cast<ClassDecl>(nominal);
436
+ if (!classDecl || !classDecl->hasSuperclass ()) {
437
+ // No class or no superclass--suggest 'self.'.
438
+ return Suggestion::Self;
439
+ }
440
+
441
+ if (auto *initDecl = dyn_cast<ConstructorDecl>(dc)) {
442
+ if (initDecl->getAttrs ().hasAttribute <ConvenienceAttr>()) {
443
+ // Innermost context is a convenience initializer--suggest 'self.'.
444
+ return Suggestion::Self;
445
+ } else {
446
+ // Innermost context is a designated initializer--suggest 'super.'.
447
+ return Suggestion::Super;
448
+ }
449
+ }
450
+
451
+ // Class context but innermost context is not an initializer--suggest
452
+ // 'self.'. 'super.' might be possible too, but is far lesss likely to be
453
+ // the right answer.
454
+ return Suggestion::Self;
455
+ }();
456
+
457
+ auto diag =
458
+ ctx.Diags .diagnose (loc, diag::unqualified_init, (unsigned )suggestion);
459
+
460
+ Expr *base = nullptr ;
461
+ switch (suggestion) {
462
+ case Suggestion::None:
463
+ return nullptr ;
464
+ case Suggestion::Self:
465
+ diag.fixItInsert (loc, " self." );
466
+ base = new (ctx)
467
+ UnresolvedDeclRefExpr (DeclNameRef (ctx.Id_self ), DeclRefKind::Ordinary,
468
+ initExpr->getNameLoc ());
469
+ base->setImplicit (true );
470
+ break ;
471
+ case Suggestion::Super:
472
+ diag.fixItInsert (loc, " super." );
473
+ base = new (ctx) SuperRefExpr (/* Self=*/ nullptr , loc, /* Implicit=*/ true );
474
+ break ;
475
+ }
476
+
477
+ return new (ctx)
478
+ UnresolvedDotExpr (base, /* dotloc=*/ SourceLoc (), initExpr->getName (),
479
+ initExpr->getNameLoc (), /* implicit=*/ true );
480
+ }
481
+
405
482
// / Bind an UnresolvedDeclRefExpr by performing name lookup and
406
483
// / returning the resultant expression. Context is the DeclContext used
407
484
// / for the lookup.
408
485
Expr *TypeChecker::resolveDeclRefExpr (UnresolvedDeclRefExpr *UDRE,
409
486
DeclContext *DC) {
410
- // Process UnresolvedDeclRefExpr by doing an unqualified lookup.
487
+ auto &Context = DC-> getASTContext ();
411
488
DeclNameRef Name = UDRE->getName ();
412
489
SourceLoc Loc = UDRE->getLoc ();
413
490
491
+ auto errorResult = [&]() -> Expr * {
492
+ return new (Context) ErrorExpr (UDRE->getSourceRange ());
493
+ };
494
+
495
+ TypeChecker::checkForForbiddenPrefix (Context, Name.getBaseName ());
496
+
497
+ // Try and recover if we have an unqualified 'init'.
498
+ if (Name.getBaseName ().isConstructor ()) {
499
+ auto *recoveryExpr = diagnoseUnqualifiedInit (UDRE, DC, Context);
500
+ if (!recoveryExpr)
501
+ return errorResult ();
502
+
503
+ return recoveryExpr;
504
+ }
505
+
506
+ // Process UnresolvedDeclRefExpr by doing an unqualified lookup.
414
507
DeclNameRef LookupName = Name;
415
508
if (Name.isCompoundName ()) {
416
509
auto &context = DC->getASTContext ();
@@ -430,12 +523,6 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
430
523
LookupName = DeclNameRef (lookupName);
431
524
}
432
525
433
- auto &Context = DC->getASTContext ();
434
-
435
- auto errorResult = [&]() -> Expr * {
436
- return new (Context) ErrorExpr (UDRE->getSourceRange ());
437
- };
438
-
439
526
// Perform standard value name lookup.
440
527
NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
441
528
// TODO: Include all of the possible members to give a solver a
@@ -867,83 +954,6 @@ TypeChecker::getSelfForInitDelegationInConstructor(DeclContext *DC,
867
954
return nullptr ;
868
955
}
869
956
870
- // / Diagnoses an unqualified `init` expression.
871
- // /
872
- // / \param initExpr The \c init expression.
873
- // / \param dc The declaration context of \p initExpr.
874
- // /
875
- // / \returns An expression matching `self.init` or `super.init` that can be used
876
- // / to recover, or `nullptr` if cannot recover.
877
- static UnresolvedDotExpr *
878
- diagnoseUnqualifiedInit (UnresolvedDeclRefExpr *initExpr, DeclContext *dc,
879
- ASTContext &ctx) {
880
- const auto loc = initExpr->getLoc ();
881
-
882
- enum class Suggestion : unsigned {
883
- None = 0 ,
884
- Self = 1 ,
885
- Super = 2 ,
886
- };
887
-
888
- Suggestion suggestion = [dc]() {
889
- NominalTypeDecl *nominal = nullptr ;
890
- {
891
- auto *typeDC = dc->getInnermostTypeContext ();
892
- if (!typeDC) {
893
- // No type context--no suggestion.
894
- return Suggestion::None;
895
- }
896
-
897
- nominal = typeDC->getSelfNominalTypeDecl ();
898
- }
899
-
900
- auto *classDecl = dyn_cast<ClassDecl>(nominal);
901
- if (!classDecl || !classDecl->hasSuperclass ()) {
902
- // No class or no superclass--suggest 'self.'.
903
- return Suggestion::Self;
904
- }
905
-
906
- if (auto *initDecl = dyn_cast<ConstructorDecl>(dc)) {
907
- if (initDecl->getAttrs ().hasAttribute <ConvenienceAttr>()) {
908
- // Innermost context is a convenience initializer--suggest 'self.'.
909
- return Suggestion::Self;
910
- } else {
911
- // Innermost context is a designated initializer--suggest 'super.'.
912
- return Suggestion::Super;
913
- }
914
- }
915
-
916
- // Class context but innermost context is not an initializer--suggest
917
- // 'self.'. 'super.' might be possible too, but is far lesss likely to be
918
- // the right answer.
919
- return Suggestion::Self;
920
- }();
921
-
922
- auto diag =
923
- ctx.Diags .diagnose (loc, diag::unqualified_init, (unsigned )suggestion);
924
-
925
- Expr *base = nullptr ;
926
- switch (suggestion) {
927
- case Suggestion::None:
928
- return nullptr ;
929
- case Suggestion::Self:
930
- diag.fixItInsert (loc, " self." );
931
- base = new (ctx)
932
- UnresolvedDeclRefExpr (DeclNameRef (ctx.Id_self ), DeclRefKind::Ordinary,
933
- initExpr->getNameLoc ());
934
- base->setImplicit (true );
935
- break ;
936
- case Suggestion::Super:
937
- diag.fixItInsert (loc, " super." );
938
- base = new (ctx) SuperRefExpr (/* Self=*/ nullptr , loc, /* Implicit=*/ true );
939
- break ;
940
- }
941
-
942
- return new (ctx)
943
- UnresolvedDotExpr (base, /* dotloc=*/ SourceLoc (), initExpr->getName (),
944
- initExpr->getNameLoc (), /* implicit=*/ true );
945
- }
946
-
947
957
namespace {
948
958
// / Update the function reference kind based on adding a direct call to a
949
959
// / callee with this kind.
@@ -1046,9 +1056,6 @@ namespace {
1046
1056
// / Keep track of acceptable DiscardAssignmentExpr's.
1047
1057
llvm::SmallPtrSet<DiscardAssignmentExpr*, 2 > CorrectDiscardAssignmentExprs;
1048
1058
1049
- // / The current number of nested \c SequenceExprs that we're within.
1050
- unsigned SequenceExprDepth = 0 ;
1051
-
1052
1059
// / The current number of nested \c SingleValueStmtExprs that we're within.
1053
1060
unsigned SingleValueStmtExprDepth = 0 ;
1054
1061
@@ -1117,6 +1124,16 @@ namespace {
1117
1124
PreWalkResult<Expr *> walkToExprPre (Expr *expr) override {
1118
1125
auto &diags = Ctx.Diags ;
1119
1126
1127
+ // Fold sequence expressions.
1128
+ if (auto *seqExpr = dyn_cast<SequenceExpr>(expr)) {
1129
+ auto result = TypeChecker::foldSequence (seqExpr, DC);
1130
+ result = result->walk (*this );
1131
+ if (!result)
1132
+ return Action::Stop ();
1133
+ // Already walked.
1134
+ return Action::SkipNode (result);
1135
+ }
1136
+
1120
1137
// FIXME(diagnostics): `InOutType` could appear here as a result
1121
1138
// of successful re-typecheck of the one of the sub-expressions e.g.
1122
1139
// `let _: Int = { (s: inout S) in s.bar() }`. On the first
@@ -1148,11 +1165,9 @@ namespace {
1148
1165
return Action::Stop ();
1149
1166
1150
1167
// If we're going to recurse, record this expression on the stack.
1151
- if (recursive) {
1152
- if (isa<SequenceExpr>(expr))
1153
- SequenceExprDepth++;
1168
+ if (recursive)
1154
1169
ExprStack.push_back (expr);
1155
- }
1170
+
1156
1171
return Action::VisitNodeIf (recursive, expr);
1157
1172
};
1158
1173
@@ -1208,38 +1223,8 @@ namespace {
1208
1223
return finish (true , expr);
1209
1224
}
1210
1225
1211
- if (auto unresolved = dyn_cast<UnresolvedDeclRefExpr>(expr)) {
1212
- TypeChecker::checkForForbiddenPrefix (
1213
- getASTContext (), unresolved->getName ().getBaseName ());
1214
-
1215
- if (unresolved->getName ().getBaseName ().isConstructor ()) {
1216
- if (auto *recoveryExpr =
1217
- diagnoseUnqualifiedInit (unresolved, DC, Ctx)) {
1218
- return finish (true , recoveryExpr);
1219
- }
1220
-
1221
- return finish (false ,
1222
- new (Ctx) ErrorExpr (unresolved->getSourceRange ()));
1223
- }
1224
-
1225
- auto *refExpr = TypeChecker::resolveDeclRefExpr (unresolved, DC);
1226
-
1227
- // Check whether this is standalone `self` in init accessor, which
1228
- // is invalid.
1229
- if (auto *accessor = DC->getInnermostPropertyAccessorContext ()) {
1230
- if (accessor->isInitAccessor () && isa<DeclRefExpr>(refExpr)) {
1231
- auto *DRE = cast<DeclRefExpr>(refExpr);
1232
- if (accessor->getImplicitSelfDecl () == DRE->getDecl () &&
1233
- !isa_and_nonnull<UnresolvedDotExpr>(Parent.getAsExpr ())) {
1234
- diags.diagnose (unresolved->getLoc (),
1235
- diag::invalid_use_of_self_in_init_accessor);
1236
- refExpr = new (Ctx) ErrorExpr (unresolved->getSourceRange ());
1237
- }
1238
- }
1239
- }
1240
-
1241
- return finish (true , refExpr);
1242
- }
1226
+ if (auto *unresolved = dyn_cast<UnresolvedDeclRefExpr>(expr))
1227
+ return finish (true , TypeChecker::resolveDeclRefExpr (unresolved, DC));
1243
1228
1244
1229
// Let's try to figure out if `InOutExpr` is out of place early
1245
1230
// otherwise there is a risk of producing solutions which can't
@@ -1312,23 +1297,26 @@ namespace {
1312
1297
assert (ExprStack.back () == expr);
1313
1298
ExprStack.pop_back ();
1314
1299
1315
- // Fold sequence expressions.
1316
- if (auto *seqExpr = dyn_cast<SequenceExpr>(expr)) {
1317
- auto result = TypeChecker::foldSequence (seqExpr, DC);
1318
- SequenceExprDepth--;
1319
- result = result->walk (*this );
1320
- if (!result)
1321
- return Action::Stop ();
1322
-
1323
- return Action::Continue (result);
1324
- }
1325
-
1326
1300
// Type check the type parameters in an UnresolvedSpecializeExpr.
1327
1301
if (auto *us = dyn_cast<UnresolvedSpecializeExpr>(expr)) {
1328
1302
if (auto *typeExpr = simplifyUnresolvedSpecializeExpr (us))
1329
1303
return Action::Continue (typeExpr);
1330
1304
}
1331
-
1305
+
1306
+ // Check whether this is standalone `self` in init accessor, which
1307
+ // is invalid.
1308
+ if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
1309
+ if (auto *accessor = DC->getInnermostPropertyAccessorContext ()) {
1310
+ if (accessor->isInitAccessor () &&
1311
+ accessor->getImplicitSelfDecl () == DRE->getDecl () &&
1312
+ !isa_and_nonnull<UnresolvedDotExpr>(Parent.getAsExpr ())) {
1313
+ Ctx.Diags .diagnose (DRE->getLoc (),
1314
+ diag::invalid_use_of_self_in_init_accessor);
1315
+ return Action::Continue (new (Ctx) ErrorExpr (DRE->getSourceRange ()));
1316
+ }
1317
+ }
1318
+ }
1319
+
1332
1320
// If we're about to step out of a ClosureExpr, restore the DeclContext.
1333
1321
if (auto *ce = dyn_cast<ClosureExpr>(expr)) {
1334
1322
assert (DC == ce && " DeclContext imbalance" );
@@ -1432,12 +1420,9 @@ namespace {
1432
1420
return Action::Continue (simplified);
1433
1421
1434
1422
// Diagnose a '_' that isn't on the immediate LHS of an assignment. We
1435
- // skip diagnostics if we've explicitly marked the expression as valid,
1436
- // or if we're inside a SequenceExpr (since the whole tree will be
1437
- // re-checked when we finish folding anyway).
1423
+ // skip diagnostics if we've explicitly marked the expression as valid.
1438
1424
if (auto *DAE = dyn_cast<DiscardAssignmentExpr>(expr)) {
1439
- if (!CorrectDiscardAssignmentExprs.count (DAE) &&
1440
- SequenceExprDepth == 0 ) {
1425
+ if (!CorrectDiscardAssignmentExprs.count (DAE)) {
1441
1426
ctx.Diags .diagnose (expr->getLoc (),
1442
1427
diag::discard_expr_outside_of_assignment);
1443
1428
return Action::Stop ();
@@ -1694,7 +1679,7 @@ bool PreCheckExpression::possiblyInTypeContext(Expr *E) {
1694
1679
// / been explicitly marked as correct, and the current AST state allows it.
1695
1680
bool PreCheckExpression::canSimplifyDiscardAssignmentExpr (
1696
1681
DiscardAssignmentExpr *DAE) {
1697
- return !CorrectDiscardAssignmentExprs.count (DAE) && SequenceExprDepth == 0 &&
1682
+ return !CorrectDiscardAssignmentExprs.count (DAE) &&
1698
1683
possiblyInTypeContext (DAE);
1699
1684
}
1700
1685
0 commit comments