about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2021-01-08 02:05:58 +0900
committerGitHub <noreply@github.com>2021-01-08 02:05:58 +0900
commitbb229b8f6c5dcf2acfdd1cc1e54d657cd5b3cacd (patch)
treef6fd509f8b72d32b7b6888c611440e778bdde94a
parentb5c496de374407c0937cf5257d89230b5358d053 (diff)
parentc71348a9c6d8c27c4d0a39428b7478c19b0c97d9 (diff)
Rollup merge of #80012 - sasurau4:feature/point-constant-identifier-E0435, r=petrochenkov
Add pointing const identifier when emitting E0435

Fix #79919
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0435.md6
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs8
-rw-r--r--compiler/rustc_resolve/src/late.rs38
-rw-r--r--compiler/rustc_resolve/src/lib.rs40
-rw-r--r--src/test/ui/error-codes/E0435.stderr2
-rw-r--r--src/test/ui/impl-trait/bindings.stderr16
-rw-r--r--src/test/ui/issues/issue-27433.stderr4
-rw-r--r--src/test/ui/issues/issue-3521-2.stderr4
-rw-r--r--src/test/ui/issues/issue-3521.stderr3
-rw-r--r--src/test/ui/issues/issue-3668-2.stderr4
-rw-r--r--src/test/ui/issues/issue-3668.stderr4
-rw-r--r--src/test/ui/issues/issue-42060.stderr4
-rw-r--r--src/test/ui/issues/issue-44239.stderr3
-rw-r--r--src/test/ui/non-constant-expr-for-arr-len.stderr2
-rw-r--r--src/test/ui/repeat_count.stderr2
-rw-r--r--src/test/ui/type/type-dependent-def-issue-49241.stderr4
16 files changed, 116 insertions, 28 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes/E0435.md b/compiler/rustc_error_codes/src/error_codes/E0435.md
index 424e5ce1e2e..798a20d48b6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0435.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0435.md
@@ -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:
 
 ```
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 809de9beff6..6a181dbab5a 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -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
             }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 2e738ce8dac..4d956e7f0d2 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -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)]
@@ -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>),
@@ -145,7 +151,7 @@ impl RibKind<'_> {
             NormalRibKind
             | ClosureOrAsyncRibKind
             | FnItemRibKind
-            | ConstantItemRibKind(_)
+            | ConstantItemRibKind(..)
             | ModuleRibKind(_)
             | MacroDefinition(_)
             | 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,
                             // 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(),
@@ -843,7 +849,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 | ClosureOrAsyncRibKind
                 | FnItemRibKind
                 | ItemRibKind(..)
-                | ConstantItemRibKind(_)
+                | ConstantItemRibKind(..)
                 | ModuleRibKind(..)
                 | ForwardTyParamBanRibKind
                 | ConstParamTyRibKind => {
@@ -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),
                                             );
                                         }
@@ -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),
+                        );
                     }
                 });
             }
@@ -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);
                 },
             )
         });
@@ -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,
@@ -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);
             },
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index dba30f66640..a6d0240b6fd 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -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>;
@@ -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.
@@ -1837,14 +1837,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,
                 )));
             }
@@ -2556,6 +2558,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";
@@ -2602,10 +2605,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;
                         }
@@ -2641,7 +2665,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
@@ -2734,7 +2758,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
diff --git a/src/test/ui/error-codes/E0435.stderr b/src/test/ui/error-codes/E0435.stderr
index 349aa0d07c5..21827d1fd87 100644
--- a/src/test/ui/error-codes/E0435.stderr
+++ b/src/test/ui/error-codes/E0435.stderr
@@ -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
 
diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr
index e983fdecdba..ad5f13d0672 100644
--- a/src/test/ui/impl-trait/bindings.stderr
+++ b/src/test/ui/impl-trait/bindings.stderr
@@ -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
diff --git a/src/test/ui/issues/issue-27433.stderr b/src/test/ui/issues/issue-27433.stderr
index e232d17e6d7..201b7e8549c 100644
--- a/src/test/ui/issues/issue-27433.stderr
+++ b/src/test/ui/issues/issue-27433.stderr
@@ -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
 
diff --git a/src/test/ui/issues/issue-3521-2.stderr b/src/test/ui/issues/issue-3521-2.stderr
index d54bbbcdc33..ba29d1becb8 100644
--- a/src/test/ui/issues/issue-3521-2.stderr
+++ b/src/test/ui/issues/issue-3521-2.stderr
@@ -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
 
diff --git a/src/test/ui/issues/issue-3521.stderr b/src/test/ui/issues/issue-3521.stderr
index ae199875269..8473526006c 100644
--- a/src/test/ui/issues/issue-3521.stderr
+++ b/src/test/ui/issues/issue-3521.stderr
@@ -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
 
diff --git a/src/test/ui/issues/issue-3668-2.stderr b/src/test/ui/issues/issue-3668-2.stderr
index d6a6e837960..7cee497b0bc 100644
--- a/src/test/ui/issues/issue-3668-2.stderr
+++ b/src/test/ui/issues/issue-3668-2.stderr
@@ -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
 
diff --git a/src/test/ui/issues/issue-3668.stderr b/src/test/ui/issues/issue-3668.stderr
index 98cd3631a53..e45472929ab 100644
--- a/src/test/ui/issues/issue-3668.stderr
+++ b/src/test/ui/issues/issue-3668.stderr
@@ -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
 
diff --git a/src/test/ui/issues/issue-42060.stderr b/src/test/ui/issues/issue-42060.stderr
index 72408c79194..dc089b856bb 100644
--- a/src/test/ui/issues/issue-42060.stderr
+++ b/src/test/ui/issues/issue-42060.stderr
@@ -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
 
diff --git a/src/test/ui/issues/issue-44239.stderr b/src/test/ui/issues/issue-44239.stderr
index bc5a6a03f03..bbd3d116c96 100644
--- a/src/test/ui/issues/issue-44239.stderr
+++ b/src/test/ui/issues/issue-44239.stderr
@@ -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
 
diff --git a/src/test/ui/non-constant-expr-for-arr-len.stderr b/src/test/ui/non-constant-expr-for-arr-len.stderr
index b947cb7e19c..01da6bcf49a 100644
--- a/src/test/ui/non-constant-expr-for-arr-len.stderr
+++ b/src/test/ui/non-constant-expr-for-arr-len.stderr
@@ -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
 
diff --git a/src/test/ui/repeat_count.stderr b/src/test/ui/repeat_count.stderr
index 5fcda348ab3..aa1b2e60d51 100644
--- a/src/test/ui/repeat_count.stderr
+++ b/src/test/ui/repeat_count.stderr
@@ -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
 
diff --git a/src/test/ui/type/type-dependent-def-issue-49241.stderr b/src/test/ui/type/type-dependent-def-issue-49241.stderr
index c5dcfa7a431..df791435e88 100644
--- a/src/test/ui/type/type-dependent-def-issue-49241.stderr
+++ b/src/test/ui/type/type-dependent-def-issue-49241.stderr
@@ -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
    |
 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