Skip to content

Commit 57ff839

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 898346f commit 57ff839

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
@@ -1138,14 +1138,12 @@ NOTE(candidate_expected_different_labels,none,
11381138
"incorrect labels for candidate (have: '%0', expected: '%1')",
11391139
(StringRef, StringRef))
11401140

1141+
ERROR(member_shadows_function,none,
1142+
"use of %0 refers to %1 rather than %2 %3",
1143+
(DeclNameRef, DescriptiveDeclKind, DescriptiveDeclKind, DeclName))
11411144
ERROR(member_shadows_global_function,none,
1142-
"use of %0 refers to %1 %2 rather than %3 %4 in %5 %6",
1143-
(DeclNameRef, DescriptiveDeclKind, DeclName, DescriptiveDeclKind,
1144-
DeclName, DescriptiveDeclKind, DeclName))
1145-
ERROR(member_shadows_global_function_near_match,none,
1146-
"use of %0 nearly matches %3 %4 in %5 %6 rather than %1 %2",
1147-
(DeclNameRef, DescriptiveDeclKind, DeclName, DescriptiveDeclKind,
1148-
DeclName, DescriptiveDeclKind, DeclName))
1145+
"use of %0 refers to %1 rather than %2 %3 in module %4",
1146+
(DeclNameRef, DescriptiveDeclKind, DescriptiveDeclKind, DeclName, DeclName))
11491147

11501148
ERROR(instance_member_use_on_type,none,
11511149
"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
@@ -6117,3 +6117,45 @@ bool UnableToInferProtocolLiteralType::diagnoseAsError() {
61176117

61186118
return true;
61196119
}
6120+
6121+
bool MissingQuialifierInMemberRefFailure::diagnoseAsError() {
6122+
auto selectedOverload = getOverloadChoiceIfAvailable(getLocator());
6123+
if (!selectedOverload)
6124+
return false;
6125+
6126+
auto *UDE = cast<UnresolvedDotExpr>(getRawAnchor());
6127+
6128+
auto baseType = getType(UDE->getBase());
6129+
6130+
auto methodKind = baseType->isAnyExistentialType()
6131+
? DescriptiveDeclKind::StaticMethod
6132+
: DescriptiveDeclKind::Method;
6133+
6134+
auto choice = selectedOverload->choice.getDeclOrNull();
6135+
if (!choice)
6136+
return false;
6137+
6138+
auto *DC = choice->getDeclContext();
6139+
if (!(DC->isModuleContext() || DC->isModuleScopeContext())) {
6140+
emitDiagnostic(UDE->getLoc(), diag::member_shadows_function, UDE->getName(),
6141+
methodKind, choice->getDescriptiveKind(),
6142+
choice->getFullName());
6143+
return true;
6144+
}
6145+
6146+
auto qualifier = DC->getParentModule()->getName();
6147+
6148+
emitDiagnostic(UDE->getLoc(), diag::member_shadows_global_function,
6149+
UDE->getName(), methodKind, choice->getDescriptiveKind(),
6150+
choice->getFullName(), qualifier);
6151+
6152+
SmallString<32> namePlusDot = qualifier.str();
6153+
namePlusDot.push_back('.');
6154+
6155+
emitDiagnostic(UDE->getLoc(), diag::fix_unqualified_access_top_level_multi,
6156+
namePlusDot, choice->getDescriptiveKind(), qualifier)
6157+
.fixItInsert(UDE->getStartLoc(), namePlusDot);
6158+
6159+
emitDiagnostic(choice, diag::decl_declared_here, choice->getFullName());
6160+
return true;
6161+
}

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
@@ -1182,7 +1182,9 @@ SpecifyObjectLiteralTypeImport::create(ConstraintSystem &cs,
11821182
}
11831183

11841184
bool AddQualifierToAccessTopLevelName::diagnose(bool asNote) const {
1185-
return false;
1185+
auto &cs = getConstraintSystem();
1186+
MissingQuialifierInMemberRefFailure failure(cs, getLocator());
1187+
return failure.diagnose(asNote);
11861188
}
11871189

11881190
AddQualifierToAccessTopLevelName *

0 commit comments

Comments
 (0)