Skip to content

Tighten up @objc optional near-miss detection heuristics. #5367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 19, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions lib/Sema/TypeCheckProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4479,12 +4479,13 @@ combineBaseNameAndFirstArgument(Identifier baseName,
/// Compute the scope between two potentially-matching names, which is
/// effectively the sum of the edit distances between the corresponding
/// argument labels.
static unsigned scorePotentiallyMatchingNames(DeclName lhs, DeclName rhs,
bool isFunc,
unsigned limit) {
static Optional<unsigned> scorePotentiallyMatchingNames(DeclName lhs,
DeclName rhs,
bool isFunc,
unsigned limit) {
// If there are a different number of argument labels, we're done.
if (lhs.getArgumentNames().size() != rhs.getArgumentNames().size())
return limit;
return None;

// Score the base name match. If there is a first argument for a
// function, include its text along with the base name's text.
Expand All @@ -4506,14 +4507,14 @@ static unsigned scorePotentiallyMatchingNames(DeclName lhs, DeclName rhs,

score = lhsFirstName.edit_distance(rhsFirstName.str(), true, limit);
}
if (score >= limit) return limit;
if (score > limit) return None;

// Compute the edit distance between matching argument names.
for (unsigned i = isFunc ? 1 : 0; i < lhs.getArgumentNames().size(); ++i) {
score += scoreIdentifiers(lhs.getArgumentNames()[i],
rhs.getArgumentNames()[i],
limit - score);
if (score >= limit) return limit;
if (score > limit) return None;
}

return score;
Expand All @@ -4532,8 +4533,10 @@ static Optional<DeclName> omitNeedlessWords(TypeChecker &tc, ValueDecl *value) {
}

/// Determine the score between two potentially-matching declarations.
static unsigned scorePotentiallyMatching(TypeChecker &tc, ValueDecl *req,
ValueDecl *witness, unsigned limit) {
static Optional<unsigned> scorePotentiallyMatching(TypeChecker &tc,
ValueDecl *req,
ValueDecl *witness,
unsigned limit) {
DeclName reqName = req->getFullName();
DeclName witnessName = witness->getFullName();

Expand Down Expand Up @@ -4663,12 +4666,12 @@ static bool shouldWarnAboutPotentialWitness(ValueDecl *req,
}

// If the score is relatively high, don't warn: this is probably
// unrelated. Allow about one typo for every two properly-typed
// unrelated. Allow about one typo for every four properly-typed
// characters, which prevents completely-wacky suggestions in many
// cases.
unsigned reqNameLen = getNameLength(req->getFullName());
unsigned witnessNameLen = getNameLength(witness->getFullName());
if (score > (std::min(reqNameLen, witnessNameLen) + 1) / 3)
if (score > (std::min(reqNameLen, witnessNameLen)) / 4)
return false;

return true;
Expand Down Expand Up @@ -4878,16 +4881,17 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,

// Score this particular optional requirement.
auto score = scorePotentiallyMatching(*this, req, value, bestScore);
if (!score) continue;

// If the score is better than the best we've seen, update the best
// and clear out the list.
if (score < bestScore) {
if (*score < bestScore) {
bestOptionalReqs.clear();
bestScore = score;
bestScore = *score;
}

// If this score matches the (possible new) best score, record it.
if (score == bestScore && bestScore < UINT_MAX)
if (*score == bestScore)
bestOptionalReqs.push_back(req);
}

Expand Down
9 changes: 9 additions & 0 deletions test/decl/protocol/conforms/near_miss_objc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,12 @@ class C10Super {
class C10Sub : C10Super, P8 {
override func foo(nearMatch: Int) { }
}

// Be more strict about near misses than we had previously.
@objc protocol P11 {
@objc optional func foo(wibble: Int)
}

class C11 : P11 {
func f(waggle: Int) { } // no warning
}