Skip to content

Commit 18c62b5

Browse files
Rollup merge of #151077 - issue-84327, r=fmease
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] {} | +++++ ++++++ ``` Addresses "case 3" from #84327.
2 parents be22fe2 + 15d8e9e commit 18c62b5

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

‎compiler/rustc_resolve/src/errors.rs‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -867,6 +867,19 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
867867
pub applicability: Applicability,
868868
}
869869

870+
#[derive(Subdiagnostic)]
871+
#[multipart_suggestion(
872+
resolve_unexpected_res_change_ty_to_const_param_sugg,
873+
applicability = "has-placeholders",
874+
style = "verbose"
875+
)]
876+
pub(crate) struct UnexpectedResChangeTyParamToConstParamSugg {
877+
#[suggestion_part(code = "const ")]
878+
pub before: Span,
879+
#[suggestion_part(code = ": /* Type */")]
880+
pub after: Span,
881+
}
882+
870883
#[derive(Subdiagnostic)]
871884
#[suggestion(
872885
resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg,

‎compiler/rustc_resolve/src/late/diagnostics.rs‎

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
414414

415415
/// Handles error reporting for `smart_resolve_path_fragment` function.
416416
/// Creates base error and amends it with one short label and possibly some longer helps/notes.
417+
#[tracing::instrument(skip(self), level = "debug")]
417418
pub(crate) fn smart_resolve_report_errors(
418419
&mut self,
419420
path: &[Segment],
@@ -451,7 +452,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
451452
err.span_suggestion_verbose(sugg.0, sugg.1, &sugg.2, Applicability::MaybeIncorrect);
452453
}
453454

454-
self.suggest_changing_type_to_const_param(&mut err, res, source, span);
455+
self.suggest_changing_type_to_const_param(&mut err, res, source, path, following_seg, span);
455456
self.explain_functions_in_pattern(&mut err, res, source);
456457

457458
if self.suggest_pattern_match_with_let(&mut err, source, span) {
@@ -1505,8 +1506,40 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
15051506
err: &mut Diag<'_>,
15061507
res: Option<Res>,
15071508
source: PathSource<'_, '_, '_>,
1509+
path: &[Segment],
1510+
following_seg: Option<&Segment>,
15081511
span: Span,
15091512
) {
1513+
if let PathSource::Expr(None) = source
1514+
&& let Some(Res::Def(DefKind::TyParam, _)) = res
1515+
&& following_seg.is_none()
1516+
&& let [segment] = path
1517+
{
1518+
// We have something like
1519+
// impl<T, N> From<[T; N]> for VecWrapper<T> {
1520+
// fn from(slice: [T; N]) -> Self {
1521+
// VecWrapper(slice.to_vec())
1522+
// }
1523+
// }
1524+
// where `N` is a type param but should likely have been a const param.
1525+
let Some(item) = self.diag_metadata.current_item else { return };
1526+
let Some(generics) = item.kind.generics() else { return };
1527+
let Some(span) = generics.params.iter().find_map(|param| {
1528+
// Only consider type params with no bounds.
1529+
if param.bounds.is_empty() && param.ident.name == segment.ident.name {
1530+
Some(param.ident.span)
1531+
} else {
1532+
None
1533+
}
1534+
}) else {
1535+
return;
1536+
};
1537+
err.subdiagnostic(errors::UnexpectedResChangeTyParamToConstParamSugg {
1538+
before: span.shrink_to_lo(),
1539+
after: span.shrink_to_hi(),
1540+
});
1541+
return;
1542+
}
15101543
let PathSource::Trait(_) = source else { return };
15111544

15121545
// We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway.

‎tests/ui/const-generics/generic_const_exprs/issue-69654.stderr‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ LL | impl<T> Bar<T> for [u8; T] {}
55
| - ^ not a value
66
| |
77
| found this type parameter
8+
|
9+
help: you might have meant to write a const parameter here
10+
|
11+
LL | impl<const T: /* Type */> Bar<T> for [u8; T] {}
12+
| +++++ ++++++++++++
813

914
error[E0599]: the function or associated item `foo` exists for struct `Foo<_>`, but its trait bounds were not satisfied
1015
--> $DIR/issue-69654.rs:17:10

0 commit comments

Comments
 (0)