Skip to content

Commit df93364

Browse files
committed
Added ability to report on generic argument mismatch better
Needs some checking over and some tests have altered that need sanity checking, but overall this is starting to get somewhere now.
1 parent ee03c28 commit df93364

17 files changed

+611
-75
lines changed

compiler/rustc_errors/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub use rustc_error_messages::{
5050
fallback_fluent_bundle, fluent_bundle, DelayDm, DiagMessage, FluentBundle, LanguageIdentifier,
5151
LazyFallbackBundle, MultiSpan, SpanLabel, SubdiagMessage,
5252
};
53-
pub use rustc_lint_defs::{pluralize, Applicability};
53+
pub use rustc_lint_defs::{a_or_an, display_list_with_comma_and, pluralize, Applicability};
5454
pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker};
5555
pub use rustc_span::ErrorGuaranteed;
5656
pub use snippet::Style;

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+368-20
Large diffs are not rendered by default.

compiler/rustc_lint_defs/src/lib.rs

+33
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,39 @@ macro_rules! pluralize {
3939
};
4040
}
4141

42+
/// Grammatical tool for displaying messages to end users in a nice form.
43+
///
44+
/// Returns "an" if the given string starts with a vowel, and "a" otherwise.
45+
pub fn a_or_an(s: &str) -> &'static str {
46+
let mut chars = s.chars();
47+
let Some(mut first_alpha_char) = chars.next() else {
48+
return "a";
49+
};
50+
if first_alpha_char == '`' {
51+
let Some(next) = chars.next() else {
52+
return "a";
53+
};
54+
first_alpha_char = next;
55+
}
56+
if ["a", "e", "i", "o", "u", "&"].contains(&&first_alpha_char.to_lowercase().to_string()[..]) {
57+
"an"
58+
} else {
59+
"a"
60+
}
61+
}
62+
63+
/// Grammatical tool for displaying messages to end users in a nice form.
64+
///
65+
/// Take a list ["a", "b", "c"] and output a display friendly version "a, b and c"
66+
pub fn display_list_with_comma_and<T: std::fmt::Display>(v: &[T]) -> String {
67+
match v.len() {
68+
0 => "".to_string(),
69+
1 => v[0].to_string(),
70+
2 => format!("{} and {}", v[0], v[1]),
71+
_ => format!("{}, {}", v[0], display_list_with_comma_and(&v[1..])),
72+
}
73+
}
74+
4275
/// Indicates the confidence in the correctness of a suggestion.
4376
///
4477
/// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion

tests/ui/argument-suggestions/extra_arguments.stderr

+7-7
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ note: function defined here
4545
--> $DIR/extra_arguments.rs:2:4
4646
|
4747
LL | fn one_arg<T>(_a: T) {}
48-
| ^^^^^^^ -----
48+
| ^^^^^^^
4949

5050
error[E0061]: this function takes 1 argument but 2 arguments were supplied
5151
--> $DIR/extra_arguments.rs:23:3
@@ -60,7 +60,7 @@ note: function defined here
6060
--> $DIR/extra_arguments.rs:2:4
6161
|
6262
LL | fn one_arg<T>(_a: T) {}
63-
| ^^^^^^^ -----
63+
| ^^^^^^^
6464

6565
error[E0061]: this function takes 1 argument but 3 arguments were supplied
6666
--> $DIR/extra_arguments.rs:24:3
@@ -74,7 +74,7 @@ note: function defined here
7474
--> $DIR/extra_arguments.rs:2:4
7575
|
7676
LL | fn one_arg<T>(_a: T) {}
77-
| ^^^^^^^ -----
77+
| ^^^^^^^
7878
help: remove the extra arguments
7979
|
8080
LL - one_arg(1, "", 1.0);
@@ -319,7 +319,7 @@ note: function defined here
319319
--> $DIR/extra_arguments.rs:2:4
320320
|
321321
LL | fn one_arg<T>(_a: T) {}
322-
| ^^^^^^^ -----
322+
| ^^^^^^^
323323

