Account for let foo = expr; to suggest const foo: Ty = expr;

This commit is contained in:
Esteban Küber 2024-07-08 19:43:20 +00:00
parent b56dc8ee90
commit cbe75486f7
13 changed files with 85 additions and 56 deletions

View File

@ -819,7 +819,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
self.dcx().create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span }) self.dcx().create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span })
} }
ResolutionError::AttemptToUseNonConstantValueInConstant(ident, suggestion, current) => { ResolutionError::AttemptToUseNonConstantValueInConstant {
ident,
suggestion,
current,
type_span,
} => {
// let foo =... // let foo =...
// ^^^ given this Span // ^^^ given this Span
// ------- get this Span to have an applicable suggestion // ------- get this Span to have an applicable suggestion
@ -844,6 +849,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
span: sp, span: sp,
suggestion, suggestion,
current, current,
type_span,
}), Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion {span})), }), Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion {span})),
None, None,
) )

View File

@ -240,16 +240,18 @@ pub(crate) struct AttemptToUseNonConstantValueInConstant<'a> {
} }
#[derive(Subdiagnostic)] #[derive(Subdiagnostic)]
#[suggestion( #[multipart_suggestion(
resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion, resolve_attempt_to_use_non_constant_value_in_constant_with_suggestion,
code = "{suggestion} ",
style = "verbose", style = "verbose",
applicability = "maybe-incorrect" applicability = "has-placeholders"
)] )]
pub(crate) struct AttemptToUseNonConstantValueInConstantWithSuggestion<'a> { pub(crate) struct AttemptToUseNonConstantValueInConstantWithSuggestion<'a> {
#[primary_span] // #[primary_span]
#[suggestion_part(code = "{suggestion} ")]
pub(crate) span: Span, pub(crate) span: Span,
pub(crate) suggestion: &'a str, pub(crate) suggestion: &'a str,
#[suggestion_part(code = ": /* Type */")]
pub(crate) type_span: Option<Span>,
pub(crate) current: &'a str, pub(crate) current: &'a str,
} }

View File

