Skip to content

Commit 1f91f12

Browse files
committed
[Sema] Tweak resolveDeclRefExpr handling
Sink forbidden prefix and `init` recovery into `resolveDeclRefExpr`, and move diagnosis of `self` in an `init` accessor into the pre-checking post-walk such that it applies to any DeclRefExpr.
1 parent 8804d6a commit 1f91f12

File tree

1 file changed

+34
-40
lines changed

1 file changed

+34
-40
lines changed

lib/Sema/PreCheckExpr.cpp

Lines changed: 34 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -484,10 +484,26 @@ diagnoseUnqualifiedInit(UnresolvedDeclRefExpr *initExpr, DeclContext *dc,
484484
/// for the lookup.
485485
Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
486486
DeclContext *DC) {
487-
// Process UnresolvedDeclRefExpr by doing an unqualified lookup.
487+
auto &Context = DC->getASTContext();
488488
DeclNameRef Name = UDRE->getName();
489489
SourceLoc Loc = UDRE->getLoc();
490490

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.
491507
DeclNameRef LookupName = Name;
492508
if (Name.isCompoundName()) {
493509
auto &context = DC->getASTContext();
@@ -507,12 +523,6 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
507523
LookupName = DeclNameRef(lookupName);
508524
}
509525

510-
auto &Context = DC->getASTContext();
511-
512-
auto errorResult = [&]() -> Expr * {
513-
return new (Context) ErrorExpr(UDRE->getSourceRange());
514-
};
515-
516526
// Perform standard value name lookup.
517527
NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
518528
// TODO: Include all of the possible members to give a solver a
@@ -1208,38 +1218,8 @@ namespace {
12081218
return finish(true, expr);
12091219
}
12101220

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-
}
1221+
if (auto *unresolved = dyn_cast<UnresolvedDeclRefExpr>(expr))
1222+
return finish(true, TypeChecker::resolveDeclRefExpr(unresolved, DC));
12431223

12441224
// Let's try to figure out if `InOutExpr` is out of place early
12451225
// otherwise there is a risk of producing solutions which can't
@@ -1328,7 +1308,21 @@ namespace {
13281308
if (auto *typeExpr = simplifyUnresolvedSpecializeExpr(us))
13291309
return Action::Continue(typeExpr);
13301310
}
1331-
1311+
1312+
// Check whether this is standalone `self` in init accessor, which
1313+
// is invalid.
1314+
if (auto *DRE = dyn_cast<DeclRefExpr>(expr)) {
1315+
if (auto *accessor = DC->getInnermostPropertyAccessorContext()) {
1316+
if (accessor->isInitAccessor() &&
1317+
accessor->getImplicitSelfDecl() == DRE->getDecl() &&
1318+
!isa_and_nonnull<UnresolvedDotExpr>(Parent.getAsExpr())) {
1319+
Ctx.Diags.diagnose(DRE->getLoc(),
1320+
diag::invalid_use_of_self_in_init_accessor);
1321+
return Action::Continue(new (Ctx) ErrorExpr(DRE->getSourceRange()));
1322+
}
1323+
}
1324+
}
1325+
13321326
// If we're about to step out of a ClosureExpr, restore the DeclContext.
13331327
if (auto *ce = dyn_cast<ClosureExpr>(expr)) {
13341328
assert(DC == ce && "DeclContext imbalance");

0 commit comments

Comments
 (0)