Recognize potential impl<const N: usize> to impl<N> mistake
When encountering code like `impl<N> Bar<N> for [u8; N]`, suggest `impl<const N: Type> Bar<N> for [u8; N]` as a possibility.
```
error[E0423]: expected value, found type parameter `T`
--> $DIR/issue-69654.rs:5:25
|
LL | impl<T> Bar<T> for [u8; T] {}
| - ^ not a value
| |
| found this type parameter
|
help: you might have meant to write a const parameter here
|
LL | impl<const T: /* Type */> Bar<T> for [u8; T] {}
| +++++ ++++++++++++
```
This commit is contained in:
parent
2f1bd3f378
commit
15d8e9ea66
3 changed files with 52 additions and 1 deletions
|
|
@ -867,6 +867,19 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
|
|||
pub applicability: Applicability,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(
|
||||
resolve_unexpected_res_change_ty_to_const_param_sugg,
|
||||
applicability = "has-placeholders",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub(crate) struct UnexpectedResChangeTyParamToConstParamSugg {
|
||||
#[suggestion_part(code = "const ")]
|
||||
pub before: Span,
|
||||
#[suggestion_part(code = ": /* Type */")]
|
||||
pub after: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg,
|
||||
|
|
|
|||
|
|
@ -414,6 +414,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
|
||||
/// Handles error reporting for `smart_resolve_path_fragment` function.
|
||||
/// Creates base error and amends it with one short label and possibly some longer helps/notes.
|
||||
#[tracing::instrument(skip(self), level = "debug")]
|
||||
pub(crate) fn smart_resolve_report_errors(
|
||||
&mut self,
|
||||
path: &[Segment],
|
||||
|
|
@ -451,7 +452,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
err.span_suggestion_verbose(sugg.0, sugg.1, &sugg.2, Applicability::MaybeIncorrect);
|
||||
}
|
||||
|
||||
self.suggest_changing_type_to_const_param(&mut err, res, source, span);
|
||||
self.suggest_changing_type_to_const_param(&mut err, res, source, path, following_seg, span);
|
||||
self.explain_functions_in_pattern(&mut err, res, source);
|
||||
|
||||
if self.suggest_pattern_match_with_let(&mut err, source, span) {
|
||||
|
|
@ -1505,8 +1506,40 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||
err: &mut Diag<'_>,
|
||||
res: Option<Res>,
|
||||
source: PathSource<'_, '_, '_>,
|
||||
path: &[Segment],
|
||||
following_seg: Option<&Segment>,
|
||||
span: Span,
|
||||
) {
|
||||
if let PathSource::Expr(None) = source
|
||||
&& let Some(Res::Def(DefKind::TyParam, _)) = res
|
||||
&& following_seg.is_none()
|
||||
&& let [segment] = path
|
||||
{
|
||||
// We have something like
|
||||
// impl<T, N> From<[T; N]> for VecWrapper<T> {
|
||||
// fn from(slice: [T; N]) -> Self {
|
||||
// VecWrapper(slice.to_vec())
|
||||
// }
|
||||
// }
|
||||
// where `N` is a type param but should likely have been a const param.
|
||||
let Some(item) = self.diag_metadata.current_item else { return };
|
||||
let Some(generics) = item.kind.generics() else { return };
|
||||
let Some(span) = generics.params.iter().find_map(|param| {
|
||||
// Only consider type params with no bounds.
|
||||
if param.bounds.is_empty() && param.ident.name == segment.ident.name {
|
||||
Some(param.ident.span)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
err.subdiagnostic(errors::UnexpectedResChangeTyParamToConstParamSugg {
|
||||
before: span.shrink_to_lo(),
|
||||
after: span.shrink_to_hi(),
|
||||
});
|
||||
return;
|
||||
}
|
||||
let PathSource::Trait(_) = source else { return };
|
||||
|
||||
// We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway.
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ LL | impl<T> Bar<T> for [u8; T] {}
|
|||
| - ^ not a value
|
||||
| |
|
||||
| found this type parameter
|
||||
|
|
||||
help: you might have meant to write a const parameter here
|
||||
|
|
||||
LL | impl<const T: /* Type */> Bar<T> for [u8; T] {}
|
||||
| +++++ ++++++++++++
|
||||
|
||||
error[E0599]: the function or associated item `foo` exists for struct `Foo<_>`, but its trait bounds were not satisfied
|
||||
--> $DIR/issue-69654.rs:17:10
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue