diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f879e548f2754..09221041031a2 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -819,7 +819,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { self.dcx().create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span }) } - ResolutionError::AttemptToUseNonConstantValueInConstant(ident, suggestion, current) => { + ResolutionError::AttemptToUseNonConstantValueInConstant { + ident, + suggestion, + current, + type_span, + } => { // let foo =... // ^^^ given this Span // ------- get this Span to have an applicable suggestion @@ -844,6 +849,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { span: sp, suggestion, current, + type_span, }), Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion {span})), None, ) diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index a4bdd62acbbda..79c76e7a976a7 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -240,16 +240,18 @@ pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> { } #[derive(Subdiagnostic)] -#[suggestion( +#[multipart_suggestion( resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion, - code = "{suggestion} ", style = "verbose", - applicability = "maybe-incorrect" + applicability = "has-placeholders" )] pub(crate) struct AttemptToUseNonConstantValueInConstantWithSuggestion<'a> { - #[primary_span] + // #[primary_span] + #[suggestion_part(code = "{suggestion} ")] pub(crate) span: Span, pub(crate) suggestion: &'a str, + #[suggestion_part(code = ": /* Type */")] + pub(crate) type_span: Option, pub(crate) current: &'a str, } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 7d531385e2120..f1934ff184bc3 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1178,21 +1178,41 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(span) = finalize { let (span, resolution_error) = match item { None if rib_ident.as_str() == "self" => (span, LowercaseSelf), - None => ( - rib_ident.span, - AttemptToUseNonConstantValueInConstant( - original_rib_ident_def, - "const", - "let", - ), - ), + None => { + // If we have a `let name = expr;`, we have the span for + // `name` and use that to see if it is followed by a type + // specifier. If not, then we know we need to suggest + // `const name: Ty = expr;`. This is a heuristic, it will + // break down in the presence of macros. + let sm = self.tcx.sess.source_map(); + let type_span = match sm.span_look_ahead( + original_rib_ident_def.span, + ":", + None, + ) { + None => { + Some(original_rib_ident_def.span.shrink_to_hi()) + } + Some(_) => None, + }; + ( + rib_ident.span, + AttemptToUseNonConstantValueInConstant { + ident: original_rib_ident_def, + suggestion: "const", + current: "let", + type_span, + }, + ) + } Some((ident, kind)) => ( span, - AttemptToUseNonConstantValueInConstant( + AttemptToUseNonConstantValueInConstant { ident, - "let", - kind.as_str(), - ), + suggestion: "let", + current: kind.as_str(), + type_span: None, + }, ), }; self.report_error(span, resolution_error); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7cb5a3fb2fd15..3dcb83d65b029 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -236,11 +236,12 @@ 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( - Ident, - /* suggestion */ &'static str, - /* current */ &'static str, - ), + AttemptToUseNonConstantValueInConstant { + ident: Ident, + suggestion: &'static str, + current: &'static str, + type_span: Option, + }, /// Error E0530: `X` bindings cannot shadow `Y`s. BindingShadowsSomethingUnacceptable { shadowing_binding: PatternSource, diff --git a/tests/ui/asm/parse-error.stderr b/tests/ui/asm/parse-error.stderr index 8030face1d253..1999cd09aa3b5 100644 --- a/tests/ui/asm/parse-error.stderr +++ b/tests/ui/asm/parse-error.stderr @@ -376,8 +376,8 @@ LL | asm!("{}", options(), const foo); | help: consider using `const` instead of `let` | -LL | const foo = 0; - | ~~~~~ +LL | const foo: /* Type */ = 0; + | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:71:44 @@ -387,8 +387,8 @@ LL | asm!("{}", clobber_abi("C"), const foo); | help: consider using `const` instead of `let` | -LL | const foo = 0; - | ~~~~~ +LL | const foo: /* Type */ = 0; + | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:74:55 @@ -398,8 +398,8 @@ LL | asm!("{}", options(), clobber_abi("C"), const foo); | help: consider using `const` instead of `let` | -LL | const foo = 0; - | ~~~~~ +LL | const foo: /* Type */ = 0; + | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:76:31 @@ -409,8 +409,8 @@ LL | asm!("{a}", a = const foo, a = const bar); | help: consider using `const` instead of `let` | -LL | const foo = 0; - | ~~~~~ +LL | const foo: /* Type */ = 0; + | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/parse-error.rs:76:46 @@ -420,8 +420,8 @@ LL | asm!("{a}", a = const foo, a = const bar); | help: consider using `const` instead of `let` | -LL | const bar = 0; - | ~~~~~ +LL | const bar: /* Type */ = 0; + | ~~~~~ ++++++++++++ error: aborting due to 64 previous errors diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr index deba9e0fc544b..1852623211813 100644 --- a/tests/ui/asm/type-check-1.stderr +++ b/tests/ui/asm/type-check-1.stderr @@ -6,8 +6,8 @@ LL | asm!("{}", const x); | help: consider using `const` instead of `let` | -LL | const x = 0; - | ~~~~~ +LL | const x: /* Type */ = 0; + | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/type-check-1.rs:44:36 @@ -17,8 +17,8 @@ LL | asm!("{}", const const_foo(x)); | help: consider using `const` instead of `let` | -LL | const x = 0; - | ~~~~~ +LL | const x: /* Type */ = 0; + | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/type-check-1.rs:47:36 @@ -28,8 +28,8 @@ LL | asm!("{}", const const_bar(x)); | help: consider using `const` instead of `let` | -LL | const x = 0; - | ~~~~~ +LL | const x: /* Type */ = 0; + | ~~~~~ ++++++++++++ error: invalid `sym` operand --> $DIR/type-check-1.rs:49:24 diff --git a/tests/ui/asm/x86_64/x86_64_parse_error.stderr b/tests/ui/asm/x86_64/x86_64_parse_error.stderr index 95b86d533fa87..9751f7b09d0eb 100644 --- a/tests/ui/asm/x86_64/x86_64_parse_error.stderr +++ b/tests/ui/asm/x86_64/x86_64_parse_error.stderr @@ -20,8 +20,8 @@ LL | asm!("{a}", in("eax") foo, a = const bar); | help: consider using `const` instead of `let` | -LL | const bar = 0; - | ~~~~~ +LL | const bar: /* Type */ = 0; + | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/x86_64_parse_error.rs:15:46 @@ -31,8 +31,8 @@ LL | asm!("{a}", in("eax") foo, a = const bar); | help: consider using `const` instead of `let` | -LL | const bar = 0; - | ~~~~~ +LL | const bar: /* Type */ = 0; + | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/x86_64_parse_error.rs:17:42 @@ -42,8 +42,8 @@ LL | asm!("{1}", in("eax") foo, const bar); | help: consider using `const` instead of `let` | -LL | const bar = 0; - | ~~~~~ +LL | const bar: /* Type */ = 0; + | ~~~~~ ++++++++++++ error: aborting due to 5 previous errors diff --git a/tests/ui/const-generics/legacy-const-generics-bad.stderr b/tests/ui/const-generics/legacy-const-generics-bad.stderr index 6285d47807109..e9ea22e472c18 100644 --- a/tests/ui/const-generics/legacy-const-generics-bad.stderr +++ b/tests/ui/const-generics/legacy-const-generics-bad.stderr @@ -6,8 +6,8 @@ LL | legacy_const_generics::foo(0, a, 2); | help: consider using `const` instead of `let` | -LL | const a = 1; - | ~~~~~ +LL | const a: /* Type */ = 1; + | ~~~~~ ++++++++++++ error: generic parameters may not be used in const operations --> $DIR/legacy-const-generics-bad.rs:12:35 diff --git a/tests/ui/consts/non-const-value-in-const.stderr b/tests/ui/consts/non-const-value-in-const.stderr index ee9ac16fe42b8..654b573544c2e 100644 --- a/tests/ui/consts/non-const-value-in-const.stderr +++ b/tests/ui/consts/non-const-value-in-const.stderr @@ -17,8 +17,8 @@ LL | let _ = [0; x]; | help: consider using `const` instead of `let` | -LL | const x = 5; - | ~~~~~ +LL | const x: /* Type */ = 5; + | ~~~~~ ++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/issues/issue-27433.fixed b/tests/ui/issues/issue-27433.fixed index ff6704e393b5b..f847b698976a0 100644 --- a/tests/ui/issues/issue-27433.fixed +++ b/tests/ui/issues/issue-27433.fixed @@ -3,5 +3,5 @@ fn main() { let foo = 42u32; #[allow(unused_variables, non_snake_case)] let FOO : u32 = foo; - //~^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant } diff --git a/tests/ui/issues/issue-27433.rs b/tests/ui/issues/issue-27433.rs index 2a34b43f58d22..9bbc5bcbb459d 100644 --- a/tests/ui/issues/issue-27433.rs +++ b/tests/ui/issues/issue-27433.rs @@ -3,5 +3,5 @@ fn main() { let foo = 42u32; #[allow(unused_variables, non_snake_case)] const FOO : u32 = foo; - //~^ ERROR attempt to use a non-constant value in a constant + //~^ ERROR attempt to use a non-constant value in a constant } diff --git a/tests/ui/repeat-expr/repeat_count.stderr b/tests/ui/repeat-expr/repeat_count.stderr index 9b5afc557357a..350ac287507a3 100644 --- a/tests/ui/repeat-expr/repeat_count.stderr +++ b/tests/ui/repeat-expr/repeat_count.stderr @@ -6,8 +6,8 @@ LL | let a = [0; n]; | help: consider using `const` instead of `let` | -LL | const n = 1; - | ~~~~~ +LL | const n: /* Type */ = 1; + | ~~~~~ ++++++++++++ error[E0308]: mismatched types --> $DIR/repeat_count.rs:7:17 diff --git a/tests/ui/typeof/issue-42060.stderr b/tests/ui/typeof/issue-42060.stderr index 7af65633f71d9..86ba9432384b2 100644 --- a/tests/ui/typeof/issue-42060.stderr +++ b/tests/ui/typeof/issue-42060.stderr @@ -6,8 +6,8 @@ LL | let other: typeof(thing) = thing; | help: consider using `const` instead of `let` | -LL | const thing = (); - | ~~~~~ +LL | const thing: /* Type */ = (); + | ~~~~~ ++++++++++++ error[E0435]: attempt to use a non-constant value in a constant --> $DIR/issue-42060.rs:9:13 @@ -17,8 +17,8 @@ LL | ::N | help: consider using `const` instead of `let` | -LL | const q = 1; - | ~~~~~ +LL | const q: /* Type */ = 1; + | ~~~~~ ++++++++++++ error[E0516]: `typeof` is a reserved keyword but unimplemented --> $DIR/issue-42060.rs:3:16