324324
error[E0061]: this function takes 1 argument but 2 arguments were supplied
325325
--> $DIR/extra_arguments.rs:54:3
@@ -334,7 +334,7 @@ note: function defined here
334334
--> $DIR/extra_arguments.rs:2:4
335335
|
336336
LL | fn one_arg<T>(_a: T) {}
337-
| ^^^^^^^ -----
337+
| ^^^^^^^
338338

339339
error[E0061]: this function takes 1 argument but 2 arguments were supplied
340340
--> $DIR/extra_arguments.rs:55:3
@@ -349,7 +349,7 @@ note: function defined here
349349
--> $DIR/extra_arguments.rs:2:4
350350
|
351351
LL | fn one_arg<T>(_a: T) {}
352-
| ^^^^^^^ -----
352+
| ^^^^^^^
353353

354354
error[E0061]: this function takes 1 argument but 2 arguments were supplied
355355
--> $DIR/extra_arguments.rs:60:3
@@ -364,7 +364,7 @@ note: function defined here
364364
--> $DIR/extra_arguments.rs:2:4
365365
|
366366
LL | fn one_arg<T>(_a: T) {}
367-
| ^^^^^^^ -----
367+
| ^^^^^^^
368368

369369
error: aborting due to 22 previous errors
370370

tests/ui/argument-suggestions/invalid_arguments.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ note: function defined here
2424
--> $DIR/invalid_arguments.rs:6:4
2525
|
2626
LL | fn two_arg_same(_a: i32, _b: i32) {}
27-
| ^^^^^^^^^^^^ -------
27+
| ^^^^^^^^^^^^ ------- -------
2828

2929
error[E0308]: mismatched types
3030
--> $DIR/invalid_arguments.rs:17:16
@@ -38,7 +38,7 @@ note: function defined here
3838
--> $DIR/invalid_arguments.rs:6:4
3939
|
4040
LL | fn two_arg_same(_a: i32, _b: i32) {}
41-
| ^^^^^^^^^^^^ -------
41+
| ^^^^^^^^^^^^ ------- -------
4242

4343
error[E0308]: arguments to this function are incorrect
4444
--> $DIR/invalid_arguments.rs:18:3
@@ -66,7 +66,7 @@ note: function defined here
6666
--> $DIR/invalid_arguments.rs:7:4
6767
|
6868
LL | fn two_arg_diff(_a: i32, _b: f32) {}
69-
| ^^^^^^^^^^^^ -------
69+
| ^^^^^^^^^^^^ ------- -------
7070

7171
error[E0308]: mismatched types
7272
--> $DIR/invalid_arguments.rs:20:16
@@ -80,7 +80,7 @@ note: function defined here
8080
--> $DIR/invalid_arguments.rs:7:4
8181
|
8282
LL | fn two_arg_diff(_a: i32, _b: f32) {}
83-
| ^^^^^^^^^^^^ -------
83+
| ^^^^^^^^^^^^ ------- -------
8484

8585
error[E0308]: arguments to this function are incorrect
8686
--> $DIR/invalid_arguments.rs:21:3
@@ -108,7 +108,7 @@ note: function defined here
108108
--> $DIR/invalid_arguments.rs:8:4
109109
|
110110
LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
111-
| ^^^^^^^^^^^^^^ -------
111+
| ^^^^^^^^^^^^^^ ------- ------- --------
112112

113113
error[E0308]: mismatched types
114114
--> $DIR/invalid_arguments.rs:25:21
@@ -122,7 +122,7 @@ note: function defined here
122122
--> $DIR/invalid_arguments.rs:8:4
123123
|
124124
LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
125-
| ^^^^^^^^^^^^^^ -------
125+
| ^^^^^^^^^^^^^^ ------- ------- --------
126126

127127
error[E0308]: mismatched types
128128
--> $DIR/invalid_arguments.rs:26:26
@@ -136,7 +136,7 @@ note: function defined here
136136
--> $DIR/invalid_arguments.rs:8:4
137137
|
138138
LL | fn three_arg_diff(_a: i32, _b: f32, _c: &str) {}
139-
| ^^^^^^^^^^^^^^ --------
139+
| ^^^^^^^^^^^^^^ ------- ------- --------
140140

