Skip to content

Suggest defining const parameter when appropriate #110041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3458,8 +3458,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
sugg.to_string(),
Applicability::MaybeIncorrect,
))
} else if res.is_none() && matches!(source, PathSource::Type) {
this.report_missing_type_error(path)
} else if res.is_none() && let PathSource::Type | PathSource::Expr(_) = source {
this.suggest_adding_generic_parameter(path, source)
} else {
None
};
Expand Down
15 changes: 10 additions & 5 deletions compiler/rustc_resolve/src/late/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2110,9 +2110,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
}
}

pub(crate) fn report_missing_type_error(
pub(crate) fn suggest_adding_generic_parameter(
&self,
path: &[Segment],
source: PathSource<'_>,
) -> Option<(Span, &'static str, String, Applicability)> {
let (ident, span) = match path {
[segment]
Expand Down Expand Up @@ -2148,7 +2149,6 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// Without the 2nd `true`, we'd suggest `impl <T>` for `impl T` when a type `T` isn't found
| (Some(Item { kind: kind @ ItemKind::Impl(..), .. }), true, true)
| (Some(Item { kind, .. }), false, _) => {
// Likely missing type parameter.
if let Some(generics) = kind.generics() {
if span.overlaps(generics.span) {
// Avoid the following:
Expand All @@ -2161,7 +2161,12 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
// | not found in this scope
return None;
}
let msg = "you might be missing a type parameter";

let (msg, sugg) = match source {
PathSource::Type => ("you might be missing a type parameter", ident),
PathSource::Expr(_) => ("you might be missing a const parameter", format!("const {ident}: /* Type */")),
_ => return None,
};
let (span, sugg) = if let [.., param] = &generics.params[..] {
let span = if let [.., bound] = &param.bounds[..] {
bound.span()
Expand All @@ -2172,9 +2177,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
} else {
param.ident.span
};
(span, format!(", {}", ident))
(span, format!(", {sugg}"))
} else {
(generics.span, format!("<{}>", ident))
(generics.span, format!("<{sugg}>"))
};
// Do not suggest if this is coming from macro expansion.
if span.can_be_used_for_suggestions() {
Expand Down
24 changes: 24 additions & 0 deletions tests/ui/missing/missing-items/missing-const-parameter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
struct Struct<const N: usize>;

impl Struct<{ N }> {}
//~^ ERROR cannot find value `N` in this scope
//~| HELP you might be missing a const parameter

fn func0(_: Struct<{ N }>) {}
//~^ ERROR cannot find value `N` in this scope
//~| HELP you might be missing a const parameter

fn func1(_: [u8; N]) {}
//~^ ERROR cannot find value `N` in this scope
//~| HELP you might be missing a const parameter

fn func2<T>(_: [T; N]) {}
//~^ ERROR cannot find value `N` in this scope
//~| HELP you might be missing a const parameter

struct Image<const R: usize>([[u32; C]; R]);
//~^ ERROR cannot find value `C` in this scope
//~| HELP a const parameter with a similar name exists
//~| HELP you might be missing a const parameter

fn main() {}
64 changes: 64 additions & 0 deletions tests/ui/missing/missing-items/missing-const-parameter.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
error[E0425]: cannot find value `N` in this scope
--> $DIR/missing-const-parameter.rs:3:15
|
LL | impl Struct<{ N }> {}
| ^ not found in this scope
|
help: you might be missing a const parameter
|
LL | impl<const N: /* Type */> Struct<{ N }> {}
| +++++++++++++++++++++

error[E0425]: cannot find value `N` in this scope
--> $DIR/missing-const-parameter.rs:7:22
|
LL | fn func0(_: Struct<{ N }>) {}
| ^ not found in this scope
|
help: you might be missing a const parameter
|
LL | fn func0<const N: /* Type */>(_: Struct<{ N }>) {}
| +++++++++++++++++++++

error[E0425]: cannot find value `N` in this scope
--> $DIR/missing-const-parameter.rs:11:18
|
LL | fn func1(_: [u8; N]) {}
| ^ not found in this scope
|
help: you might be missing a const parameter
|
LL | fn func1<const N: /* Type */>(_: [u8; N]) {}
| +++++++++++++++++++++

error[E0425]: cannot find value `N` in this scope
--> $DIR/missing-const-parameter.rs:15:20
|
LL | fn func2<T>(_: [T; N]) {}
| ^ not found in this scope
|
help: you might be missing a const parameter
|
LL | fn func2<T, const N: /* Type */>(_: [T; N]) {}
| +++++++++++++++++++++

error[E0425]: cannot find value `C` in this scope
--> $DIR/missing-const-parameter.rs:19:37
|
LL | struct Image<const R: usize>([[u32; C]; R]);
| - ^
| |
| similarly named const parameter `R` defined here
|
help: a const parameter with a similar name exists
|
LL | struct Image<const R: usize>([[u32; R]; R]);
| ~
help: you might be missing a const parameter
|
LL | struct Image<const R: usize, const C: /* Type */>([[u32; C]; R]);
| +++++++++++++++++++++

error: aborting due to 5 previous errors

For more information about this error, try `rustc --explain E0425`.