@ -1178,21 +1178,41 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if let Some(span) = finalize { if let Some(span) = finalize {
let (span, resolution_error) = match item { let (span, resolution_error) = match item {
None if rib_ident.as_str() == "self" => (span, LowercaseSelf), None if rib_ident.as_str() == "self" => (span, LowercaseSelf),
None => ( None => {
rib_ident.span, // If we have a `let name = expr;`, we have the span for
AttemptToUseNonConstantValueInConstant( // `name` and use that to see if it is followed by a type
original_rib_ident_def, // specifier. If not, then we know we need to suggest
"const", // `const name: Ty = expr;`. This is a heuristic, it will
"let", // 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)) => ( Some((ident, kind)) => (
span, span,
AttemptToUseNonConstantValueInConstant( AttemptToUseNonConstantValueInConstant {
ident, ident,
"let", suggestion: "let",
kind.as_str(), current: kind.as_str(),
), type_span: None,
},
), ),
}; };
self.report_error(span, resolution_error); self.report_error(span, resolution_error);

View File

@ -236,11 +236,12 @@ 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, ident: Ident,
/* suggestion */ &'static str, suggestion: &'static str,
/* current */ &'static str, current: &'static str,
), type_span: Option<Span>,
},
/// Error E0530: `X` bindings cannot shadow `Y`s. /// Error E0530: `X` bindings cannot shadow `Y`s.
BindingShadowsSomethingUnacceptable { BindingShadowsSomethingUnacceptable {
shadowing_binding: PatternSource, shadowing_binding: PatternSource,

View File

@ -376,8 +376,8 @@ LL | asm!("{}", options(), const foo);
| |
help: consider using `const` instead of `let` 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:71:44 --> $DIR/parse-error.rs:71:44
@ -387,8 +387,8 @@ LL | asm!("{}", clobber_abi("C"), const foo);
| |
help: consider using `const` instead of `let` 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:74:55 --> $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` 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:76:31 --> $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` 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/parse-error.rs:76:46 --> $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` help: consider using `const` instead of `let`
| |
LL | const bar = 0; LL | const bar: /* Type */ = 0;
| ~~~~~ | ~~~~~ ++++++++++++
error: aborting due to 64 previous errors error: aborting due to 64 previous errors

View File

@ -6,8 +6,8 @@ LL | asm!("{}", const x);
| |
help: consider using `const` instead of `let` 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/type-check-1.rs:44:36 --> $DIR/type-check-1.rs:44:36
@ -17,8 +17,8 @@ LL | asm!("{}", const const_foo(x));
| |
help: consider using `const` instead of `let` 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/type-check-1.rs:47:36 --> $DIR/type-check-1.rs:47:36
@ -28,8 +28,8 @@ LL | asm!("{}", const const_bar(x));
| |
help: consider using `const` instead of `let` help: consider using `const` instead of `let`
| |
LL | const x = 0; LL | const x: /* Type */ = 0;
| ~~~~~ | ~~~~~ ++++++++++++
error: invalid `sym` operand error: invalid `sym` operand
--> $DIR/type-check-1.rs:49:24 --> $DIR/type-check-1.rs:49:24

View File

@ -20,8 +20,8 @@ LL | asm!("{a}", in("eax") foo, a = const bar);
| |
help: consider using `const` instead of `let` 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/x86_64_parse_error.rs:15:46 --> $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` 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/x86_64_parse_error.rs:17:42 --> $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` help: consider using `const` instead of `let`
| |
LL | const bar = 0; LL | const bar: /* Type */ = 0;
| ~~~~~ | ~~~~~ ++++++++++++
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View File

@ -6,8 +6,8 @@ LL | legacy_const_generics::foo(0, a, 2);
| |
help: consider using `const` instead of `let` 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 error: generic parameters may not be used in const operations
--> $DIR/legacy-const-generics-bad.rs:12:35 --> $DIR/legacy-const-generics-bad.rs:12:35

View File

@ -17,8 +17,8 @@ LL | let _ = [0; x];
| |
help: consider using `const` instead of `let` help: consider using `const` instead of `let`
| |
LL | const x = 5; LL | const x: /* Type */ = 5;
| ~~~~~ | ~~~~~ ++++++++++++
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View File

@ -3,5 +3,5 @@ fn main() {
let foo = 42u32; let foo = 42u32;
#[allow(unused_variables, non_snake_case)] #[allow(unused_variables, non_snake_case)]
let FOO : u32 = foo; 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
} }

View File

@ -3,5 +3,5 @@ fn main() {
let foo = 42u32; let foo = 42u32;
#[allow(unused_variables, non_snake_case)] #[allow(unused_variables, non_snake_case)]
const FOO : u32 = foo; 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
} }

View File

@ -6,8 +6,8 @@ LL | let a = [0; n];
| |
help: consider using `const` instead of `let` help: consider using `const` instead of `let`
| |
LL | const n = 1; LL | const n: /* Type */ = 1;
| ~~~~~ | ~~~~~ ++++++++++++
error[E0308]: mismatched types error[E0308]: mismatched types
--> $DIR/repeat_count.rs:7:17 --> $DIR/repeat_count.rs:7:17

View File

@ -6,8 +6,8 @@ LL | let other: typeof(thing) = thing;
| |
help: consider using `const` instead of `let` 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 error[E0435]: attempt to use a non-constant value in a constant
--> $DIR/issue-42060.rs:9:13 --> $DIR/issue-42060.rs:9:13
@ -17,8 +17,8 @@ LL | <typeof(q)>::N
| |
help: consider using `const` instead of `let` 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 error[E0516]: `typeof` is a reserved keyword but unimplemented
--> $DIR/issue-42060.rs:3:16 --> $DIR/issue-42060.rs:3:16