141141
error[E0308]: arguments to this function are incorrect
142142
--> $DIR/invalid_arguments.rs:28:3
@@ -207,7 +207,7 @@ note: function defined here
207207
--> $DIR/invalid_arguments.rs:9:4
208208
|
209209
LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
210-
| ^^^^^^^^^^^^^^^^ -------
210+
| ^^^^^^^^^^^^^^^^ ------- ------- --------
211211

212212
error[E0308]: mismatched types
213213
--> $DIR/invalid_arguments.rs:35:23
@@ -221,7 +221,7 @@ note: function defined here
221221
--> $DIR/invalid_arguments.rs:9:4
222222
|
223223
LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
224-
| ^^^^^^^^^^^^^^^^ -------
224+
| ^^^^^^^^^^^^^^^^ ------- ------- --------
225225

226226
error[E0308]: mismatched types
227227
--> $DIR/invalid_arguments.rs:36:26
@@ -235,7 +235,7 @@ note: function defined here
235235
--> $DIR/invalid_arguments.rs:9:4
236236
|
237237
LL | fn three_arg_repeat(_a: i32, _b: i32, _c: &str) {}
238-
| ^^^^^^^^^^^^^^^^ --------
238+
| ^^^^^^^^^^^^^^^^ ------- ------- --------
239239

240240
error[E0308]: arguments to this function are incorrect
241241
--> $DIR/invalid_arguments.rs:38:3

tests/ui/argument-suggestions/too-long.stderr

