[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 static bool
diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs, diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs,
ArrayRef<Solution> solutions) { ArrayRef<Solution> solutions) {
llvm::MapVector<Expr *, ValueDecl *> ambiguities;
bool allSolutionsHaveFixes = true; bool allSolutionsHaveFixes = true;
for (const auto &solution : solutions) { for (const auto &solution : solutions) {
if (solution.Fixes.empty()) { if (solution.Fixes.empty()) {
@@ -2900,23 +2898,10 @@ diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs,
continue; continue;
} }
for (const auto *fix : solution.Fixes) { if (!llvm::all_of(solution.Fixes, [](const ConstraintFix *fix) {
if (fix->getKind() != FixKind::TreatEphemeralAsNonEphemeral) return fix->getKind() == FixKind::TreatEphemeralAsNonEphemeral;
return false; }))
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 // If all solutions have fixes for ephemeral pointers, let's
@@ -2924,13 +2909,10 @@ diagnoseAmbiguityWithEphemeralPointers(ConstraintSystem &cs,
if (allSolutionsHaveFixes) if (allSolutionsHaveFixes)
return false; return false;
auto &DE = cs.getASTContext().Diags; // If only some of the solutions have ephemeral pointer fixes
for (const auto &entry : ambiguities) { // let's let `diagnoseAmbiguity` diagnose the problem either
DE.diagnose(entry.first->getLoc(), diag::ambiguous_decl_ref, // with affected argument or related declaration e.g. function ref.
DeclNameRef(entry.second->getBaseName())); return cs.diagnoseAmbiguity(solutions);
}
return true;
} }
bool ConstraintSystem::diagnoseAmbiguityWithFixes( 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@-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}} // 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@-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}} // 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'}}
}