Skip to content

Commit fa6b731

Browse files
committed
[MiscDiagnostics] Produce warnings about confusable self iff its explicit
Restrict the warning to diagnose only explicit instances of `self` reference that do not mention the parent type via dot syntax e.g. `MyStruct.self`. Resolves: SR-15897 Resolves: SR-15691 Resolves: rdar://90624344 (cherry picked from commit e52c3a0)
1 parent ef7e22c commit fa6b731

File tree

2 files changed

+40
-23
lines changed

2 files changed

+40
-23
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4717,31 +4717,43 @@ static void diagUnqualifiedAccessToMethodNamedSelf(const Expr *E,
47174717
if (!E || isa<ErrorExpr>(E) || !E->getType())
47184718
return {false, E};
47194719

4720-
if (auto *declRefExpr = dyn_cast<DeclRefExpr>(E)) {
4721-
if (declRefExpr->getDecl()->getBaseName() == Ctx.Id_self &&
4722-
declRefExpr->getType()->is<AnyFunctionType>()) {
4723-
if (auto typeContext = DC->getInnermostTypeContext()) {
4724-
// self() is not easily confusable
4725-
if (!isa<CallExpr>(Parent.getAsExpr())) {
4726-
auto baseType = typeContext->getDeclaredInterfaceType();
4727-
if (!baseType->getEnumOrBoundGenericEnum()) {
4728-
auto baseTypeString = baseType.getString();
4729-
4730-
Ctx.Diags.diagnose(E->getLoc(), diag::self_refers_to_method,
4731-
baseTypeString);
4732-
4733-
Ctx.Diags
4734-
.diagnose(E->getLoc(),
4735-
diag::fix_unqualified_access_member_named_self,
4736-
baseTypeString)
4737-
.fixItInsert(E->getLoc(), diag::insert_type_qualification,
4738-
baseType);
4739-
}
4740-
}
4741-
}
4742-
}
4720+
auto *DRE = dyn_cast<DeclRefExpr>(E);
4721+
// If this is not an explicit 'self' reference, let's keep searching.
4722+
if (!DRE || DRE->isImplicit())
4723+
return {true, E};
4724+
4725+
// If this not 'self' or it's not a function reference, it's unrelated.
4726+
if (!(DRE->getDecl()->getBaseName() == Ctx.Id_self &&
4727+
DRE->getType()->is<AnyFunctionType>()))
4728+
return {true, E};
4729+
4730+
auto typeContext = DC->getInnermostTypeContext();
4731+
// Use of 'self' in enums is not confusable.
4732+
if (!typeContext || typeContext->getSelfEnumDecl())
4733+
return {true, E};
4734+
4735+
// self(...) is not easily confusable.
4736+
if (auto *parentExpr = Parent.getAsExpr()) {
4737+
if (isa<CallExpr>(parentExpr))
4738+
return {true, E};
4739+
4740+
// Explicit call to a static method 'self' of some type is not
4741+
// confusable.
4742+
if (isa<DotSyntaxCallExpr>(parentExpr) && !parentExpr->isImplicit())
4743+
return {true, E};
47434744
}
47444745

4746+
auto baseType = typeContext->getDeclaredInterfaceType();
4747+
auto baseTypeString = baseType.getString();
4748+
4749+
Ctx.Diags.diagnose(E->getLoc(), diag::self_refers_to_method,
4750+
baseTypeString);
4751+
4752+
Ctx.Diags
4753+
.diagnose(E->getLoc(), diag::fix_unqualified_access_member_named_self,
4754+
baseTypeString)
4755+
.fixItInsert(E->getLoc(), diag::insert_type_qualification, baseType);
4756+
47454757
return {true, E};
47464758
}
47474759
};

test/Parse/self_rebinding.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,3 +126,8 @@ enum EnumCaseNamedSelf {
126126
self = EnumCaseNamedSelf.`self` // OK
127127
}
128128
}
129+
130+
// rdar://90624344 - warning about `self` which cannot be fixed because it's located in implicitly generated code.
131+
struct TestImplicitSelfUse : Codable {
132+
let `self`: Int // Ok
133+
}

0 commit comments

Comments
 (0)