Skip to content

Commit 1b4f9c3

Browse files
committed
[Diagnostic] In no exact match cases diagnose labeling mismatch as a note
Each candidate with incorrect labels (but everything else lined up) gets a note on its declarationm which says what is expected and what has been given.
1 parent be470f5 commit 1b4f9c3

File tree

8 files changed

+87
-42
lines changed

8 files changed

+87
-42
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,9 @@ ERROR(argument_out_of_order_unnamed_named,none,
10511051
ERROR(argument_out_of_order_unnamed_unnamed,none,
10521052
"unnamed argument #%0 must precede unnamed argument #%1",
10531053
(unsigned, unsigned))
1054+
NOTE(candidate_expected_different_labels,none,
1055+
"incorrect labels for candidate (have: '%0', expected: '%1')",
1056+
(StringRef, StringRef))
10541057

10551058
ERROR(member_shadows_global_function,none,
10561059
"use of %0 refers to %1 %2 rather than %3 %4 in %5 %6",

lib/Sema/CSDiagnostics.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "swift/Parse/Lexer.h"
3434
#include "llvm/ADT/ArrayRef.h"
3535
#include "llvm/ADT/SmallString.h"
36+
#include <string>
3637

3738
using namespace swift;
3839
using namespace constraints;
@@ -691,6 +692,46 @@ bool LabelingFailure::diagnoseAsError() {
691692
isa<SubscriptExpr>(anchor));
692693
}
693694

695+
bool LabelingFailure::diagnoseAsNote() {
696+
auto *anchor = getRawAnchor();
697+
698+
auto *argExpr = getArgumentExprFor(anchor);
699+
if (!argExpr)
700+
return false;
701+
702+
SmallVector<Identifier, 4> argLabels;
703+
if (auto *paren = dyn_cast<ParenExpr>(argExpr)) {
704+
argLabels.push_back(Identifier());
705+
} else if (auto *tuple = dyn_cast<TupleExpr>(argExpr)) {
706+
argLabels.append(tuple->getElementNames().begin(),
707+
tuple->getElementNames().end());
708+
} else {
709+
return false;
710+
}
711+
712+
auto stringifyLabels = [](ArrayRef<Identifier> labels) -> std::string {
713+
std::string str;
714+
for (auto label : labels) {
715+
str += label.empty() ? "_" : label.str();
716+
str += ':';
717+
}
718+
return "(" + str + ")";
719+
};
720+
721+
auto selectedOverload = getChoiceFor(anchor);
722+
if (!selectedOverload)
723+
return false;
724+
725+
const auto &choice = selectedOverload->choice;
726+
if (auto *decl = choice.getDeclOrNull()) {
727+
emitDiagnostic(decl, diag::candidate_expected_different_labels,
728+
stringifyLabels(argLabels), stringifyLabels(CorrectLabels));
729+
return true;
730+
}
731+
732+
return false;
733+
}
734+
694735
bool NoEscapeFuncToTypeConversionFailure::diagnoseAsError() {
695736
auto *anchor = getAnchor();
696737

lib/Sema/CSDiagnostics.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ class LabelingFailure final : public FailureDiagnostic {
529529
: FailureDiagnostic(root, cs, locator), CorrectLabels(labels) {}
530530

531531
bool diagnoseAsError() override;
532+
bool diagnoseAsNote() override;
532533
};
533534

534535
/// Diagnose errors related to converting function type which

test/ClangImporter/objc_diags.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@
33
import ObjectiveC
44

55
func instanceMethod(_ b: B) {
6-
b.method(1, 2.5) // expected-error {{argument labels '(_:, _:)' do not match any available overloads}}
7-
// expected-note @-1 {{overloads for 'method' exist with these partially matching parameter lists: (Int32, onCat1: Double), (Int32, onExtA: Double), (Int32, onExtB: Double), (Int32, with: Double), (Int32, with: Float), (Int32, withDouble: Double), (Int32, withFloat: Float)}}
6+
// Notes for labeling mismatch candidates are now attached to each individual declaration
7+
b.method(1, 2.5) // expected-error {{no exact matches in call to instance method 'method'}}
88
}

test/ClangImporter/objc_missing_designated_init.swift

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,57 +3,57 @@
33
import UnimportableMembers
44
import UnimportableMembersUser
55

6-
class IncompleteInitSubclassImplicit : IncompleteDesignatedInitializers {
6+
class IncompleteInitSubclassImplicit : IncompleteDesignatedInitializers { // expected-note 6 {{incorrect labels for candidate}}
77
var myOneNewMember = 1
88
}
99

1010
class IncompleteInitSubclass : IncompleteDesignatedInitializers {
11-
override init(first: Int) {}
12-
override init(second: Int) {}
11+
override init(first: Int) {} // expected-note 3 {{incorrect labels for candidate}}
12+
override init(second: Int) {} // expected-note 3 {{incorrect labels for candidate}}
1313
}
1414

15-
class IncompleteConvenienceInitSubclass : IncompleteConvenienceInitializers {}
15+
class IncompleteConvenienceInitSubclass : IncompleteConvenienceInitializers {} // expected-note 2 {{incorrect labels for candidate}}
1616

17-
class IncompleteUnknownInitSubclass : IncompleteUnknownInitializers {}
17+
class IncompleteUnknownInitSubclass : IncompleteUnknownInitializers {} // expected-note 4 {{incorrect labels for candidate}}
1818

19-
class IncompleteInitCategorySubclassImplicit : IncompleteDesignatedInitializersWithCategory {}
19+
class IncompleteInitCategorySubclassImplicit : IncompleteDesignatedInitializersWithCategory {} // expected-note 6 {{incorrect labels for candidate}}
2020

2121
class IncompleteInitCategorySubclass : IncompleteDesignatedInitializersWithCategory {
22-
override init(first: Int) {}
23-
override init(second: Int) {}
22+
override init(first: Int) {} // expected-note 3 {{incorrect labels for candidate}}
23+
override init(second: Int) {} // expected-note 3 {{incorrect labels for candidate}}
2424
}
2525

26-
class DesignatedInitializerInAnotherModuleSubclass : DesignatedInitializerInAnotherModule {}
26+
class DesignatedInitializerInAnotherModuleSubclass : DesignatedInitializerInAnotherModule {} // expected-note 9 {{incorrect labels for candidate}}
2727

2828

2929
func testBaseClassesBehaveAsExpected() {
3030
_ = IncompleteDesignatedInitializers(first: 0) // okay
3131
_ = IncompleteDesignatedInitializers(second: 0) // okay
32-
_ = IncompleteDesignatedInitializers(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
32+
_ = IncompleteDesignatedInitializers(missing: 0) // expected-error {{no exact matches in call to initializer}}
3333
_ = IncompleteDesignatedInitializers(conveniently: 0) // okay
3434
_ = IncompleteDesignatedInitializers(category: 0) // okay
3535

3636
_ = IncompleteConvenienceInitializers(first: 0) // okay
3737
_ = IncompleteConvenienceInitializers(second: 0) // okay
38-
_ = IncompleteConvenienceInitializers(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
38+
_ = IncompleteConvenienceInitializers(missing: 0) // expected-error {{no exact matches in call to initializer}}
3939
_ = IncompleteConvenienceInitializers(conveniently: 0) // okay
4040
_ = IncompleteConvenienceInitializers(category: 0) // okay
4141

4242
_ = IncompleteUnknownInitializers(first: 0) // okay
4343
_ = IncompleteUnknownInitializers(second: 0) // okay
44-
_ = IncompleteUnknownInitializers(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
44+
_ = IncompleteUnknownInitializers(missing: 0) // expected-error {{no exact matches in call to initializer}}
4545
_ = IncompleteUnknownInitializers(conveniently: 0) // okay
4646
_ = IncompleteUnknownInitializers(category: 0) // okay
4747

4848
_ = IncompleteDesignatedInitializersWithCategory(first: 0) // okay
4949
_ = IncompleteDesignatedInitializersWithCategory(second: 0) // okay
50-
_ = IncompleteDesignatedInitializersWithCategory(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
50+
_ = IncompleteDesignatedInitializersWithCategory(missing: 0) // expected-error {{no exact matches in call to initializer}}
5151
_ = IncompleteDesignatedInitializersWithCategory(conveniently: 0) // okay
5252
_ = IncompleteDesignatedInitializersWithCategory(category: 0) // okay
5353

5454
_ = DesignatedInitializerInAnotherModule(first: 0) // okay
5555
_ = DesignatedInitializerInAnotherModule(second: 0) // okay
56-
_ = DesignatedInitializerInAnotherModule(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
56+
_ = DesignatedInitializerInAnotherModule(missing: 0) // expected-error {{no exact matches in call to initializer}}
5757
_ = DesignatedInitializerInAnotherModule(conveniently: 0) // okay
5858
_ = DesignatedInitializerInAnotherModule(category: 0) // okay
5959
_ = DesignatedInitializerInAnotherModule(fromOtherModule: 0) // okay
@@ -62,44 +62,44 @@ func testBaseClassesBehaveAsExpected() {
6262
func testSubclasses() {
6363
_ = IncompleteInitSubclass(first: 0) // okay
6464
_ = IncompleteInitSubclass(second: 0) // okay
65-
_ = IncompleteInitSubclass(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
66-
_ = IncompleteInitSubclass(conveniently: 0) // expected-error {{argument labels '(conveniently:)' do not match any available overloads}} expected-note {{overloads}}
67-
_ = IncompleteInitSubclass(category: 0) // expected-error {{argument labels '(category:)' do not match any available overloads}} expected-note {{overloads}}
65+
_ = IncompleteInitSubclass(missing: 0) // expected-error {{no exact matches in call to initializer}}
66+
_ = IncompleteInitSubclass(conveniently: 0) // expected-error {{no exact matches in call to initializer}}
67+
_ = IncompleteInitSubclass(category: 0) // expected-error {{no exact matches in call to initializer}}
6868

6969
_ = IncompleteInitSubclassImplicit(first: 0) // okay
7070
_ = IncompleteInitSubclassImplicit(second: 0) // okay
71-
_ = IncompleteInitSubclassImplicit(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
72-
_ = IncompleteInitSubclassImplicit(conveniently: 0) // expected-error {{argument labels '(conveniently:)' do not match any available overloads}} expected-note {{overloads}}
73-
_ = IncompleteInitSubclassImplicit(category: 0) // expected-error {{argument labels '(category:)' do not match any available overloads}} expected-note {{overloads}}
71+
_ = IncompleteInitSubclassImplicit(missing: 0) // expected-error {{no exact matches in call to initializer}}
72+
_ = IncompleteInitSubclassImplicit(conveniently: 0) // expected-error {{no exact matches in call to initializer}}
73+
_ = IncompleteInitSubclassImplicit(category: 0) // expected-error {{no exact matches in call to initializer}}
7474

7575
_ = IncompleteConvenienceInitSubclass(first: 0) // okay
7676
_ = IncompleteConvenienceInitSubclass(second: 0) // okay
77-
_ = IncompleteConvenienceInitSubclass(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
77+
_ = IncompleteConvenienceInitSubclass(missing: 0) // expected-error {{no exact matches in call to initializer}}
7878
_ = IncompleteConvenienceInitSubclass(conveniently: 0) // okay
7979
_ = IncompleteConvenienceInitSubclass(category: 0) // okay
8080

8181
_ = IncompleteUnknownInitSubclass(first: 0) // okay
8282
_ = IncompleteUnknownInitSubclass(second: 0) // okay
83-
_ = IncompleteUnknownInitSubclass(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
83+
_ = IncompleteUnknownInitSubclass(missing: 0) // expected-error {{no exact matches in call to initializer}}
8484
_ = IncompleteUnknownInitSubclass(conveniently: 0) // okay
8585
_ = IncompleteUnknownInitSubclass(category: 0) // okay
8686

8787
_ = IncompleteInitCategorySubclass(first: 0) // okay
8888
_ = IncompleteInitCategorySubclass(second: 0) // okay
89-
_ = IncompleteInitCategorySubclass(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
90-
_ = IncompleteInitCategorySubclass(conveniently: 0) // expected-error {{argument labels '(conveniently:)' do not match any available overloads}} expected-note {{overloads}}
91-
_ = IncompleteInitCategorySubclass(category: 0) // expected-error {{argument labels '(category:)' do not match any available overloads}} expected-note {{overloads}}
89+
_ = IncompleteInitCategorySubclass(missing: 0) // expected-error {{no exact matches in call to initializer}}
90+
_ = IncompleteInitCategorySubclass(conveniently: 0) // expected-error {{no exact matches in call to initializer}}
91+
_ = IncompleteInitCategorySubclass(category: 0) // expected-error {{no exact matches in call to initializer}}
9292

9393
_ = IncompleteInitCategorySubclassImplicit(first: 0) // okay
9494
_ = IncompleteInitCategorySubclassImplicit(second: 0) // okay
95-
_ = IncompleteInitCategorySubclassImplicit(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
96-
_ = IncompleteInitCategorySubclassImplicit(conveniently: 0) // expected-error {{argument labels '(conveniently:)' do not match any available overloads}} expected-note {{overloads}}
97-
_ = IncompleteInitCategorySubclassImplicit(category: 0) // expected-error {{argument labels '(category:)' do not match any available overloads}} expected-note {{overloads}}
95+
_ = IncompleteInitCategorySubclassImplicit(missing: 0) // expected-error {{no exact matches in call to initializer}}
96+
_ = IncompleteInitCategorySubclassImplicit(conveniently: 0) // expected-error {{no exact matches in call to initializer}}
97+
_ = IncompleteInitCategorySubclassImplicit(category: 0) // expected-error {{no exact matches in call to initializer}}
9898

9999
_ = DesignatedInitializerInAnotherModuleSubclass(first: 0) // okay
100100
_ = DesignatedInitializerInAnotherModuleSubclass(second: 0) // okay
101-
_ = DesignatedInitializerInAnotherModuleSubclass(missing: 0) // expected-error {{argument labels '(missing:)' do not match any available overloads}} expected-note {{overloads}}
102-
_ = DesignatedInitializerInAnotherModuleSubclass(conveniently: 0) // expected-error {{argument labels '(conveniently:)' do not match any available overloads}} expected-note {{overloads}}
103-
_ = DesignatedInitializerInAnotherModuleSubclass(category: 0) // expected-error {{argument labels '(category:)' do not match any available overloads}} expected-note {{overloads}}
101+
_ = DesignatedInitializerInAnotherModuleSubclass(missing: 0) // expected-error {{no exact matches in call to initializer}}
102+
_ = DesignatedInitializerInAnotherModuleSubclass(conveniently: 0) // expected-error {{no exact matches in call to initializer}}
103+
_ = DesignatedInitializerInAnotherModuleSubclass(category: 0) // expected-error {{no exact matches in call to initializer}}
104104
_ = DesignatedInitializerInAnotherModuleSubclass(fromOtherModule: 0) // okay
105105
}

test/Constraints/diagnostics.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,8 @@ enum Color {
417417

418418
static func rainbow() -> Color {}
419419

420-
static func overload(a : Int) -> Color {}
421-
static func overload(b : Int) -> Color {}
420+
static func overload(a : Int) -> Color {} // expected-note {{incorrect labels for candidate (have: '(_:)', expected: '(a:)')}}
421+
static func overload(b : Int) -> Color {} // expected-note {{incorrect labels for candidate (have: '(_:)', expected: '(b:)')}}
422422

423423
static func frob(_ a : Int, b : inout Int) -> Color {}
424424
static var svar: Color { return .Red }
@@ -444,8 +444,7 @@ let _ : Color = .rainbow // expected-error {{member 'rainbow' is a function; di
444444
let _: Color = .overload(a : 1.0) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
445445
let _: Color = .overload(1.0) // expected-error {{ambiguous reference to member 'overload'}}
446446
// expected-note @-1 {{overloads for 'overload' exist with these partially matching parameter lists: (a: Int), (b: Int)}}
447-
let _: Color = .overload(1) // expected-error {{ambiguous reference to member 'overload'}}
448-
// expected-note @-1 {{overloads for 'overload' exist with these partially matching parameter lists: (a: Int), (b: Int)}}
447+
let _: Color = .overload(1) // expected-error {{no exact matches in call to static method 'overload'}}
449448
let _: Color = .frob(1.0, &i) // expected-error {{missing argument label 'b:' in call}}
450449
let _: Color = .frob(1.0, b: &i) // expected-error {{cannot convert value of type 'Double' to expected argument type 'Int'}}
451450
let _: Color = .frob(1, i) // expected-error {{missing argument label 'b:' in call}}

test/Constraints/unchecked_optional.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ class A {
66
func do_b(_ x: Int) {}
77
func do_b(_ x: Float) {}
88

9-
func do_c(x: Int) {}
10-
func do_c(y: Int) {}
9+
func do_c(x: Int) {} // expected-note 2 {{incorrect labels for candidate (have: '(_:)', expected: '(x:)')}}
10+
func do_c(y: Int) {} // expected-note 2 {{incorrect labels for candidate (have: '(_:)', expected: '(y:)')}}
1111
}
1212

1313
func test0(_ a : A!) {
@@ -16,7 +16,7 @@ func test0(_ a : A!) {
1616
a.do_b(1)
1717
a.do_b(5.0)
1818

19-
a.do_c(1) // expected-error {{cannot invoke 'do_c' with an argument list of type '(Int)'}}
19+
a.do_c(1) // expected-error {{no exact matches in call to instance method 'do_c'}}
2020
a.do_c(x: 1)
2121
}
2222

@@ -26,7 +26,7 @@ func test1(_ a : A!) {
2626
a?.do_b(1)
2727
a?.do_b(5.0)
2828

29-
a?.do_c(1) // expected-error {{cannot invoke 'do_c' with an argument list of type '(Int)'}}
29+
a?.do_c(1) // expected-error {{no exact matches in call to instance method 'do_c'}}
3030
a?.do_c(x: 1)
3131
}
3232

validation-test/Sema/type_checker_crashers_fixed/rdar45470505.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ extension BinaryInteger {
44
init(bytes: [UInt8]) { fatalError() }
55

66
init<S: Sequence>(bytes: S) where S.Iterator.Element == UInt8 {
7-
self.init(bytes // expected-error {{missing argument label 'integerLiteral:' in call}}
7+
// expected-note@-1 {{incorrect labels for candidate (have: '(_:)', expected: '(bytes:)')}}
8+
self.init(bytes // expected-error {{no exact matches in call to initializer}}
89
// expected-note@-1 {{}}
910

1011
extension

0 commit comments

Comments
 (0)