Skip to content

Commit b65e3c9

Browse files
committed
Improve module selector @_dynamicReplacement diagnostics
1 parent 60cc537 commit b65e3c9

File tree

4 files changed

+66
-25
lines changed

4 files changed

+66
-25
lines changed

lib/Sema/TypeCheckAttr.cpp

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3889,6 +3889,23 @@ static void lookupReplacedDecl(DeclNameRef replacedDeclName,
38893889
results);
38903890
}
38913891

3892+
static bool
3893+
diagnoseCandidatesEliminatedByModuleSelector(ASTContext &ctx,
3894+
DeclNameRefWithLoc replacedDeclName,
3895+
DeclAttribute *attr,
3896+
const ValueDecl *replacement) {
3897+
if (!replacedDeclName.Name.hasModuleSelector())
3898+
return false;
3899+
3900+
// Look up without the module selector
3901+
SmallVector<ValueDecl *, 4> results;
3902+
lookupReplacedDecl(DeclNameRef(replacedDeclName.Name.getFullName()),
3903+
attr, replacement, results);
3904+
3905+
ModuleSelectorCorrection correction(results);
3906+
return correction.diagnose(ctx, replacedDeclName.Loc, replacedDeclName.Name);
3907+
}
3908+
38923909
/// Remove any argument labels from the interface type of the given value that
38933910
/// are extraneous from the type system's point of view, producing the
38943911
/// type to compare against for the purposes of dynamic replacement.
@@ -3908,14 +3925,14 @@ static Type getDynamicComparisonType(ValueDecl *value) {
39083925
return interfaceType->removeArgumentLabels(numArgumentLabels);
39093926
}
39103927

