Suggest changing ty to const params if appropriate
This commit is contained in:
parent
3f7b1a5f49
commit
5906237b32
@ -289,6 +289,9 @@ resolve_underscore_lifetime_name_cannot_be_used_here =
|
||||
`'_` cannot be used here
|
||||
.note = `'_` is a reserved lifetime name
|
||||
|
||||
resolve_unexpected_res_change_ty_to_const_param_sugg =
|
||||
you might have meant to write a const parameter here
|
||||
|
||||
resolve_unreachable_label =
|
||||
use of unreachable label `{$name}`
|
||||
.label = unreachable label `{$name}`
|
||||
|
@ -1,4 +1,4 @@
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_errors::{codes::*, Applicability};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_span::{
|
||||
symbol::{Ident, Symbol},
|
||||
@ -787,3 +787,16 @@ pub(crate) struct IsNotDirectlyImportable {
|
||||
pub(crate) span: Span,
|
||||
pub(crate) target: Ident,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
resolve_unexpected_res_change_ty_to_const_param_sugg,
|
||||
code = "const ",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[applicability]
|
||||
pub applicability: Applicability,
|
||||
}
|
||||
|
@ -444,6 +444,7 @@ pub(crate) fn smart_resolve_report_errors(
|
||||
}
|
||||
|
||||
self.suggest_bare_struct_literal(&mut err);
|
||||
self.suggest_changing_type_to_const_param(&mut err, res, source, span);
|
||||
|
||||
if self.suggest_pattern_match_with_let(&mut err, source, span) {
|
||||
// Fallback label.
|
||||
@ -1138,6 +1139,55 @@ fn suggest_bare_struct_literal(&mut self, err: &mut Diagnostic) {
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_changing_type_to_const_param(
|
||||
&mut self,
|
||||
err: &mut Diagnostic,
|
||||
res: Option<Res>,
|
||||
source: PathSource<'_>,
|
||||
span: Span,
|
||||
) {
|
||||
let PathSource::Trait(_) = source else { return };
|
||||
|
||||
// We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway.
|
||||
let applicability = match res {
|
||||
Some(Res::PrimTy(PrimTy::Int(_) | PrimTy::Uint(_) | PrimTy::Bool | PrimTy::Char)) => {
|
||||
Applicability::MachineApplicable
|
||||
}
|
||||
// FIXME(const_generics): Add `DefKind::TyParam` and `SelfTyParam` once we support generic
|
||||
// const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the
|
||||
// benefits of including them here outweighs the small number of false positives.
|
||||
Some(Res::Def(DefKind::Struct | DefKind::Enum, _))
|
||||
if self.r.tcx.features().adt_const_params =>
|
||||
{
|
||||
Applicability::MaybeIncorrect
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
||||
let Some(item) = self.diagnostic_metadata.current_item else { return };
|
||||
let Some(generics) = item.kind.generics() else { return };
|
||||
|
||||
let param = generics.params.iter().find_map(|param| {
|
||||
// Only consider type params with exactly one trait bound.
|
||||
if let [bound] = &*param.bounds
|
||||
&& let ast::GenericBound::Trait(tref, ast::TraitBoundModifiers::NONE) = bound
|
||||
&& tref.span == span
|
||||
&& param.ident.span.eq_ctxt(span)
|
||||
{
|
||||
Some(param.ident.span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(param) = param {
|
||||
err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg {
|
||||
span: param.shrink_to_lo(),
|
||||
applicability,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn suggest_pattern_match_with_let(
|
||||
&mut self,
|
||||
err: &mut Diagnostic,
|
||||
|
10
tests/ui/resolve/change-ty-to-const-param-sugg-0.rs
Normal file
10
tests/ui/resolve/change-ty-to-const-param-sugg-0.rs
Normal file
@ -0,0 +1,10 @@
|
||||
fn make<N: u32>() {}
|
||||
//~^ ERROR expected trait, found builtin type `u32`
|
||||
//~| HELP you might have meant to write a const parameter here
|
||||
|
||||
struct Array<N: usize>([bool; N]);
|
||||
//~^ ERROR expected trait, found builtin type `usize`
|
||||
//~| HELP you might have meant to write a const parameter here
|
||||
//~| ERROR expected value, found type parameter `N`
|
||||
|
||||
fn main() {}
|
34
tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr
Normal file
34
tests/ui/resolve/change-ty-to-const-param-sugg-0.stderr
Normal file
@ -0,0 +1,34 @@
|
||||
error[E0404]: expected trait, found builtin type `u32`
|
||||
--> $DIR/change-ty-to-const-param-sugg-0.rs:1:12
|
||||
|
|
||||
LL | fn make<N: u32>() {}
|
||||
| ^^^ not a trait
|
||||
|
|
||||
help: you might have meant to write a const parameter here
|
||||
|
|
||||
LL | fn make<const N: u32>() {}
|
||||
| +++++
|
||||
|
||||
error[E0404]: expected trait, found builtin type `usize`
|
||||
--> $DIR/change-ty-to-const-param-sugg-0.rs:5:17
|
||||
|
|
||||
LL | struct Array<N: usize>([bool; N]);
|
||||
| ^^^^^ not a trait
|
||||
|
|
||||
help: you might have meant to write a const parameter here
|
||||
|
|
||||
LL | struct Array<const N: usize>([bool; N]);
|
||||
| +++++
|
||||
|
||||
error[E0423]: expected value, found type parameter `N`
|
||||
--> $DIR/change-ty-to-const-param-sugg-0.rs:5:31
|
||||
|
|
||||
LL | struct Array<N: usize>([bool; N]);
|
||||
| - ^ not a value
|
||||
| |
|
||||
| found this type parameter
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0404, E0423.
|
||||
For more information about an error, try `rustc --explain E0404`.
|
24
tests/ui/resolve/change-ty-to-const-param-sugg-1.rs
Normal file
24
tests/ui/resolve/change-ty-to-const-param-sugg-1.rs
Normal file
@ -0,0 +1,24 @@
|
||||
#![feature(adt_const_params)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
struct Tagged<T: Tag, O: Options>;
|
||||
//~^ ERROR expected trait, found enum `Tag`
|
||||
//~| HELP you might have meant to write a const parameter here
|
||||
//~| ERROR expected trait, found struct `Options`
|
||||
//~| HELP you might have meant to write a const parameter here
|
||||
|
||||
#[derive(PartialEq, Eq, ConstParamTy)]
|
||||
enum Tag {
|
||||
One,
|
||||
Two,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, ConstParamTy)]
|
||||
struct Options {
|
||||
verbose: bool,
|
||||
safe: bool,
|
||||
}
|
||||
|
||||
fn main() {}
|
25
tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr
Normal file
25
tests/ui/resolve/change-ty-to-const-param-sugg-1.stderr
Normal file
@ -0,0 +1,25 @@
|
||||
error[E0404]: expected trait, found enum `Tag`
|
||||
--> $DIR/change-ty-to-const-param-sugg-1.rs:6:18
|
||||
|
|
||||
LL | struct Tagged<T: Tag, O: Options>;
|
||||
| ^^^ not a trait
|
||||
|
|
||||
help: you might have meant to write a const parameter here
|
||||
|
|
||||
LL | struct Tagged<const T: Tag, O: Options>;
|
||||
| +++++
|
||||
|
||||
error[E0404]: expected trait, found struct `Options`
|
||||
--> $DIR/change-ty-to-const-param-sugg-1.rs:6:26
|
||||
|
|
||||
LL | struct Tagged<T: Tag, O: Options>;
|
||||
| ^^^^^^^ not a trait
|
||||
|
|
||||
help: you might have meant to write a const parameter here
|
||||
|
|
||||
LL | struct Tagged<T: Tag, const O: Options>;
|
||||
| +++++
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0404`.
|
Loading…
Reference in New Issue
Block a user