@@ -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.
@@ -1209,19 +1219,6 @@ namespace {
1209
1219
}
1210
1220
1211
1221
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
1222
auto *refExpr = TypeChecker::resolveDeclRefExpr (unresolved, DC);
1226
1223
1227
1224
// Check whether this is standalone `self` in init accessor, which
0 commit comments