Skip to content

Commit c9c20af

Browse files
committed
[Diagnostics] Port name shadowing diagnostics
Diagnose an attempt to reference a top-level name shadowed by a local member e.g. ```swift extension Sequence { func test() -> Int { return max(1, 2) } } ``` Here `min` refers to a global function `min<T>(_: T, _: T)` in `Swift` module and can only be accessed by adding `Swift.` to it, because `Sequence` has a member named `min` which accepts a single argument.
1 parent 7351bfc commit c9c20af

File tree

4 files changed

+73
-8
lines changed

4 files changed

+73
-8
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,14 +1153,12 @@ NOTE(candidate_expected_different_labels,none,
11531153
"incorrect labels for candidate (have: '%0', expected: '%1')",
11541154
(StringRef, StringRef))
11551155

1156+
ERROR(member_shadows_function,none,
1157+
"use of %0 refers to %1 rather than %2 %3",
1158+
(DeclNameRef, DescriptiveDeclKind, DescriptiveDeclKind, DeclName))
11561159
ERROR(member_shadows_global_function,none,
1157-
"use of %0 refers to %1 %2 rather than %3 %4 in %5 %6",
1158-
(DeclNameRef, DescriptiveDeclKind, DeclName, DescriptiveDeclKind,
1159-
DeclName, DescriptiveDeclKind, DeclName))
1160-
ERROR(member_shadows_global_function_near_match,none,
1161-
"use of %0 nearly matches %3 %4 in %5 %6 rather than %1 %2",
1162-
(DeclNameRef, DescriptiveDeclKind, DeclName, DescriptiveDeclKind,
1163-
DeclName, DescriptiveDeclKind, DeclName))
1160+
"use of %0 refers to %1 rather than %2 %3 in module %4",
1161+
(DeclNameRef, DescriptiveDeclKind, DescriptiveDeclKind, DeclName, DeclName))
11641162

11651163
ERROR(instance_member_use_on_type,none,
11661164
"instance member %1 cannot be used on type %0; "

lib/Sema/CSDiagnostics.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6137,3 +6137,45 @@ bool UnableToInferProtocolLiteralType::diagnoseAsError() {
61376137

61386138
return true;
61396139
}
6140+
6141+
bool MissingQuialifierInMemberRefFailure::diagnoseAsError() {
6142+
auto selectedOverload = getOverloadChoiceIfAvailable(getLocator());
6143+
if (!selectedOverload)
6144+
return false;
6145+
6146+
auto *UDE = cast<UnresolvedDotExpr>(getRawAnchor());
6147+
6148+
auto baseType = getType(UDE->getBase());
6149+
6150+
auto methodKind = baseType->isAnyExistentialType()
6151+
? DescriptiveDeclKind::StaticMethod
6152+
: DescriptiveDeclKind::Method;
6153+
6154+
auto choice = selectedOverload->choice.getDeclOrNull();
6155+
if (!choice)
6156+
return false;
6157+
6158+
auto *DC = choice->getDeclContext();
6159+
if (!(DC->isModuleContext() || DC->isModuleScopeContext())) {
6160+
emitDiagnostic(UDE->getLoc(), diag::member_shadows_function, UDE->getName(),
6161+
methodKind, choice->getDescriptiveKind(),
6162+
choice->getFullName());
6163+
return true;
6164+
}
6165+
6166+
auto qualifier = DC->getParentModule()->getName();
6167+
6168+
emitDiagnostic(UDE->getLoc(), diag::member_shadows_global_function,
6169+
UDE->getName(), methodKind, choice->getDescriptiveKind(),
6170+
choice->getFullName(), qualifier);
6171+
6172+
SmallString<32> namePlusDot = qualifier.str();
6173+
namePlusDot.push_back('.');
6174+
6175+
emitDiagnostic(UDE->getLoc(), diag::fix_unqualified_access_top_level_multi,
6176+
namePlusDot, choice->getDescriptiveKind(), qualifier)
6177+
.fixItInsert(UDE->getStartLoc(), namePlusDot);
6178+
6179+
emitDiagnostic(choice, diag::decl_declared_here, choice->getFullName());
6180+
return true;
6181+
}

lib/Sema/CSDiagnostics.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1936,6 +1936,29 @@ class UnableToInferProtocolLiteralType final : public FailureDiagnostic {
19361936
bool diagnoseAsError();
19371937
};
19381938

1939+
/// Diagnose an attempt to reference a top-level name shadowed by a local
1940+
/// member e.g.
1941+
///
1942+
/// ```swift
1943+
/// extension Sequence {
1944+
/// func test() -> Int {
1945+
/// return max(1, 2)
1946+
/// }
1947+
/// }
1948+
/// ```
1949+
///
1950+
/// Here `min` refers to a global function `min<T>(_: T, _: T)` in `Swift`
1951+
/// module and can only be accessed by adding `Swift.` to it, because `Sequence`
1952+
/// has a member named `min` which accepts a single argument.
1953+
class MissingQuialifierInMemberRefFailure final : public FailureDiagnostic {
1954+
public:
1955+
MissingQuialifierInMemberRefFailure(ConstraintSystem &cs,
1956+
ConstraintLocator *locator)
1957+
: FailureDiagnostic(cs, locator) {}
1958+
1959+
bool diagnoseAsError();
1960+
};
1961+
19391962
} // end namespace constraints
19401963
} // end namespace swift
19411964

lib/Sema/CSFix.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,9 @@ AllowNonClassTypeToConvertToAnyObject::create(ConstraintSystem &cs, Type type,
12191219
}
12201220

12211221
bool AddQualifierToAccessTopLevelName::diagnose(bool asNote) const {
1222-
return false;
1222+
auto &cs = getConstraintSystem();
1223+
MissingQuialifierInMemberRefFailure failure(cs, getLocator());
1224+
return failure.diagnose(asNote);
12231225
}
12241226

12251227
AddQualifierToAccessTopLevelName *

0 commit comments

Comments
 (0)