[ConstraintSystem] Simplify diagnoseAmbiguityWithEphemeralPointers

Don't attempt to figure out what exactly is ambiguous, let
`diagnoseAmbiguity` take care of that. Simplify make sure
that only some of the solutions have fixes and these fixes
are all related to use of ephemeral pointers.
This commit is contained in:
Pavel Yaskevich
2020-02-18 15:06:13 -08:00
parent d2953bb0c0
commit 2c92df4a6d
3 changed files with 22 additions and 26 deletions

View File

@@ -2891,8 +2891,6 @@ static bool diagnoseConflictingGenericArguments(ConstraintSystem &cs,
static bool
diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs,
ArrayRef<Solution> solutions) {
llvm::MapVector<Expr *, ValueDecl *> ambiguities;
bool allSolutionsHaveFixes = true;
for (const auto &solution : solutions) {
if (solution.Fixes.empty()) {
@@ -2900,23 +2898,10 @@ diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs,
continue;
}
for (const auto *fix : solution.Fixes) {
if (fix->getKind() != FixKind::TreatEphemeralAsNonEphemeral)
if (!llvm::all_of(solution.Fixes, [](const ConstraintFix *fix) {
return fix->getKind() == FixKind::TreatEphemeralAsNonEphemeral;
}))
return false;
// Ephemeral pointers are only possible in argument positions.
if (auto *anchor = simplifyLocatorToAnchor(fix->getLocator())) {
anchor = cast<InOutExpr>(anchor)->getSubExpr();
auto overload = solution.getOverloadChoiceIfAvailable(
cs.getConstraintLocator(anchor));
if (!(overload && overload->choice.isDecl()))
return false;
ambiguities.insert({anchor, overload->choice.getDecl()});
}
}
}
// If all solutions have fixes for ephemeral pointers, let's
@@ -2924,13 +2909,10 @@ diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs,
if (allSolutionsHaveFixes)
return false;
auto &DE = cs.getASTContext().Diags;
for (const auto &entry : ambiguities) {
DE.diagnose(entry.first->getLoc(), diag::ambiguous_decl_ref,
DeclNameRef(entry.second->getBaseName()));
}
return true;
// If only some of the solutions have ephemeral pointer fixes
// let's let `diagnoseAmbiguity` diagnose the problem either
// with affected argument or related declaration e.g. function ref.
return cs.diagnoseAmbiguity(solutions);
}
bool ConstraintSystem::diagnoseAmbiguityWithFixes(

View File

@@ -520,3 +520,10 @@ func testArgumentLabelReferencing() {
// expected-note@-5 {{implicit argument conversion from '[Int]' to 'UnsafePointer<Int>' produces a pointer valid only for the duration of the call to 'takesTwoPointers(ptr:ptr:)'}}
// expected-note@-6 {{use the 'withUnsafeBufferPointer' method on Array in order to explicitly convert argument to buffer pointer valid for a defined scope}}
}
func ambiguous_fn(@_nonEphemeral _ ptr: UnsafePointer<Int>) {} // expected-note {{found this candidate}}
func ambiguous_fn(_ ptr: UnsafeRawPointer) {} // expected-note {{found this candidate}}
func test_ambiguity_with_function_instead_of_argument(_ x: inout Int) {
ambiguous_fn(&x) // expected-error {{ambiguous use of 'ambiguous_fn'}}
}

View File

@@ -467,3 +467,10 @@ func testNonEphemeralInMemberwiseInits() {
// expected-note@-1 {{implicit argument conversion from 'String' to 'UnsafePointer<Int8>' produces a pointer valid only for the duration of the call to 'const'}}
// expected-note@-2 {{use the 'withCString' method on String in order to explicitly convert argument to pointer valid for a defined scope}}
}
func ambiguous_fn(@_nonEphemeral _ ptr: UnsafePointer<Int>) {} // expected-note {{found this candidate}}
func ambiguous_fn(_ ptr: UnsafeRawPointer) {} // expected-note {{found this candidate}}
func test_ambiguity_with_function_instead_of_argument(_ x: inout Int) {
ambiguous_fn(&x) // expected-error {{ambiguous use of 'ambiguous_fn'}}
}