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:
Esteban Küber 2026-01-13 19:33:40 +00:00
parent 2f1bd3f378
commit 15d8e9ea66
3 changed files with 52 additions and 1 deletions

View file

@ -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,

View file

@ -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.

View file

@ -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