Skip to content

Commit a8e1664

Browse files
authored
Rollup merge of #154557 - Muhtasim-Rasheed:issue-147313-improve-help, r=chenyukang
Make E0284 generic argument suggestions more explicit Closes #147313 Previously, when type annotations were missing for a function call, rust suggested: "consider specifying the generic argument". This PR improves the diagnostics: - If only one generic type is missing: "consider specifying a concrete type for the generic type `<T>`" with the turbofish being "::\<SomeConcreteType>" - If only one const generic is missing: "consider specifying a const for the const generic `<CONST>`" with the turbofish being "::<SOME_CONST>" Multiple missing generics still produce the original more general suggestion
2 parents 4c7e656 + b178681 commit a8e1664

53 files changed

Lines changed: 279 additions & 178 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ use rustc_middle::hir::nested_filter;
1515
use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind};
1616
use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
1717
use rustc_middle::ty::{
18-
self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind,
19-
Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypeckResults,
18+
self, GenericArg, GenericArgKind, GenericArgsRef, GenericParamDefKind, InferConst,
19+
IsSuggestable, Term, TermKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
20+
TypeVisitableExt, TypeckResults,
2021
};
2122
use rustc_span::{BytePos, DUMMY_SP, Ident, Span, sym};
2223
use tracing::{debug, instrument, warn};
@@ -592,15 +593,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
592593
(true, parent.prefix.to_string(), parent.name)
593594
});
594595

596+
let param = &generics.own_params[argument_index];
597+
let param_name = param.name.to_string();
598+
595599
infer_subdiags.push(SourceKindSubdiag::GenericLabel {
596600
span,
597601
is_type,
598-
param_name: generics.own_params[argument_index].name.to_string(),
602+
param_name: param_name.clone(),
599603
parent_exists,
600604
parent_prefix,
601605
parent_name,
602606
});
603607

608+
let mut used_fallback = false;
604609
let args = if self.tcx.get_diagnostic_item(sym::iterator_collect_fn)
605610
== Some(generics_def_id)
606611
{
@@ -634,9 +639,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
634639
let mut p = fmt_printer(self, Namespace::TypeNS);
635640
p.comma_sep(generic_args.iter().copied().map(|arg| {
636641
if arg.is_suggestable(self.tcx, true) {
642+
used_fallback = true;
637643
return arg;
638644
}
639-
640645
match arg.kind() {
641646
GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
642647
GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
@@ -648,11 +653,31 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
648653
};
649654

650655
if !have_turbofish {
651-
infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
652-
span: insert_span,
653-
arg_count: generic_args.len(),
654-
args,
655-
});
656+
if generic_args.len() == 1 && used_fallback {
657+
match param.kind {
658+
GenericParamDefKind::Type { .. } => {
659+
infer_subdiags.push(SourceKindSubdiag::GenericTypeSuggestion {
660+
span: insert_span,
661+
param: param_name,
662+
});
663+
}
664+
GenericParamDefKind::Const { .. } => {
665+
infer_subdiags.push(SourceKindSubdiag::ConstGenericSuggestion {
666+
span: insert_span,
667+
param: param_name,
668+
});
669+
}
670+
GenericParamDefKind::Lifetime => {
671+
bug!("unexpected lifetime")
672+
}
673+
}
674+
} else {
675+
infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
676+
span: insert_span,
677+
arg_count: generic_args.len(),
678+
args,
679+
});
680+
}
656681
}
657682
}
658683
InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {

compiler/rustc_trait_selection/src/errors.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,28 @@ pub(crate) enum SourceKindSubdiag<'a> {
331331
arg_count: usize,
332332
args: String,
333333
},
334+
#[suggestion(
335+
"consider specifying a concrete type for the type parameter `{$param}`",
336+
style = "verbose",
337+
code = "::</* Type */>",
338+
applicability = "has-placeholders"
339+
)]
340+
GenericTypeSuggestion {
341+
#[primary_span]
342+
span: Span,
343+
param: String,
344+
},
345+
#[suggestion(
346+
"consider specifying a const for the const parameter `{$param}`",
347+
style = "verbose",
348+
code = "::</* CONST */>",
349+
applicability = "has-placeholders"
350+
)]
351+
ConstGenericSuggestion {
352+
#[primary_span]
353+
span: Span,
354+
param: String,
355+
},
334356
}
335357

336358
#[derive(Subdiagnostic)]

tests/ui/associated-type-bounds/duplicate-bound-err.stderr

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,32 @@ error[E0282]: type annotations needed
44
LL | iter::empty()
55
| ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
66
|
7-
help: consider specifying the generic argument
7+
help: consider specifying a concrete type for the type parameter `T`
88
|
9-
LL | iter::empty::<T>()
10-
| +++++
9+
LL | iter::empty::</* Type */>()
10+
| ++++++++++++++
1111

1212
error[E0282]: type annotations needed
1313
--> $DIR/duplicate-bound-err.rs:18:5
1414
|
1515
LL | iter::empty()
1616
| ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
1717
|
18-
help: consider specifying the generic argument
18+
help: consider specifying a concrete type for the type parameter `T`
1919
|
20-
LL | iter::empty::<T>()
21-
| +++++
20+
LL | iter::empty::</* Type */>()
21+
| ++++++++++++++
2222

