Rollup merge of #80012 - sasurau4:feature/point-constant-identifier-E0435, r=petrochenkov

Add pointing const identifier when emitting E0435

Fix #79919
This commit is contained in:
Yuki Okushi 2021-01-08 02:05:58 +09:00 committed by GitHub
commit bb229b8f6c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 116 additions and 28 deletions

View File

@ -7,6 +7,12 @@ let foo = 42;
let a: [u8; foo]; // error: attempt to use a non-constant value in a constant 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: To fix this error, please replace the value with a constant. Example:
``` ```

View File

@ -398,13 +398,19 @@ impl<'a> Resolver<'a> {
err.help("use the `|| { ... }` closure form instead"); err.help("use the `|| { ... }` closure form instead");
err err
} }
ResolutionError::AttemptToUseNonConstantValueInConstant => { ResolutionError::AttemptToUseNonConstantValueInConstant(ident, sugg) => {
let mut err = struct_span_err!( let mut err = struct_span_err!(
self.session, self.session,
span, span,
E0435, E0435,
"attempt to use a non-constant value in a constant" "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.span_label(span, "non-constant value");
err err
} }

View File

@ -92,6 +92,12 @@ crate enum HasGenericParams {
No, No,
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
crate enum ConstantItemKind {
Const,
Static,
}
/// The rib kind restricts certain accesses, /// The rib kind restricts certain accesses,
/// e.g. to a `Res::Local` of an outer item. /// e.g. to a `Res::Local` of an outer item.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -119,7 +125,7 @@ crate enum RibKind<'a> {
/// ///
/// The `bool` indicates if this constant may reference generic parameters /// 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. /// 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. /// We passed through a module.
ModuleRibKind(Module<'a>), ModuleRibKind(Module<'a>),
@ -145,7 +151,7 @@ impl RibKind<'_> {
NormalRibKind NormalRibKind
| ClosureOrAsyncRibKind | ClosureOrAsyncRibKind
| FnItemRibKind | FnItemRibKind
| ConstantItemRibKind(_) | ConstantItemRibKind(..)
| ModuleRibKind(_) | ModuleRibKind(_)
| MacroDefinition(_) | MacroDefinition(_)
| ConstParamTyRibKind => false, | ConstParamTyRibKind => false,
@ -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, // Note that we might not be inside of an repeat expression here,
// but considering that `IsRepeatExpr` is only relevant for // but considering that `IsRepeatExpr` is only relevant for
// non-trivial constants this is doesn't matter. // 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( this.smart_resolve_path(
ty.id, ty.id,
qself.as_ref(), qself.as_ref(),
@ -843,7 +849,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
| ClosureOrAsyncRibKind | ClosureOrAsyncRibKind
| FnItemRibKind | FnItemRibKind
| ItemRibKind(..) | ItemRibKind(..)
| ConstantItemRibKind(_) | ConstantItemRibKind(..)
| ModuleRibKind(..) | ModuleRibKind(..)
| ForwardTyParamBanRibKind | ForwardTyParamBanRibKind
| ConstParamTyRibKind => { | ConstParamTyRibKind => {
@ -970,6 +976,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
this.with_constant_rib( this.with_constant_rib(
IsRepeatExpr::No, IsRepeatExpr::No,
true, true,
None,
|this| this.visit_expr(expr), |this| this.visit_expr(expr),
); );
} }
@ -1012,11 +1019,19 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.with_item_rib(HasGenericParams::No, |this| { self.with_item_rib(HasGenericParams::No, |this| {
this.visit_ty(ty); this.visit_ty(ty);
if let Some(expr) = expr { 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, // We already forbid generic params because of the above item rib,
// so it doesn't matter whether this is a trivial constant. // so it doesn't matter whether this is a trivial constant.
this.with_constant_rib(IsRepeatExpr::No, true, |this| { this.with_constant_rib(
this.visit_expr(expr) IsRepeatExpr::No,
}); true,
Some((item.ident, constant_item_kind)),
|this| this.visit_expr(expr),
);
} }
}); });
} }
@ -1118,15 +1133,16 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
&mut self, &mut self,
is_repeat: IsRepeatExpr, is_repeat: IsRepeatExpr,
is_trivial: bool, is_trivial: bool,
item: Option<(Ident, ConstantItemKind)>,
f: impl FnOnce(&mut Self), f: impl FnOnce(&mut Self),
) { ) {
debug!("with_constant_rib: is_repeat={:?} is_trivial={}", is_repeat, is_trivial); 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( this.with_rib(
TypeNS, TypeNS,
ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial), ConstantItemRibKind(is_repeat == IsRepeatExpr::Yes || is_trivial, item),
|this| { |this| {
this.with_label_rib(ConstantItemRibKind(is_trivial), f); this.with_label_rib(ConstantItemRibKind(is_trivial, item), f);
}, },
) )
}); });
@ -1266,6 +1282,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
this.with_constant_rib( this.with_constant_rib(
IsRepeatExpr::No, IsRepeatExpr::No,
true, true,
None,
|this| { |this| {
visit::walk_assoc_item( visit::walk_assoc_item(
this, this,
@ -2200,6 +2217,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
self.with_constant_rib( self.with_constant_rib(
is_repeat, is_repeat,
constant.value.is_potential_trivial_const_param(), constant.value.is_potential_trivial_const_param(),
None,
|this| { |this| {
visit::walk_anon_const(this, constant); visit::walk_anon_const(this, constant);
}, },

View File

@ -64,7 +64,7 @@ use tracing::debug;
use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding}; use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding};
use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion};
use imports::{Import, ImportKind, ImportResolver, NameResolution}; use imports::{Import, ImportKind, ImportResolver, NameResolution};
use late::{HasGenericParams, PathSource, Rib, RibKind::*}; use late::{ConstantItemKind, HasGenericParams, PathSource, Rib, RibKind::*};
use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
type Res = def::Res<NodeId>; type Res = def::Res<NodeId>;
@ -210,7 +210,7 @@ enum ResolutionError<'a> {
/// Error E0434: can't capture dynamic environment in a fn item. /// Error E0434: can't capture dynamic environment in a fn item.
CannotCaptureDynamicEnvironmentInFnItem, CannotCaptureDynamicEnvironmentInFnItem,
/// Error E0435: attempt to use a non-constant value in a constant. /// Error E0435: attempt to use a non-constant value in a constant.
AttemptToUseNonConstantValueInConstant, AttemptToUseNonConstantValueInConstant(Ident, String),
/// Error E0530: `X` bindings cannot shadow `Y`s. /// Error E0530: `X` bindings cannot shadow `Y`s.
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>), BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
/// Error E0128: type parameters with a default cannot use forward-declared identifiers. /// Error E0128: type parameters with a default cannot use forward-declared identifiers.
@ -1837,14 +1837,16 @@ impl<'a> Resolver<'a> {
// Use the rib kind to determine whether we are resolving parameters // Use the rib kind to determine whether we are resolving parameters
// (macro 2.0 hygiene) or local variables (`macro_rules` hygiene). // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident }; 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. // The ident resolves to a type parameter or local variable.
return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs( return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
i, i,
rib_ident, rib_ident,
res, *res,
record_used, record_used,
path_span, path_span,
*original_rib_ident_def,
ribs, ribs,
))); )));
} }
@ -2556,6 +2558,7 @@ impl<'a> Resolver<'a> {
mut res: Res, mut res: Res,
record_used: bool, record_used: bool,
span: Span, span: Span,
original_rib_ident_def: Ident,
all_ribs: &[Rib<'a>], all_ribs: &[Rib<'a>],
) -> Res { ) -> Res {
const CG_BUG_STR: &str = "min_const_generics resolve check didn't stop compilation"; const CG_BUG_STR: &str = "min_const_generics resolve check didn't stop compilation";
@ -2602,10 +2605,31 @@ impl<'a> Resolver<'a> {
res_err = Some(CannotCaptureDynamicEnvironmentInFnItem); res_err = Some(CannotCaptureDynamicEnvironmentInFnItem);
} }
} }
ConstantItemRibKind(_) => { ConstantItemRibKind(_, item) => {
// Still doesn't deal with upvars // Still doesn't deal with upvars
if record_used { 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; return Res::Err;
} }
@ -2641,7 +2665,7 @@ impl<'a> Resolver<'a> {
in_ty_param_default = true; in_ty_param_default = true;
continue; continue;
} }
ConstantItemRibKind(trivial) => { ConstantItemRibKind(trivial, _) => {
let features = self.session.features_untracked(); let features = self.session.features_untracked();
// HACK(min_const_generics): We currently only allow `N` or `{ N }`. // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
if !(trivial if !(trivial
@ -2734,7 +2758,7 @@ impl<'a> Resolver<'a> {
in_ty_param_default = true; in_ty_param_default = true;
continue; continue;
} }
ConstantItemRibKind(trivial) => { ConstantItemRibKind(trivial, _) => {
let features = self.session.features_untracked(); let features = self.session.features_untracked();
// HACK(min_const_generics): We currently only allow `N` or `{ N }`. // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
if !(trivial if !(trivial

View File

@ -1,6 +1,8 @@
error[E0435]: attempt to use a non-constant value in a constant error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/E0435.rs:3:17 --> $DIR/E0435.rs:3:17
| |
LL | let foo = 42u32;
| --- help: consider using `const` instead of `let`
LL | let _: [u8; foo]; LL | let _: [u8; foo];
| ^^^ non-constant value | ^^^ non-constant value

View File

@ -2,25 +2,33 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/bindings.rs:5:29 --> $DIR/bindings.rs:5:29
| |
LL | const foo: impl Clone = x; 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/bindings.rs:11:33 --> $DIR/bindings.rs:11:33
| |
LL | const foo: impl Clone = x; 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/bindings.rs:18:33 --> $DIR/bindings.rs:18:33
| |
LL | const foo: impl Clone = x; 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/bindings.rs:25:33 --> $DIR/bindings.rs:25:33
| |
LL | const foo: impl Clone = x; 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 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 --> $DIR/bindings.rs:1:12

View File

@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-27433.rs:3:23 --> $DIR/issue-27433.rs:3:23
| |
LL | const FOO : u32 = foo; LL | const FOO : u32 = foo;
| ^^^ non-constant value | --- ^^^ non-constant value
| |
| help: consider using `let` instead of `const`
error: aborting due to previous error error: aborting due to previous error

View File

@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-3521-2.rs:4:23 --> $DIR/issue-3521-2.rs:4:23
| |
LL | static y: isize = foo + 1; 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 error: aborting due to previous error

View File

@ -1,6 +1,9 @@
error[E0435]: attempt to use a non-constant value in a constant error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-3521.rs:6:15 --> $DIR/issue-3521.rs:6:15
| |
LL | let foo = 100;
| --- help: consider using `const` instead of `let`
...
LL | Bar = foo LL | Bar = foo
| ^^^ non-constant value | ^^^ non-constant value

View File

@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-3668-2.rs:2:27 --> $DIR/issue-3668-2.rs:2:27
| |
LL | static child: isize = x + 1; 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 error: aborting due to previous error

View File

@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-3668.rs:8:34 --> $DIR/issue-3668.rs:8:34
| |
LL | static childVal: Box<P> = self.child.get(); 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 error: aborting due to previous error

View File

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

View File

@ -1,6 +1,9 @@
error[E0435]: attempt to use a non-constant value in a constant error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-44239.rs:6:26 --> $DIR/issue-44239.rs:6:26
| |
LL | let n = 0;
| - help: consider using `const` instead of `let`
...
LL | const N: usize = n; LL | const N: usize = n;
| ^ non-constant value | ^ non-constant value

View File

@ -1,6 +1,8 @@
error[E0435]: attempt to use a non-constant value in a constant error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/non-constant-expr-for-arr-len.rs:5:22 --> $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]; LL | let _x = [0; n];
| ^ non-constant value | ^ non-constant value

View File

@ -1,6 +1,8 @@
error[E0435]: attempt to use a non-constant value in a constant error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/repeat_count.rs:5:17 --> $DIR/repeat_count.rs:5:17
| |
LL | let n = 1;
| - help: consider using `const` instead of `let`
LL | let a = [0; n]; LL | let a = [0; n];
| ^ non-constant value | ^ non-constant value

View File

@ -2,7 +2,9 @@ error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/type-dependent-def-issue-49241.rs:3:22 --> $DIR/type-dependent-def-issue-49241.rs:3:22
| |
LL | const l: usize = v.count(); LL | const l: usize = v.count();
| ^ non-constant value | - ^ non-constant value
| |
| help: consider using `let` instead of `const`
error: aborting due to previous error error: aborting due to previous error