[Diagnostics] Improve argument labeling diagnostics

Extend new labeling diagnostics (via fixes) to support
member references and subscripts.
This commit is contained in:
Pavel Yaskevich
2019-02-21 16:03:03 -08:00
parent 1a66c77110
commit d4b67bf3f7
10 changed files with 53 additions and 19 deletions

View File

@@ -366,10 +366,25 @@ bool MissingConformanceFailure::diagnoseAsError() {
bool LabelingFailure::diagnoseAsError() {
auto &cs = getConstraintSystem();
auto *call = cast<CallExpr>(getAnchor());
return diagnoseArgumentLabelError(cs.getASTContext(), call->getArg(),
CorrectLabels,
isa<SubscriptExpr>(call->getFn()));
auto *anchor = getRawAnchor();
Expr *argExpr = nullptr;
if (auto *UDE = dyn_cast<UnresolvedDotExpr>(anchor)) {
if (auto *call = dyn_cast_or_null<CallExpr>(findParentExpr(UDE)))
argExpr = call->getArg();
} else if (auto *UME = dyn_cast<UnresolvedMemberExpr>(anchor)) {
argExpr = UME->getArgument();
} else if (auto *call = dyn_cast<CallExpr>(anchor)) {
argExpr = call->getArg();
} else if (auto *SE = dyn_cast<SubscriptExpr>(anchor)) {
argExpr = SE->getIndex();
}
if (!argExpr)
return false;
return diagnoseArgumentLabelError(cs.getASTContext(), argExpr, CorrectLabels,
isa<SubscriptExpr>(anchor));
}
bool NoEscapeFuncToTypeConversionFailure::diagnoseAsError() {

View File

@@ -443,9 +443,9 @@ class LabelingFailure final : public FailureDiagnostic {
ArrayRef<Identifier> CorrectLabels;
public:
LabelingFailure(ConstraintSystem &cs, ConstraintLocator *locator,
LabelingFailure(Expr *root, ConstraintSystem &cs, ConstraintLocator *locator,
ArrayRef<Identifier> labels)
: FailureDiagnostic(nullptr, cs, locator), CorrectLabels(labels) {}
: FailureDiagnostic(root, cs, locator), CorrectLabels(labels) {}
bool diagnoseAsError() override;
};

View File

@@ -145,7 +145,8 @@ MarkExplicitlyEscaping::create(ConstraintSystem &cs, ConstraintLocator *locator,
}
bool RelabelArguments::diagnose(Expr *root, bool asNote) const {
LabelingFailure failure(getConstraintSystem(), getLocator(), getLabels());
LabelingFailure failure(root, getConstraintSystem(), getLocator(),
getLabels());
return failure.diagnose(asNote);
}

View File

@@ -755,7 +755,7 @@ public:
return true;
auto *anchor = Locator.getBaseLocator()->getAnchor();
if (!anchor || !isa<CallExpr>(anchor))
if (!anchor)
return true;
auto *locator = CS.getConstraintLocator(anchor);
@@ -1229,6 +1229,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
if (func1Params.size() != func2Params.size())
return getTypeMatchFailure(argumentLocator);
bool hasLabelingFailures = false;
for (unsigned i : indices(func1Params)) {
auto func1Param = func1Params[i];
auto func2Param = func2Params[i];
@@ -1242,9 +1243,16 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
// FIXME: We should not end up with labels here at all, but we do
// from invalid code in diagnostics, and as a result of code completion
// directly building constraint systems.
if (func1Param.getLabel() != func2Param.getLabel())
if (func1Param.getLabel() != func2Param.getLabel()) {
if (!shouldAttemptFixes())
return getTypeMatchFailure(argumentLocator);
// If we are allowed to attempt fixes, let's ignore labeling
// failures, and create a fix to re-label arguments if types
// line up correctly.
hasLabelingFailures = true;
}
// FIXME: We should check value ownership too, but it's not completely
// trivial because of inout-to-pointer conversions.
@@ -1260,6 +1268,17 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
return result;
}
if (hasLabelingFailures) {
SmallVector<Identifier, 4> correctLabels;
for (const auto &param : func2Params)
correctLabels.push_back(param.getLabel());
auto *fix = RelabelArguments::create(*this, correctLabels,
getConstraintLocator(argumentLocator));
if (recordFix(fix))
return getTypeMatchFailure(argumentLocator);
}
// Result type can be covariant (or equal).
return matchTypes(func1->getResult(), func2->getResult(), subKind,
subflags,

View File

@@ -448,6 +448,7 @@ let _: Color = .overload(1) // expected-error {{ambiguous reference to member '
let _: Color = .frob(1.0, &i) // expected-error {{missing argument label 'b:' in call}}
let _: Color = .frob(1.0, b: &i) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
let _: Color = .frob(1, i) // expected-error {{missing argument label 'b:' in call}}
// expected-error@-1 {{passing value of type 'Int' to an inout parameter requires explicit '&'}}
let _: Color = .frob(1, b: i) // expected-error {{passing value of type 'Int' to an inout parameter requires explicit '&'}} {{28-28=&}}
let _: Color = .frob(1, &d) // expected-error {{missing argument label 'b:' in call}}
let _: Color = .frob(1, b: &d) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}

View File

@@ -630,7 +630,7 @@ let arr = [BottleLayout]()
let layout = BottleLayout(count:1)
let ix = arr.firstIndex(of:layout) // expected-error {{argument type 'BottleLayout' does not conform to expected type 'Equatable'}}
let _: () -> UInt8 = { .init("a" as Unicode.Scalar) } // expected-error {{initializer 'init(_:)' requires that 'Unicode.Scalar' conform to 'BinaryInteger'}}
let _: () -> UInt8 = { .init("a" as Unicode.Scalar) } // expected-error {{missing argument label 'ascii:' in call}}
// https://bugs.swift.org/browse/SR-9068
func compare<C: Collection, Key: Hashable, Value: Equatable>(c: C)

View File

@@ -291,10 +291,7 @@ switch staticMembers {
case .init(0): break
case .init(_): break // expected-error{{'_' can only appear in a pattern}}
case .init(let x): break // expected-error{{cannot appear in an expression}}
case .init(opt: 0): break
// expected-error@-1 {{value of optional type 'StaticMembers?' must be unwrapped to a value of type 'StaticMembers'}}
// expected-note@-2 {{coalesce}}
// expected-note@-3 {{force-unwrap}}
case .init(opt: 0): break // expected-error{{pattern cannot match values of type 'StaticMembers'}}
case .prop: break
// TODO: repeated error message

View File

@@ -91,7 +91,7 @@ struct SR718 {
subscript(a a : UInt) -> Int { return 0 }
}
SR718()[a: Int()] // expected-error {{cannot convert value of type 'Int' to expected argument type 'UInt'}}
SR718()[a: Int()] // expected-error {{extraneous argument label 'a:' in subscript}}
// rdar://problem/25601561 - Qol: Bad diagnostic for failed assignment from Any to more specific type

View File

@@ -16,6 +16,8 @@ class B {
class D : B {
override init() {
super.init()
super.init(42)
// expected-error@-1 {{missing argument label 'x:' in call}}
}
override init(x:Int) {

View File

@@ -106,10 +106,9 @@ func testMethods(_ i: Int, x: Y) {
func testSubscripts(_ i: Int, s: String, x: Y) {
var i2 = x[i]
var i3 = x[x: i] // expected-error{{cannot subscript a value of type 'Y' with an index of type '(x: Int)'}}
// expected-note @-1 {{overloads for 'subscript' exist with these partially matching parameter lists: (Int), (y: String)}}
var i3 = x[x: i] // expected-error{{extraneous argument label 'x:' in subscript}}
var s2 = x[y: s]
var s3 = x[s] // expected-error{{cannot convert value of type 'String' to expected argument type 'Int'}}
var s3 = x[s] // expected-error{{missing argument label 'y:' in subscript}}
}
// Operators