2323
error[E0282]: type annotations needed
2424
--> $DIR/duplicate-bound-err.rs:22:5
2525
|
2626
LL | iter::empty()
2727
| ^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `empty`
2828
|
29-
help: consider specifying the generic argument
29+
help: consider specifying a concrete type for the type parameter `T`
3030
|
31-
LL | iter::empty::<T>()
32-
| +++++
31+
LL | iter::empty::</* Type */>()
32+
| ++++++++++++++
3333

3434
error: unconstrained opaque type
3535
--> $DIR/duplicate-bound-err.rs:26:51

tests/ui/async-await/unresolved_type_param.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ error[E0282]: type annotations needed
44
LL | bar().await;
55
| ^^^ cannot infer type of the type parameter `T` declared on the function `bar`
66
|
7-
help: consider specifying the generic argument
7+
help: consider specifying a concrete type for the type parameter `T`
88
|
9-
LL | bar::<T>().await;
10-
| +++++
9+
LL | bar::</* Type */>().await;
10+
| ++++++++++++++
1111

1212
error: aborting due to 1 previous error
1313

tests/ui/const-generics/defaults/rp_impl_trait_fail.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ note: required by a const generic parameter in `uwu`
6161
|
6262
LL | fn uwu<const N: u8>() -> impl Traitor<N> {
6363
| ^^^^^^^^^^^ required by this const generic parameter in `uwu`
64-
help: consider specifying the generic argument
64+
help: consider specifying a const for the const parameter `N`
6565
|
66-
LL | uwu::<N>();
67-
| +++++
66+
LL | uwu::</* CONST */>();
67+
| +++++++++++++++
6868

6969
error: aborting due to 4 previous errors
7070

tests/ui/const-generics/fn-const-param-infer.adt_const_params.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ error[E0282]: type annotations needed
1919
LL | let _ = Checked::<generic>;
2020
| ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `generic`
2121
|
22-
help: consider specifying the generic argument
22+
help: consider specifying a concrete type for the type parameter `T`
2323
|
24-
LL | let _ = Checked::<generic::<T>>;
25-
| +++++
24+
LL | let _ = Checked::<generic::</* Type */>>;
25+
| ++++++++++++++
2626

2727
error: aborting due to 3 previous errors
2828

tests/ui/const-generics/fn-const-param-infer.full.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ error[E0282]: type annotations needed
1919
LL | let _ = Checked::<generic>;
2020
| ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `generic`
2121
|
22-
help: consider specifying the generic argument
22+
help: consider specifying a concrete type for the type parameter `T`
2323
|
24-
LL | let _ = Checked::<generic::<T>>;
25-
| +++++
24+
LL | let _ = Checked::<generic::</* Type */>>;
25+
| ++++++++++++++
2626

2727
error: aborting due to 3 previous errors
2828

tests/ui/const-generics/fn-const-param-infer.min.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ error[E0282]: type annotations needed
2121
LL | let _ = Checked::<generic>;
2222
| ^^^^^^^ cannot infer type of the type parameter `T` declared on the function `generic`
2323
|
24-
help: consider specifying the generic argument
24+
help: consider specifying a concrete type for the type parameter `T`
2525
|
26-
LL | let _ = Checked::<generic::<T>>;
27-
| +++++
26+
LL | let _ = Checked::<generic::</* Type */>>;
27+
| ++++++++++++++
2828

2929
error: aborting due to 3 previous errors
3030

tests/ui/const-generics/generic_const_exprs/dyn-compatibility-ok-infer-err.stderr

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ note: required by a const generic parameter in `use_dyn`
99
|
1010
LL | fn use_dyn<const N: usize>(v: &dyn Foo<N>) where [u8; N + 1]: Sized {
1111
| ^^^^^^^^^^^^^^ required by this const generic parameter in `use_dyn`
12-
help: consider specifying the generic argument
12+
help: consider specifying a const for the const parameter `N`
1313
|
14-
LL | use_dyn::<N>(&());
15-
| +++++
14+
LL | use_dyn::</* CONST */>(&());
15+
| +++++++++++++++
1616

1717
error[E0284]: type annotations needed
1818
--> $DIR/dyn-compatibility-ok-infer-err.rs:19:5
@@ -30,10 +30,10 @@ LL | impl<const N: usize> Foo<N> for () {
3030
| |
3131
| unsatisfied trait bound introduced here
3232
= note: required for the cast from `&()` to `&dyn Foo<_>`
33-
help: consider specifying the generic argument
33+
help: consider specifying a const for the const parameter `N`
3434
|
35-
LL | use_dyn::<N>(&());
36-
| +++++
35+
LL | use_dyn::</* CONST */>(&());
36+
| +++++++++++++++
3737

3838
error: aborting due to 2 previous errors
3939

tests/ui/const-generics/infer/cannot-infer-const-args.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ note: required by a const generic parameter in `foo`
99
|
1010
LL | fn foo<const X: usize>() -> usize {
1111
| ^^^^^^^^^^^^^^ required by this const generic parameter in `foo`
12-
help: consider specifying the generic argument
12+
help: consider specifying a const for the const parameter `X`
1313
|
14-
LL | foo::<X>();
15-
| +++++
14+
LL | foo::</* CONST */>();
15+
| +++++++++++++++
1616

1717
error: aborting due to 1 previous error
1818

0 commit comments

Comments
 (0)