Skip to content
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

Add pointing const identifier when emitting E0435 #80012

Merged
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
6 changes: 6 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0435.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ let foo = 42;
let a: [u8; foo]; // error: attempt to use a non-constant value in a constant
```

'constant' means 'a compile-time value'.

More details can be found in the [Variables and Mutability] section of the book.

[Variables and Mutability]: https://doc.rust-lang.org/book/ch03-01-variables-and-mutability.html#differences-between-variables-and-constants

To fix this error, please replace the value with a constant. Example:

```
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_resolve/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,13 +398,19 @@ impl<'a> Resolver<'a> {
err.help("use the `|| { ... }` closure form instead");
err
}
ResolutionError::AttemptToUseNonConstantValueInConstant => {
ResolutionError::AttemptToUseNonConstantValueInConstant(ident, sugg) => {
let mut err = struct_span_err!(
self.session,
span,
E0435,
"attempt to use a non-constant value in a constant"
);
err.span_suggestion(
ident.span,
&sugg,
"".to_string(),
Applicability::MaybeIncorrect,
);
err.span_label(span, "non-constant value");
err
}
Expand Down
38 changes: 28 additions & 10 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ crate enum HasGenericParams {
No,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
crate enum ConstantItemKind {
Const,
Static,
}

/// The rib kind restricts certain accesses,
/// e.g. to a `Res::Local` of an outer item.
#[derive(Copy, Clone, Debug)]
Expand Down Expand Up @@ -119,7 +125,7 @@ crate enum RibKind<'a> {
///
/// The `bool` indicates if this constant may reference generic parameters
/// and is used to only allow generic parameters to be used in trivial constant expressions.
ConstantItemRibKind(bool),
ConstantItemRibKind(bool, Option<(Ident, ConstantItemKind)>),

/// We passed through a module.
ModuleRibKind(Module<'a>),
Expand All @@ -145,7 +151,7 @@ impl RibKind<'_> {
NormalRibKind
| ClosureOrAsyncRibKind
| FnItemRibKind
| ConstantItemRibKind(_)
| ConstantItemRibKind(..)
| ModuleRibKind(_)
| MacroDefinition(_)
| ConstParamTyRibKind => false,
Expand Down Expand Up @@ -634,7 +640,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
// Note that we might not be inside of an repeat expression here,
// but considering that `IsRepeatExpr` is only relevant for
// non-trivial constants this is doesn't matter.
self.with_constant_rib(IsRepeatExpr::No, true, |this| {
self.with_constant_rib(IsRepeatExpr::No, true, None, |this| {
this.smart_resolve_path(
ty.id,
qself.as_ref(),
Expand Down Expand Up @@ -843,7 +849,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
| ClosureOrAsyncRibKind
| FnItemRibKind
| ItemRibKind(..)
| ConstantItemRibKind(_)
| ConstantItemRibKind(..)
| ModuleRibKind(..)
| ForwardTyParamBanRibKind
| ConstParamTyRibKind => {
Expand Down Expand Up @@ -970,6 +976,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
this.with_constant_rib(
IsRepeatExpr::No,
true,
None,
|this| this.visit_expr(expr),
);
}
Expand Down Expand Up @@ -1012,11 +1019,19 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.with_item_rib(HasGenericParams::No, |this| {
this.visit_ty(ty);
if let Some(expr) = expr {
let constant_item_kind = match item.kind {
ItemKind::Const(..) => ConstantItemKind::Const,
ItemKind::Static(..) => ConstantItemKind::Static,
_ => unreachable!(),
};
// We already forbid generic params because of the above item rib,
// so it doesn't matter whether this is a trivial constant.
this.with_constant_rib(IsRepeatExpr::No, true, |this| {
this.visit_expr(expr)
});
this.with_constant_rib(
IsRepeatExpr::No,
true,
Some((item.ident, constant_item_kind)),
|this| this.visit_expr(expr),
);
}
});
}
Expand Down Expand Up @@ -1118,15 +1133,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&mut self,
is_repeat: IsRepeatExpr,
is_trivial: bool,
item: Option<(Ident, ConstantItemKind)>,
f: impl FnOnce(&mut Self),
) {
debug!("with_constant_rib: is_repeat={:?} is_trivial={}", is_repeat, is_trivial);
self.with_rib(ValueNS, ConstantItemRibKind(is_trivial), |this| {
self.with_rib(ValueNS, ConstantItemRibKind(is_trivial, item), |this| {
this.with_rib(
TypeNS,
ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial),
ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial, item),
|this| {
this.with_label_rib(ConstantItemRibKind(is_trivial), f);
this.with_label_rib(ConstantItemRibKind(is_trivial, item), f);
},
)
});
Expand Down Expand Up @@ -1266,6 +1282,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
this.with_constant_rib(
IsRepeatExpr::No,
true,
None,
|this| {
visit::walk_assoc_item(
this,
Expand Down Expand Up @@ -2200,6 +2217,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.with_constant_rib(
is_repeat,
constant.value.is_potential_trivial_const_param(),
None,
|this| {
visit::walk_anon_const(this, constant);
},
Expand Down
40 changes: 32 additions & 8 deletions compiler/rustc_resolve/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ use tracing::debug;
use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding};
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
use imports::{Import, ImportKind, ImportResolver, NameResolution};
use late::{HasGenericParams, PathSource, Rib, RibKind::*};
use late::{ConstantItemKind, HasGenericParams, PathSource, Rib, RibKind::*};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};

type Res = def::Res<NodeId>;
Expand Down Expand Up @@ -210,7 +210,7 @@ enum ResolutionError<'a> {
/// Error E0434: can't capture dynamic environment in a fn item.
CannotCaptureDynamicEnvironmentInFnItem,
/// Error E0435: attempt to use a non-constant value in a constant.
AttemptToUseNonConstantValueInConstant,
AttemptToUseNonConstantValueInConstant(Ident, String),
/// Error E0530: `X` bindings cannot shadow `Y`s.
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
Expand Down Expand Up @@ -1821,14 +1821,16 @@ impl<'a> Resolver<'a> {
// Use the rib kind to determine whether we are resolving parameters
// (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident };
if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() {
if let Some((original_rib_ident_def, res)) = ribs[i].bindings.get_key_value(&rib_ident)
{
// The ident resolves to a type parameter or local variable.
return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
i,
rib_ident,
res,
*res,
record_used,
path_span,
*original_rib_ident_def,
ribs,
)));
}
Expand Down Expand Up @@ -2540,6 +2542,7 @@ impl<'a> Resolver<'a> {
mut res: Res,
record_used: bool,
span: Span,
original_rib_ident_def: Ident,
all_ribs: &[Rib<'a>],
) -> Res {
const CG_BUG_STR: &str = "min_const_generics resolve check didn't stop compilation";
Expand Down Expand Up @@ -2586,10 +2589,31 @@ impl<'a> Resolver<'a> {
res_err = Some(CannotCaptureDynamicEnvironmentInFnItem);
}
}
ConstantItemRibKind(_) => {
ConstantItemRibKind(_, item) => {
// Still doesn't deal with upvars
if record_used {
self.report_error(span, AttemptToUseNonConstantValueInConstant);
let (span, resolution_error) =
if let Some((ident, constant_item_kind)) = item {
let kind_str = match constant_item_kind {
ConstantItemKind::Const => "const",
ConstantItemKind::Static => "static",
};
let sugg = format!(
"consider using `let` instead of `{}`",
kind_str
);
(span, AttemptToUseNonConstantValueInConstant(ident, sugg))
} else {
let sugg = "consider using `const` instead of `let`";
(
rib_ident.span,
AttemptToUseNonConstantValueInConstant(
original_rib_ident_def,
sugg.to_string(),
),
)
};
self.report_error(span, resolution_error);
}
return Res::Err;
}
Expand Down Expand Up @@ -2625,7 +2649,7 @@ impl<'a> Resolver<'a> {
in_ty_param_default = true;
continue;
}
ConstantItemRibKind(trivial) => {
ConstantItemRibKind(trivial, _) => {
let features = self.session.features_untracked();
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
if !(trivial
Expand Down Expand Up @@ -2718,7 +2742,7 @@ impl<'a> Resolver<'a> {
in_ty_param_default = true;
continue;
}
ConstantItemRibKind(trivial) => {
ConstantItemRibKind(trivial, _) => {
let features = self.session.features_untracked();
// HACK(min_const_generics): We currently only allow `N` or `{ N }`.
if !(trivial
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/error-codes/E0435.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/E0435.rs:3:17
|
LL | let foo = 42u32;
| --- help: consider using `const` instead of `let`
LL | let _: [u8; foo];
| ^^^ non-constant value

Expand Down
16 changes: 12 additions & 4 deletions src/test/ui/impl-trait/bindings.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,33 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/bindings.rs:5:29
|
LL | const foo: impl Clone = x;
| ^ non-constant value
| --- ^ non-constant value
| |
| help: consider using `let` instead of `const`

error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/bindings.rs:11:33
|
LL | const foo: impl Clone = x;
| ^ non-constant value
| --- ^ non-constant value
| |
| help: consider using `let` instead of `const`

error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/bindings.rs:18:33
|
LL | const foo: impl Clone = x;
| ^ non-constant value
| --- ^ non-constant value
| |
| help: consider using `let` instead of `const`

error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/bindings.rs:25:33
|
LL | const foo: impl Clone = x;
| ^ non-constant value
| --- ^ non-constant value
| |
| help: consider using `let` instead of `const`

warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes
--> $DIR/bindings.rs:1:12
Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/issues/issue-27433.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-27433.rs:3:23
|
LL | const FOO : u32 = foo;
| ^^^ non-constant value
| --- ^^^ non-constant value
| |
| help: consider using `let` instead of `const`

error: aborting due to previous error

Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/issues/issue-3521-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-3521-2.rs:4:23
|
LL | static y: isize = foo + 1;
| ^^^ non-constant value
| - ^^^ non-constant value
| |
| help: consider using `let` instead of `static`

error: aborting due to previous error

Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/issues/issue-3521.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-3521.rs:6:15
|
LL | let foo = 100;
| --- help: consider using `const` instead of `let`
...
LL | Bar = foo
| ^^^ non-constant value

Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/issues/issue-3668-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-3668-2.rs:2:27
|
LL | static child: isize = x + 1;
| ^ non-constant value
| ----- ^ non-constant value
| |
| help: consider using `let` instead of `static`

error: aborting due to previous error

Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/issues/issue-3668.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-3668.rs:8:34
|
LL | static childVal: Box<P> = self.child.get();
| ^^^^ non-constant value
| -------- ^^^^ non-constant value
| |
| help: consider using `let` instead of `static`

error: aborting due to previous error

Expand Down
4 changes: 4 additions & 0 deletions src/test/ui/issues/issue-42060.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-42060.rs:3:23
|
LL | let thing = ();
| ----- help: consider using `const` instead of `let`
LL | let other: typeof(thing) = thing;
| ^^^^^ non-constant value

error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-42060.rs:9:13
|
LL | let q = 1;
| - help: consider using `const` instead of `let`
LL | <typeof(q)>::N
| ^ non-constant value

Expand Down
3 changes: 3 additions & 0 deletions src/test/ui/issues/issue-44239.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-44239.rs:6:26
|
LL | let n = 0;
| - help: consider using `const` instead of `let`
...
LL | const N: usize = n;
| ^ non-constant value

Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/non-constant-expr-for-arr-len.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/non-constant-expr-for-arr-len.rs:5:22
|
LL | fn bar(n: usize) {
| - help: consider using `const` instead of `let`
LL | let _x = [0; n];
| ^ non-constant value

Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/repeat_count.stderr
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/repeat_count.rs:5:17
|
LL | let n = 1;
| - help: consider using `const` instead of `let`
LL | let a = [0; n];
| ^ non-constant value

Expand Down
Loading