3911-
static FuncDecl *findSimilarAccessor(DeclNameRef replacedVarName,
3928+
static FuncDecl *findSimilarAccessor(DeclNameRefWithLoc replacedVarName,
39123929
const AccessorDecl *replacement,
39133930
DeclAttribute *attr, ASTContext &ctx,
39143931
bool forDynamicReplacement) {
39153932

39163933
// Retrieve the replaced abstract storage decl.
39173934
SmallVector<ValueDecl *, 4> results;
3918-
lookupReplacedDecl(replacedVarName, attr, replacement, results);
3935+
lookupReplacedDecl(replacedVarName.Name, attr, replacement, results);
39193936

39203937
// Filter out any accessors that won't work.
39213938
if (!results.empty()) {
@@ -3946,17 +3963,21 @@ static FuncDecl *findSimilarAccessor(DeclNameRef replacedVarName,
39463963

39473964
auto &Diags = ctx.Diags;
39483965
if (results.empty()) {
3949-
Diags.diagnose(attr->getLocation(),
3950-
diag::dynamic_replacement_accessor_not_found,
3951-
replacedVarName);
3966+
if (!diagnoseCandidatesEliminatedByModuleSelector(ctx, replacedVarName,
3967+
attr, replacement)) {
3968+
Diags.diagnose(attr->getLocation(),
3969+
diag::dynamic_replacement_accessor_not_found,
3970+
replacedVarName.Name);
3971+
}
39523972
attr->setInvalid();
3973+
39533974
return nullptr;
39543975
}
39553976

39563977
if (results.size() > 1) {
39573978
Diags.diagnose(attr->getLocation(),
39583979
diag::dynamic_replacement_accessor_ambiguous,
3959-
replacedVarName);
3980+
replacedVarName.Name);
39603981
for (auto result : results) {
39613982
Diags.diagnose(result,
39623983
diag::dynamic_replacement_accessor_ambiguous_candidate,
@@ -3998,15 +4019,15 @@ static FuncDecl *findSimilarAccessor(DeclNameRef replacedVarName,
39984019
return origAccessor;
39994020
}
40004021

4001-
static FuncDecl *findReplacedAccessor(DeclNameRef replacedVarName,
4022+
static FuncDecl *findReplacedAccessor(DeclNameRefWithLoc replacedVarName,
40024023
const AccessorDecl *replacement,
40034024
DeclAttribute *attr,
40044025
ASTContext &ctx) {
40054026
return findSimilarAccessor(replacedVarName, replacement, attr, ctx,
40064027
/*forDynamicReplacement*/ true);
40074028
}
40084029

4009-
static FuncDecl *findTargetAccessor(DeclNameRef replacedVarName,
4030+
static FuncDecl *findTargetAccessor(DeclNameRefWithLoc replacedVarName,
40104031
const AccessorDecl *replacement,
40114032
DeclAttribute *attr,
40124033
ASTContext &ctx) {
@@ -4015,15 +4036,15 @@ static FuncDecl *findTargetAccessor(DeclNameRef replacedVarName,
40154036
}
40164037

40174038
static AbstractFunctionDecl *
4018-
findSimilarFunction(DeclNameRef replacedFunctionName,
4039+
findSimilarFunction(DeclNameRefWithLoc replacedFunctionName,
40194040
const AbstractFunctionDecl *base, DeclAttribute *attr,
40204041
DiagnosticEngine *Diags, bool forDynamicReplacement) {
40214042

40224043
// Note: we might pass a constant attribute when typechecker is nullptr.
40234044
// Any modification to attr must be guarded by a null check on TC.
40244045
//
40254046
SmallVector<ValueDecl *, 4> lookupResults;
4026-
lookupReplacedDecl(replacedFunctionName, attr, base, lookupResults);
4047+
lookupReplacedDecl(replacedFunctionName.Name, attr, base, lookupResults);
40274048

40284049
SmallVector<AbstractFunctionDecl *, 4> candidates;
40294050
for (auto *result : lookupResults) {
@@ -4040,11 +4061,15 @@ findSimilarFunction(DeclNameRef replacedFunctionName,
40404061

40414062
if (candidates.empty()) {
40424063
if (Diags) {
4043-
Diags->diagnose(attr->getLocation(),
4044-
forDynamicReplacement
4045-
? diag::dynamic_replacement_function_not_found
4046-
: diag::specialize_target_function_not_found,
4047-
replacedFunctionName);
4064+
if (!diagnoseCandidatesEliminatedByModuleSelector(base->getASTContext(),
4065+
replacedFunctionName,
4066+
attr, base)) {
4067+
Diags->diagnose(attr->getLocation(),
4068+
forDynamicReplacement
4069+
? diag::dynamic_replacement_function_not_found
4070+
: diag::specialize_target_function_not_found,
4071+
replacedFunctionName.Name);
4072+
}
40484073
}
40494074

40504075
attr->setInvalid();
@@ -4110,7 +4135,7 @@ findSimilarFunction(DeclNameRef replacedFunctionName,
41104135
forDynamicReplacement
41114136
? diag::dynamic_replacement_function_of_type_not_found
41124137
: diag::specialize_target_function_of_type_not_found,
4113-
replacedFunctionName,
4138+
replacedFunctionName.Name,
41144139
base->getInterfaceType()->getCanonicalType());
41154140

41164141
for (auto *result : matches) {
@@ -4126,15 +4151,15 @@ findSimilarFunction(DeclNameRef replacedFunctionName,
41264151
}
41274152

41284153
static AbstractFunctionDecl *
4129-
findReplacedFunction(DeclNameRef replacedFunctionName,
4154+
findReplacedFunction(DeclNameRefWithLoc replacedFunctionName,
41304155
const AbstractFunctionDecl *replacement,
41314156
DynamicReplacementAttr *attr, DiagnosticEngine *Diags) {
41324157
return findSimilarFunction(replacedFunctionName, replacement, attr, Diags,
41334158
true /*forDynamicReplacement*/);
41344159
}
41354160

41364161
static AbstractFunctionDecl *
4137-
findTargetFunction(DeclNameRef targetFunctionName,
4162+
findTargetFunction(DeclNameRefWithLoc targetFunctionName,
41384163
const AbstractFunctionDecl *base,
41394164
AbstractSpecializeAttr * attr, DiagnosticEngine *diags) {
41404165
return findSimilarFunction(targetFunctionName, base, attr, diags,
@@ -5802,13 +5827,15 @@ DynamicallyReplacedDeclRequest::evaluate(Evaluator &evaluator,
58025827
}
58035828

58045829
auto &Ctx = VD->getASTContext();
5830+
DeclNameRefWithLoc nameWithLoc{attr->getReplacedFunctionName(),
5831+
attr->getReplacedFunctionNameLoc(),
5832+
std::nullopt};
58055833
if (auto *AD = dyn_cast<AccessorDecl>(VD)) {
5806-
return findReplacedAccessor(attr->getReplacedFunctionName(), AD, attr, Ctx);
5834+
return findReplacedAccessor(nameWithLoc, AD, attr, Ctx);
58075835
}
58085836

58095837
if (auto *AFD = dyn_cast<AbstractFunctionDecl>(VD)) {
5810-
return findReplacedFunction(attr->getReplacedFunctionName(), AFD,
5811-
attr, &Ctx.Diags);
5838+
return findReplacedFunction(nameWithLoc, AFD, attr, &Ctx.Diags);
58125839
}
58135840

58145841
if (auto *SD = dyn_cast<AbstractStorageDecl>(VD)) {
@@ -5831,8 +5858,10 @@ SpecializeAttrTargetDeclRequest::evaluate(Evaluator &evaluator,
58315858

58325859
auto &ctx = vd->getASTContext();
58335860

5834-
auto targetFunctionName = attr->getTargetFunctionName();
5835-
if (!targetFunctionName)
5861+
DeclNameRefWithLoc targetFunctionName{attr->getTargetFunctionName(),
5862+
attr->getTargetFunctionNameLoc(),
5863+
std::nullopt};
5864+
if (!targetFunctionName.Name)
58365865
return nullptr;
58375866

58385867
if (auto *ad = dyn_cast<AccessorDecl>(vd)) {

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,15 @@ ModuleSelectorCorrection(const LookupTypeResult &candidates) {
11911191
}
11921192
}
11931193

1194+
ModuleSelectorCorrection::
1195+
ModuleSelectorCorrection(const SmallVectorImpl<ValueDecl *> &candidates) {
1196+
for (auto result : candidates) {
1197+
auto owningModule = result->getModuleContext();
1198+
candidateModules.insert(
1199+
{ owningModule->getName(), CandidateKind::ContextFree });
1200+
}
1201+
}
1202+
11941203
bool ModuleSelectorCorrection::diagnose(ASTContext &ctx,
11951204
DeclNameLoc nameLoc,
11961205
DeclNameRef originalName) const {

lib/Sema/TypeChecker.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ class ModuleSelectorCorrection {
331331
public:
332332
ModuleSelectorCorrection(const LookupResult &candidates);
333333
ModuleSelectorCorrection(const LookupTypeResult &candidates);
334+
ModuleSelectorCorrection(const SmallVectorImpl<ValueDecl *> &candidates);
334335

335336
/// Emit an error and warnings if there were any candidates.
336337
///

test/NameLookup/module_selector.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ extension B: @retroactive main::Equatable {
9595
// @_derivative(of:)
9696

9797
@_dynamicReplacement(for: main::negate())
98-
// FIXME improve: expected-error@-1 {{replaced function 'main::negate()' could not be found}}
98+
// expected-error@-1 {{'negate()' is not imported through module 'main'}}
99+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{29-33=ModuleSelectorTestingKit}}
99100

100101
mutating func myNegate() {
101102
let fn: (main::Int, main::Int) -> main::Int =
@@ -260,7 +261,8 @@ extension D: @retroactive Swift::Equatable {
260261
// @_derivative(of:)
261262

262263
@_dynamicReplacement(for: Swift::negate())
263-
// FIXME improve: expected-error@-1 {{replaced function 'Swift::negate()' could not be found}}
264+
// expected-error@-1 {{'negate()' is not imported through module 'Swift'}}
265+
// expected-note@-2 {{did you mean module 'ModuleSelectorTestingKit'?}} {{29-34=ModuleSelectorTestingKit}}
264266

265267
mutating func myNegate() {
266268
// expected-note@-1 {{'myNegate()' declared here}}

0 commit comments

Comments
 (0)