Skip to content

Commit 78fa5a1

Browse files
Tweak parameter mismatch explanation to not say unknown
1 parent 15b663e commit 78fa5a1

File tree

8 files changed

+87
-38
lines changed

8 files changed

+87
-38
lines changed

compiler/rustc_errors/src/lib.rs

+11
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,17 @@ pub fn display_list_with_comma_and<T: std::fmt::Display>(v: &[T]) -> String {
19951995
}
19961996
}
19971997

1998+
pub fn ordinalize(x: usize) -> String {
1999+
let suffix = match x % 10 {
2000+
_ if (11..=19).contains(&x) => "th",
2001+
1 => "st",
2002+
2 => "nd",
2003+
3 => "rd",
2004+
_ => "th",
2005+
};
2006+
format!("{x}{suffix}")
2007+
}
2008+
19982009
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
19992010
pub enum TerminalUrl {
20002011
No,

compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+31-24
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxIndexSet;
55
use rustc_errors::codes::*;
66
use rustc_errors::{
77
Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, a_or_an,
8-
display_list_with_comma_and, pluralize,
8+
display_list_with_comma_and, ordinalize, pluralize,
99
};
1010
use rustc_hir::def::{CtorOf, DefKind, Res};
1111
use rustc_hir::def_id::DefId;
@@ -2347,9 +2347,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23472347

23482348
let check_for_matched_generics = || {
23492349
if matched_inputs.iter().any(|x| x.is_some())
2350-
&& params_with_generics.iter().any(|x| x.0.is_some())
2350+
&& params_with_generics.iter().any(|x| x.1.is_some())
23512351
{
2352-
for (idx, (generic, _)) in params_with_generics.iter().enumerate() {
2352+
for &(idx, generic, _) in &params_with_generics {
23532353
// Param has to have a generic and be matched to be relevant
23542354
if matched_inputs[idx.into()].is_none() {
23552355
continue;
@@ -2362,7 +2362,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23622362
for unmatching_idx in idx + 1..params_with_generics.len() {
23632363
if matched_inputs[unmatching_idx.into()].is_none()
23642364
&& let Some(unmatched_idx_param_generic) =
2365-
params_with_generics[unmatching_idx].0
2365+
params_with_generics[unmatching_idx].1
23662366
&& unmatched_idx_param_generic.name.ident()
23672367
== generic.name.ident()
23682368
{
@@ -2377,8 +2377,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23772377

23782378
let check_for_matched_generics = check_for_matched_generics();
23792379

2380-
for (idx, (generic_param, param)) in
2381-
params_with_generics.iter().enumerate().filter(|(idx, _)| {
2380+
for &(idx, generic_param, param) in
2381+
params_with_generics.iter().filter(|&(idx, _, _)| {
23822382
check_for_matched_generics
23832383
|| expected_idx.is_none_or(|expected_idx| expected_idx == *idx)
23842384
})
@@ -2390,8 +2390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23902390

23912391
let other_params_matched: Vec<(usize, &hir::Param<'_>)> = params_with_generics
23922392
.iter()
2393-
.enumerate()
2394-
.filter(|(other_idx, (other_generic_param, _))| {
2393+
.filter(|(other_idx, other_generic_param, _)| {
23952394
if *other_idx == idx {
23962395
return false;
23972396
}
@@ -2410,18 +2409,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24102409
}
24112410
other_generic_param.name.ident() == generic_param.name.ident()
24122411
})
2413-
.map(|(other_idx, (_, other_param))| (other_idx, *other_param))
2412+
.map(|&(other_idx, _, other_param)| (other_idx, other_param))
24142413
.collect();
24152414

24162415
if !other_params_matched.is_empty() {
24172416
let other_param_matched_names: Vec<String> = other_params_matched
24182417
.iter()
2419-
.map(|(_, other_param)| {
2418+
.map(|(idx, other_param)| {
24202419
if let hir::PatKind::Binding(_, _, ident, _) = other_param.pat.kind
24212420
{
24222421
format!("`{ident}`")
24232422
} else {
2424-
"{unknown}".to_string()
2423+
format!("the {} parameter", ordinalize(idx + 1))
24252424
}
24262425
})
24272426
.collect();
@@ -2478,18 +2477,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24782477
{
24792478
let param_idents_matching: Vec<String> = params_with_generics
24802479
.iter()
2481-
.filter(|(generic, _)| {
2480+
.filter(|(_, generic, _)| {
24822481
if let Some(generic) = generic {
24832482
generic.name.ident() == generic_param.name.ident()
24842483
} else {
24852484
false
24862485
}
24872486
})
2488-
.map(|(_, param)| {
2487+
.map(|(idx, _, param)| {
24892488
if let hir::PatKind::Binding(_, _, ident, _) = param.pat.kind {
24902489
format!("`{ident}`")
24912490
} else {
2492-
"{unknown}".to_string()
2491+
format!("the {} parameter", ordinalize(idx + 1))
24932492
}
24942493
})
24952494
.collect();
@@ -2498,8 +2497,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24982497
spans.push_span_label(
24992498
generic_param.span,
25002499
format!(
2501-
"{} all reference this parameter {}",
2500+
"{} {} reference this parameter `{}`",
25022501
display_list_with_comma_and(&param_idents_matching),
2502+
if param_idents_matching.len() == 2 { "both" } else { "all" },
25032503
generic_param.name.ident().name,
25042504
),
25052505
);
@@ -2580,7 +2580,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25802580

25812581
if let Some(params_with_generics) = self.get_hir_params_with_generics(def_id, is_method) {
25822582
debug_assert_eq!(params_with_generics.len(), matched_inputs.len());
2583-
for (idx, (generic_param, _)) in params_with_generics.iter().enumerate() {
2583+
for &(idx, generic_param, _) in &params_with_generics {
25842584
if matched_inputs[idx.into()].is_none() {
25852585
continue;
25862586
}
@@ -2594,20 +2594,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25942594
};
25952595

25962596
let mut idxs_matched: Vec<usize> = vec![];
2597-
for (other_idx, (_, _)) in params_with_generics.iter().enumerate().filter(
2598-
|(other_idx, (other_generic_param, _))| {
2599-
if *other_idx == idx {
2597+
for &(other_idx, _, _) in
2598+
params_with_generics.iter().filter(|&&(other_idx, other_generic_param, _)| {
2599+
if other_idx == idx {
26002600
return false;
26012601
}
26022602
let Some(other_generic_param) = other_generic_param else {
26032603
return false;
26042604
};
2605-
if matched_inputs[(*other_idx).into()].is_some() {
2605+
if matched_inputs[other_idx.into()].is_some() {
26062606
return false;
26072607
}
26082608
other_generic_param.name.ident() == generic_param.name.ident()
2609-
},
2610-
) {
2609+
})
2610+
{
26112611
idxs_matched.push(other_idx);
26122612
}
26132613

@@ -2642,7 +2642,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26422642
&self,
26432643
def_id: DefId,
26442644
is_method: bool,
2645-
) -> Option<Vec<(Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
2645+
) -> Option<Vec<(usize, Option<&hir::GenericParam<'_>>, &hir::Param<'_>)>> {
26462646
let fn_node = self.tcx.hir().get_if_local(def_id)?;
26472647
let fn_decl = fn_node.fn_decl()?;
26482648

@@ -2685,7 +2685,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26852685
}
26862686

26872687
debug_assert_eq!(params.len(), generic_params.len());
2688-
Some(generic_params.into_iter().zip(params).collect())
2688+
Some(
2689+
generic_params
2690+
.into_iter()
2691+
.zip(params)
2692+
.enumerate()
2693+
.map(|(a, (b, c))| (a, b, c))
2694+
.collect(),
2695+
)
26892696
}
26902697
}
26912698

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
1919
| ^^^ - ----- ----- this parameter needs to match the `async` block type of `f1`
2020
| | |
2121
| | `f2` needs to match the `async` block type of this parameter
22-
| `f1` and `f2` all reference this parameter F
22+
| `f1` and `f2` both reference this parameter `F`
2323

2424
error[E0308]: mismatched types
2525
--> $DIR/coroutine-desc.rs:12:16
@@ -39,7 +39,7 @@ LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
3939
| ^^^ - ----- ----- this parameter needs to match the future type of `f1`
4040
| | |
4141
| | `f2` needs to match the future type of this parameter
42-
| `f1` and `f2` all reference this parameter F
42+
| `f1` and `f2` both reference this parameter `F`
4343

4444
error[E0308]: mismatched types
4545
--> $DIR/coroutine-desc.rs:14:26
@@ -62,7 +62,7 @@ LL | fn fun<F: Future<Output = ()>>(f1: F, f2: F) {}
6262
| ^^^ - ----- ----- this parameter needs to match the `async` closure body type of `f1`
6363
| | |
6464
| | `f2` needs to match the `async` closure body type of this parameter
65-
| `f1` and `f2` all reference this parameter F
65+
| `f1` and `f2` both reference this parameter `F`
6666

6767
error: aborting due to 3 previous errors
6868

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ LL | fn test<T>(_a: T, _b: T) {}
1616
| ^^^^ - ----- ----- this parameter needs to match the `&mut {integer}` type of `_a`
1717
| | |
1818
| | `_b` needs to match the `&mut {integer}` type of this parameter
19-
| `_a` and `_b` all reference this parameter T
19+
| `_a` and `_b` both reference this parameter `T`
2020

2121
error: aborting due to 1 previous error
2222

tests/ui/fn/fn-item-type.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ LL | fn eq<T>(x: T, y: T) {}
1717
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
1818
| | |
1919
| | `y` needs to match the fn item type of this parameter
20-
| `x` and `y` all reference this parameter T
20+
| `x` and `y` both reference this parameter `T`
2121
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
2222

2323
error[E0308]: mismatched types
@@ -39,7 +39,7 @@ LL | fn eq<T>(x: T, y: T) {}
3939
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
4040
| | |
4141
| | `y` needs to match the fn item type of this parameter
42-
| `x` and `y` all reference this parameter T
42+
| `x` and `y` both reference this parameter `T`
4343
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
4444

4545
error[E0308]: mismatched types
@@ -61,7 +61,7 @@ LL | fn eq<T>(x: T, y: T) {}
6161
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
6262
| | |
6363
| | `y` needs to match the fn item type of this parameter
64-
| `x` and `y` all reference this parameter T
64+
| `x` and `y` both reference this parameter `T`
6565
= help: consider casting both fn items to fn pointers using `as fn(isize) -> isize`
6666

6767
error[E0308]: mismatched types
@@ -83,7 +83,7 @@ LL | fn eq<T>(x: T, y: T) {}
8383
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
8484
| | |
8585
| | `y` needs to match the fn item type of this parameter
86-
| `x` and `y` all reference this parameter T
86+
| `x` and `y` both reference this parameter `T`
8787
= help: consider casting both fn items to fn pointers using `as fn()`
8888

8989
error[E0308]: mismatched types
@@ -105,7 +105,7 @@ LL | fn eq<T>(x: T, y: T) {}
105105
| ^^ - ---- ---- this parameter needs to match the fn item type of `x`
106106
| | |
107107
| | `y` needs to match the fn item type of this parameter
108-
| `x` and `y` all reference this parameter T
108+
| `x` and `y` both reference this parameter `T`
109109

110110
error: aborting due to 5 previous errors
111111

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn same_type<T>(_: T, _: T) {}
2+
3+
fn f<X, Y>(x: X, y: Y) {
4+
same_type([x], Some(y));
5+
//~^ ERROR mismatched types
6+
}
7+
8+
fn main() {}
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/param-mismatch-no-names.rs:4:20
3+
|
4+
LL | same_type([x], Some(y));
5+
| --------- --- ^^^^^^^ expected `[X; 1]`, found `Option<Y>`
6+
| | |
7+
| | expected all arguments to be this `[X; 1]` type because they need to match the type of this parameter
8+
| arguments to this function are incorrect
9+
|
10+
= note: expected array `[X; 1]`
11+
found enum `Option<Y>`
12+
note: function defined here
13+
--> $DIR/param-mismatch-no-names.rs:1:4
14+
|
15+
LL | fn same_type<T>(_: T, _: T) {}
16+
| ^^^^^^^^^ - ---- ---- this parameter needs to match the `[X; 1]` type of the 1st parameter
17+
| | |
18+
| | the 2nd parameter needs to match the `[X; 1]` type of this parameter
19+
| the 1st parameter and the 2nd parameter both reference this parameter `T`
20+
21+
error: aborting due to 1 previous error
22+
23+
For more information about this error, try `rustc --explain E0308`.

tests/ui/mismatched_types/generic-mismatch-reporting-issue-116615.stderr

+5-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ LL | fn foo<T>(a: T, b: T) {}
1414
| ^^^ - ---- ---- this parameter needs to match the integer type of `a`
1515
| | |
1616
| | `b` needs to match the integer type of this parameter
17-
| `a` and `b` all reference this parameter T
17+
| `a` and `b` both reference this parameter `T`
1818

1919
error[E0308]: arguments to this function are incorrect
2020
--> $DIR/generic-mismatch-reporting-issue-116615.rs:8:5
@@ -38,7 +38,7 @@ LL | fn foo_multi_same<T>(a: T, b: T, c: T, d: T, e: T, f: i32) {}
3838
| | | | this parameter needs to match the `&str` type of `a` and `b`
3939
| | | `c`, `d` and `e` need to match the `&str` type of this parameter
4040
| | `c`, `d` and `e` need to match the `&str` type of this parameter
41-
| `a`, `b`, `c`, `d` and `e` all reference this parameter T
41+
| `a`, `b`, `c`, `d` and `e` all reference this parameter `T`
4242

4343
error[E0308]: arguments to this function are incorrect
4444
--> $DIR/generic-mismatch-reporting-issue-116615.rs:10:5
@@ -65,8 +65,8 @@ LL | fn foo_multi_generics<S, T>(a: T, b: T, c: T, d: T, e: T, f: S, g: S) {}
6565
| | | | | `d` and `e` need to match the `&str` type of this parameter
6666
| | | | `d` and `e` need to match the `&str` type of this parameter
6767
| | | `d` and `e` need to match the `&str` type of this parameter
68-
| | `a`, `b`, `c`, `d` and `e` all reference this parameter T
69-
| `f` and `g` all reference this parameter S
68+
| | `a`, `b`, `c`, `d` and `e` all reference this parameter `T`
69+
| `f` and `g` both reference this parameter `S`
7070

7171
error[E0308]: arguments to this function are incorrect
7272
--> $DIR/generic-mismatch-reporting-issue-116615.rs:12:5
@@ -90,7 +90,7 @@ LL | fn foo_multi_same<T>(a: T, b: T, c: T, d: T, e: T, f: i32) {}
9090
| | | | this parameter needs to match the `&str` type of `a`, `d` and `e`
9191
| | | this parameter needs to match the `&str` type of `a`, `d` and `e`
9292
| | `b` and `c` need to match the `&str` type of this parameter
93-
| `a`, `b`, `c`, `d` and `e` all reference this parameter T
93+
| `a`, `b`, `c`, `d` and `e` all reference this parameter `T`
9494

9595
error: aborting due to 4 previous errors
9696

0 commit comments

Comments
 (0)