+23-1
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,31 @@ note: method defined here
1111
|
1212
LL | fn foo(
1313
| ^^^
14-
...
14+
LL | &self,
15+
LL | a: i32,
16+
| ------
17+
LL | b: i32,
18+
| ------
19+
LL | c: i32,
20+
| ------
21+
LL | d: i32,
22+
| ------
23+
LL | e: i32,
24+
| ------
1525
LL | f: i32,
1626
| ------
27+
LL | g: i32,
28+
| ------
29+
LL | h: i32,
30+
| ------
31+
LL | i: i32,
32+
| ------
33+
LL | j: i32,
34+
| ------
35+
LL | k: i32,
36+
| ------
37+
LL | l: i32,
38+
| ------
1739
help: consider dereferencing the borrow
1840
|
1941
LL | qux.foo(a, b, c, d, e, *f, g, h, i, j, k, l);

tests/ui/async-await/coroutine-desc.stderr

+23-8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ LL | fun(async {}, async {});
55
| --- -------- ^^^^^^^^ expected `async` block, found a different `async` block
66
| | |
77
| | the expected `async` block
8+
| | expected argument `f2` to be an `async` block because that argument needs to match the type of this parameter
89
| arguments to this function are incorrect
910
|
1011
= note: expected `async` block `{async block@$DIR/coroutine-desc.rs:10:9: 10:17}`
@@ -13,14 +14,19 @@ note: function defined here
1314
--> $DIR/coroutine-desc.rs:8:4
1415
|
1516
LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
16-
| ^^^ -----
17+
| ^^^ - ----- -----
18+
| | | |
19+
| | | this parameter needs to match the `async` block type of `f1`
20+
| | `f2` needs to match the type of this parameter
21+
| `f1` and `f2` all reference this parameter F
1722

1823
error[E0308]: mismatched types
1924
--> $DIR/coroutine-desc.rs:12:16
2025
|
2126
LL | fun(one(), two());
22-
| --- ^^^^^ expected future, found a different future
23-
| |
27+
| --- ----- ^^^^^ expected future, found a different future
28+
| | |
29+
| | expected argument `f2` to be a future because that argument needs to match the type of this parameter
2430
| arguments to this function are incorrect
2531
|
2632
= help: consider `await`ing on both `Future`s
@@ -29,15 +35,20 @@ note: function defined here
2935
--> $DIR/coroutine-desc.rs:8:4
3036
|
3137
LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
32-
| ^^^ -----
38+
| ^^^ - ----- -----
39+
| | | |
40+
| | | this parameter needs to match the future type of `f1`
41+
| | `f2` needs to match the type of this parameter
42+
| `f1` and `f2` all reference this parameter F
3343

3444
error[E0308]: mismatched types
3545
--> $DIR/coroutine-desc.rs:14:26
3646
|
3747
LL | fun((async || {})(), (async || {})());
38-
| --- -- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
39-
| | |
40-
| | the expected `async` closure body
48+
| --- --------------- ^^^^^^^^^^^^^^^ expected `async` closure body, found a different `async` closure body
49+
| | | |
50+
| | | the expected `async` closure body
51+
| | expected argument `f2` to be an `async` closure body because that argument needs to match the type of this parameter
4152
| arguments to this function are incorrect
4253
|
4354
= note: expected `async` closure body `{async closure body@$DIR/coroutine-desc.rs:14:19: 14:21}`
@@ -46,7 +57,11 @@ note: function defined here
4657
--> $DIR/coroutine-desc.rs:8:4
4758
|
4859
LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
49-
| ^^^ -----
60+
| ^^^ - ----- -----
61+
| | | |
62+
| | | this parameter needs to match the `async` closure body type of `f1`
63+
| | `f2` needs to match the type of this parameter
64+
| `f1` and `f2` all reference this parameter F
5065

5166
error: aborting due to 3 previous errors
5267

tests/ui/coercion/coerce-reborrow-multi-arg-fail.stderr

+8-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ error[E0308]: mismatched types
22
--> $DIR/coerce-reborrow-multi-arg-fail.rs:4:18
33
|
44
LL | test(&mut 7, &7);
5-
| ---- ^^ types differ in mutability
6-
| |
5+
| ---- ------ ^^ types differ in mutability
6+
| | |
7+
| | expected argument `_b` to be an `&mut {integer}` because that argument needs to match the type of this parameter
78
| arguments to this function are incorrect
89
|
910
= note: expected mutable reference `&mut {integer}`
@@ -12,7 +13,11 @@ note: function defined here
1213
--> $DIR/coerce-reborrow-multi-arg-fail.rs:1:4
1314
|
1415
LL | fn test<T>(_a: T, _b: T) {}
15-
| ^^^^ -----
16+
| ^^^^ - ----- -----
17+
| | | |
18+
| | | this parameter needs to match the `&mut {integer}` type of `_a`
19+
| | `_b` needs to match the type of this parameter
20+
| `_a` and `_b` all reference this parameter T
1621

1722
error: aborting due to 1 previous error
1823

tests/ui/coercion/coerce-to-bang.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ note: function defined here
1212
--> $DIR/coerce-to-bang.rs:3:4
1313
|
1414
LL | fn foo(x: usize, y: !, z: usize) { }
15-
| ^^^ ----
15+
| ^^^ -------- ---- --------
1616

1717
error[E0308]: mismatched types
1818
--> $DIR/coerce-to-bang.rs:18:13
@@ -28,7 +28,7 @@ note: function defined here
2828
--> $DIR/coerce-to-bang.rs:3:4
2929
|
3030
LL | fn foo(x: usize, y: !, z: usize) { }
31-
| ^^^ ----
31+
| ^^^ -------- ---- --------
3232

3333
error[E0308]: mismatched types
3434
--> $DIR/coerce-to-bang.rs:26:12
@@ -44,7 +44,7 @@ note: function defined here
4444
--> $DIR/coerce-to-bang.rs:3:4
4545
|
4646
LL | fn foo(x: usize, y: !, z: usize) { }
47-
| ^^^ ----
47+
| ^^^ -------- ---- --------
4848

4949
error[E0308]: mismatched types
5050
--> $DIR/coerce-to-bang.rs:36:12
@@ -60,7 +60,7 @@ note: function defined here
6060
--> $DIR/coerce-to-bang.rs:3:4
6161
|
6262
LL | fn foo(x: usize, y: !, z: usize) { }
63-
| ^^^ ----
63+
| ^^^ -------- ---- --------
6464

6565
error[E0308]: mismatched types
6666
--> $DIR/coerce-to-bang.rs:45:12
@@ -76,7 +76,7 @@ note: function defined here
7676
--> $DIR/coerce-to-bang.rs:3:4
7777
|
7878
LL | fn foo(x: usize, y: !, z: usize) { }
79-
| ^^^ ----
79+
| ^^^ -------- ---- --------
8080

8181
error[E0308]: mismatched types
8282
--> $DIR/coerce-to-bang.rs:50:21

0 commit comments

Comments
 (0)