Skip to content

Commit 5906237

Browse files
committed
Suggest changing ty to const params if appropriate
1 parent 3f7b1a5 commit 5906237

7 files changed

+160
-1
lines changed

compiler/rustc_resolve/messages.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ resolve_underscore_lifetime_name_cannot_be_used_here =
289289
`'_` cannot be used here
290290
.note = `'_` is a reserved lifetime name
291291
292+
resolve_unexpected_res_change_ty_to_const_param_sugg =
293+
you might have meant to write a const parameter here
294+
292295
resolve_unreachable_label =
293296
use of unreachable label `{$name}`
294297
.label = unreachable label `{$name}`

compiler/rustc_resolve/src/errors.rs

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rustc_errors::codes::*;
1+
use rustc_errors::{codes::*, Applicability};
22
use rustc_macros::{Diagnostic, Subdiagnostic};
33
use rustc_span::{
44
symbol::{Ident, Symbol},
@@ -787,3 +787,16 @@ pub(crate) struct IsNotDirectlyImportable {
787787
pub(crate) span: Span,
788788
pub(crate) target: Ident,
789789
}
790+
791+
#[derive(Subdiagnostic)]
792+
#[suggestion(
793+
resolve_unexpected_res_change_ty_to_const_param_sugg,
794+
code = "const ",
795+
style = "verbose"
796+
)]
797+
pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
798+
#[primary_span]
799+
pub span: Span,
800+
#[applicability]
801+
pub applicability: Applicability,
802+
}

compiler/rustc_resolve/src/late/diagnostics.rs

+50
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
444444
}
445445

446446
self.suggest_bare_struct_literal(&mut err);
447+
self.suggest_changing_type_to_const_param(&mut err, res, source, span);
447448

448449
if self.suggest_pattern_match_with_let(&mut err, source, span) {
449450
// Fallback label.
@@ -1138,6 +1139,55 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
11381139
}
11391140
}
11401141

1142+
fn suggest_changing_type_to_const_param(
1143+
&mut self,
1144+
err: &mut Diagnostic,
1145+
res: Option<Res>,
1146+
source: PathSource<'_>,
1147+
span: Span,
1148+
) {
1149+
let PathSource::Trait(_) = source else { return };
1150+
1151+
// We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway.
1152+
let applicability = match res {
1153+
Some(Res::PrimTy(PrimTy::Int(_) | PrimTy::Uint(_) | PrimTy::Bool | PrimTy::Char)) => {
1154+
Applicability::MachineApplicable
1155+
}
1156+
// FIXME(const_generics): Add `DefKind::TyParam` and `SelfTyParam` once we support generic
1157+
// const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the
1158+
// benefits of including them here outweighs the small number of false positives.
1159+
Some(Res::Def(DefKind::Struct | DefKind::Enum, _))
1160+
if self.r.tcx.features().adt_const_params =>
1161+
{
1162+
Applicability::MaybeIncorrect
1163+
}
1164+
_ => return,
1165+
};
1166+
1167+
let Some(item) = self.diagnostic_metadata.current_item else { return };
1168+
let Some(generics) = item.kind.generics() else { return };
1169+
1170+
let param = generics.params.iter().find_map(|param| {
1171+
// Only consider type params with exactly one trait bound.
1172+
if let [bound] = &*param.bounds
1173+
&& let ast::GenericBound::Trait(tref, ast::TraitBoundModifiers::NONE) = bound
1174+
&& tref.span == span
1175+
&& param.ident.span.eq_ctxt(span)
1176+
{
1177+
Some(param.ident.span)
1178+
} else {
1179+
None
1180+
}
1181+
});
1182+
1183+
if let Some(param) = param {
1184+
err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg {
1185+
span: param.shrink_to_lo(),
1186+
applicability,
1187+
});
1188+
}
1189+
}
1190+
11411191
fn suggest_pattern_match_with_let(
11421192
&mut self,
11431193
err: &mut Diagnostic,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
fn make<N: u32>() {}
2+
//~^ ERROR expected trait, found builtin type `u32`
3+
//~| HELP you might have meant to write a const parameter here
4+
5+
struct Array<N: usize>([bool; N]);
6+
//~^ ERROR expected trait, found builtin type `usize`
7+
//~| HELP you might have meant to write a const parameter here
8+
//~| ERROR expected value, found type parameter `N`
9+
10+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
error[E0404]: expected trait, found builtin type `u32`
2+
--> $DIR/change-ty-to-const-param-sugg-0.rs:1:12
3+
|
4+
LL | fn make<N: u32>() {}
5+
| ^^^ not a trait
6+
|
7+
help: you might have meant to write a const parameter here
8+
|
9+
LL | fn make<const N: u32>() {}
10+
| +++++
11+
12+
error[E0404]: expected trait, found builtin type `usize`
13+
--> $DIR/change-ty-to-const-param-sugg-0.rs:5:17
14+
|
15+
LL | struct Array<N: usize>([bool; N]);
16+
| ^^^^^ not a trait
17+
|
18+
help: you might have meant to write a const parameter here
19+
|
20+
LL | struct Array<const N: usize>([bool; N]);
21+
| +++++
22+
23+
error[E0423]: expected value, found type parameter `N`
24+
--> $DIR/change-ty-to-const-param-sugg-0.rs:5:31
25+
|
26+
LL | struct Array<N: usize>([bool; N]);
27+
| - ^ not a value
28+
| |
29+
| found this type parameter
30+
31+
error: aborting due to 3 previous errors
32+
33+
Some errors have detailed explanations: E0404, E0423.
34+
For more information about an error, try `rustc --explain E0404`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#![feature(adt_const_params)]
2+
#![allow(incomplete_features)]
3+
4+
use std::marker::ConstParamTy;
5+
6+
struct Tagged<T: Tag, O: Options>;
7+
//~^ ERROR expected trait, found enum `Tag`
8+
//~| HELP you might have meant to write a const parameter here
9+
//~| ERROR expected trait, found struct `Options`
10+
//~| HELP you might have meant to write a const parameter here
11+
12+
#[derive(PartialEq, Eq, ConstParamTy)]
13+
enum Tag {
14+
One,
15+
Two,
16+
}
17+
18+
#[derive(PartialEq, Eq, ConstParamTy)]
19+
struct Options {
20+
verbose: bool,
21+
safe: bool,
22+
}
23+
24+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
error[E0404]: expected trait, found enum `Tag`
2+
--> $DIR/change-ty-to-const-param-sugg-1.rs:6:18
3+
|
4+
LL | struct Tagged<T: Tag, O: Options>;
5+
| ^^^ not a trait
6+
|
7+
help: you might have meant to write a const parameter here
8+
|
9+
LL | struct Tagged<const T: Tag, O: Options>;
10+
| +++++
11+
12+
error[E0404]: expected trait, found struct `Options`
13+
--> $DIR/change-ty-to-const-param-sugg-1.rs:6:26
14+
|
15+
LL | struct Tagged<T: Tag, O: Options>;
16+
| ^^^^^^^ not a trait
17+
|
18+
help: you might have meant to write a const parameter here
19+
|
20+
LL | struct Tagged<T: Tag, const O: Options>;
21+
| +++++
22+
23+
error: aborting due to 2 previous errors
24+
25+
For more information about this error, try `rustc --explain E0404`.

0 commit comments

Comments
 (0)