Skip to content

Commit 876a14a

Browse files
committed
finally understanding rust const environment
1 parent 5ab6849 commit 876a14a

8 files changed

Lines changed: 85 additions & 64 deletions

File tree

Cargo.lock

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ byte-slice-cast = { version = "1.2.2", default-features = false }
2020
generic-array = { version = "0.14.7", optional = true }
2121
arbitrary = { version = "1.4.1", features = ["derive"], optional = true }
2222
impl-trait-for-tuples = "0.2.2"
23+
const_format = { version = "0.2.34" }
2324

2425
[dev-dependencies]
2526
criterion = "0.4.0"

derive/src/decode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ pub fn quote(
7373
let recurse_indices =
7474
variants.iter().enumerate().map(|(i, v)| (v.ident.clone(), utils::variant_index(v, i)));
7575

76-
let const_eval_check = utils::const_eval_check_variant_indexes(recurse_indices);
76+
let const_eval_check = utils::const_eval_check_variant_indexes(recurse_indices, crate_path);
7777

7878
let read_byte_err_msg =
7979
format!("Could not decode `{type_name}`, failed to read variant byte");

derive/src/encode.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ fn impl_encode(data: &Data, type_name: &Ident, crate_path: &syn::Path) -> TokenS
404404
}
405405
};
406406

407-
let const_eval_check = const_eval_check_variant_indexes(recurse_variant_indices);
407+
let const_eval_check = const_eval_check_variant_indexes(recurse_variant_indices, crate_path);
408408

409409
let encoding = quote! {
410410
#const_eval_check

derive/src/utils.rs

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,37 +40,54 @@ where
4040

4141
pub fn const_eval_check_variant_indexes(
4242
recurse_variant_indices: impl Iterator<Item = (syn::Ident, TokenStream)>,
43+
crate_path: &syn::Path,
4344
) -> TokenStream {
4445
let mut recurse_indices = vec![];
45-
let mut variant_msg = vec![];
4646
for (ident, index) in recurse_variant_indices {
47-
recurse_indices.push((index, ident));
47+
let ident_str = ident.to_string();
48+
recurse_indices.push(quote! { (#index, #ident_str) });
4849
}
4950
let len = recurse_indices.len();
5051

51-
let error_message = format!(
52-
"Found Variants that have duplicate indexes. Use different indexes for each variant.\n\
53-
List of variants:\n\
54-
{}",
55-
variant_msg.concat()
56-
);
52+
if len == 0 {
53+
return quote! {};
54+
}
5755

5856
quote! {
5957
const _: () = {
60-
let indices: [(usize, &'static str); #len] = [#( #recurse_indices ,)*];
61-
let len = indices.len();
62-
63-
// Check each pair for uniqueness
64-
let mut i = 0;
65-
while i < len {
66-
let mut j = i + 1;
67-
while j < len {
68-
if indices[i] == indices[j] {
69-
::core::panic!(#error_message);
70-
}
71-
j += 1;
72-
}
73-
i += 1;
58+
const indices: [(usize, &'static str); #len] = [#( #recurse_indices ,)*];
59+
60+
// Returns if there is duplicate, and if there is some the duplicate indexes.
61+
const fn duplicate_info(array: &[(usize, &'static str); #len]) -> (bool, usize, usize) {
62+
let len = array.len();
63+
let mut i = 0;
64+
while i < len {
65+
let mut j = i + 1;
66+
while j < len {
67+
if array[i].0 == array[j].0 {
68+
return (true, i, j);
69+
}
70+
j += 1;
71+
}
72+
i += 1;
73+
}
74+
(false, 0, 0)
75+
}
76+
77+
const DUP_INFO: (bool, usize, usize) = duplicate_info(&indices);
78+
79+
if DUP_INFO.0 {
80+
let msg = #crate_path::__private::concatcp!(
81+
"Found variants that have duplicate indexes. Both `",
82+
indices[DUP_INFO.1].1,
83+
"` and `",
84+
indices[DUP_INFO.2].1,
85+
"` have the index `",
86+
indices[DUP_INFO.1].0,
87+
"`. Use different indexes for each variant."
88+
);
89+
90+
::core::panic!("{}", msg);
7491
}
7592
};
7693
}

src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ pub mod alloc {
4141
pub use std::{alloc, borrow, boxed, collections, rc, string, sync, vec};
4242
}
4343

44+
/// Private module to reexport items used by derive macros.
45+
// We don't feature gate this module with `derive` to avoid compilation error when
46+
// `parity-scale-codec-derive` is used on its own and this crate doesn't have the feature enabled.
47+
#[doc(hidden)]
48+
pub mod __private {
49+
pub use const_format::concatcp;
50+
}
51+
4452
#[cfg(feature = "bit-vec")]
4553
mod bit_vec;
4654
mod btree_utils;

tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.stderr

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,30 @@ error[E0080]: evaluation of constant value failed
22
--> tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:1:10
33
|
44
1 | #[derive(::parity_scale_codec::Decode, ::parity_scale_codec::Encode)]
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found Variants that have duplicate indexes. Use different indexes for each variant.
6-
List of variants:
7-
Index for variant `A` is `1`
8-
Index for variant `B` is `1usize`
9-
', $DIR/tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:1:10
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found variants that have duplicate indexes. Both `A` and `B` have the index `1`. Use different indexes for each variant.', $DIR/tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:1:10
106
|
117
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `::core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
128

139
error[E0080]: evaluation of constant value failed
1410
--> tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:1:40
1511
|
1612
1 | #[derive(::parity_scale_codec::Decode, ::parity_scale_codec::Encode)]
17-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found Variants that have duplicate indexes. Use different indexes for each variant.
18-
List of variants:
19-
Index for variant `A` is `1`
20-
Index for variant `B` is `1usize`
21-
', $DIR/tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:1:40
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found variants that have duplicate indexes. Both `A` and `B` have the index `1`. Use different indexes for each variant.', $DIR/tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:1:40
2214
|
2315
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `::core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
2416

2517
error[E0080]: evaluation of constant value failed
2618
--> tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:8:10
2719
|
2820
8 | #[derive(::parity_scale_codec::Decode, ::parity_scale_codec::Encode)]
29-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found Variants that have duplicate indexes. Use different indexes for each variant.
30-
List of variants:
31-
Index for variant `A` is `1usize`
32-
Index for variant `B` is `1usize`
33-
', $DIR/tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:8:10
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found variants that have duplicate indexes. Both `A` and `B` have the index `1`. Use different indexes for each variant.', $DIR/tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:8:10
3422
|
3523
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `::core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
3624

3725
error[E0080]: evaluation of constant value failed
3826
--> tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:8:40
3927
|
4028
8 | #[derive(::parity_scale_codec::Decode, ::parity_scale_codec::Encode)]
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found Variants that have duplicate indexes. Use different indexes for each variant.
42-
List of variants:
43-
Index for variant `A` is `1usize`
44-
Index for variant `B` is `1usize`
45-
', $DIR/tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:8:40
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found variants that have duplicate indexes. Both `A` and `B` have the index `1`. Use different indexes for each variant.', $DIR/tests/scale_codec_ui/codec_discriminiant_variant_counted_in_default_index.rs:8:40
4630
|
4731
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `::core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)

tests/scale_codec_ui/codec_duplicate_index.stderr

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,30 @@ error[E0080]: evaluation of constant value failed
22
--> tests/scale_codec_ui/codec_duplicate_index.rs:1:10
33
|
44
1 | #[derive(::parity_scale_codec::Decode, ::parity_scale_codec::Encode)]
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found Variants that have duplicate indexes. Use different indexes for each variant.
6-
List of variants:
7-
Index for variant `A` is `3`
8-
Index for variant `B` is `3usize`
9-
', $DIR/tests/scale_codec_ui/codec_duplicate_index.rs:1:10
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found variants that have duplicate indexes. Both `A` and `B` have the index `3`. Use different indexes for each variant.', $DIR/tests/scale_codec_ui/codec_duplicate_index.rs:1:10
106
|
117
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `::core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
128

139
error[E0080]: evaluation of constant value failed
1410
--> tests/scale_codec_ui/codec_duplicate_index.rs:1:40
1511
|
1612
1 | #[derive(::parity_scale_codec::Decode, ::parity_scale_codec::Encode)]
17-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found Variants that have duplicate indexes. Use different indexes for each variant.
18-
List of variants:
19-
Index for variant `A` is `3`
20-
Index for variant `B` is `3usize`
21-
', $DIR/tests/scale_codec_ui/codec_duplicate_index.rs:1:40
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found variants that have duplicate indexes. Both `A` and `B` have the index `3`. Use different indexes for each variant.', $DIR/tests/scale_codec_ui/codec_duplicate_index.rs:1:40
2214
|
2315
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `::core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
2416

2517
error[E0080]: evaluation of constant value failed
2618
--> tests/scale_codec_ui/codec_duplicate_index.rs:9:10
2719
|
2820
9 | #[derive(::parity_scale_codec::Decode, ::parity_scale_codec::Encode)]
29-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found Variants that have duplicate indexes. Use different indexes for each variant.
30-
List of variants:
31-
Index for variant `A` is `0usize`
32-
Index for variant `B` is `0usize`
33-
', $DIR/tests/scale_codec_ui/codec_duplicate_index.rs:9:10
21+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found variants that have duplicate indexes. Both `A` and `B` have the index `0`. Use different indexes for each variant.', $DIR/tests/scale_codec_ui/codec_duplicate_index.rs:9:10
3422
|
3523
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `::core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)
3624

3725
error[E0080]: evaluation of constant value failed
3826
--> tests/scale_codec_ui/codec_duplicate_index.rs:9:40
3927
|
4028
9 | #[derive(::parity_scale_codec::Decode, ::parity_scale_codec::Encode)]
41-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found Variants that have duplicate indexes. Use different indexes for each variant.
42-
List of variants:
43-
Index for variant `A` is `0usize`
44-
Index for variant `B` is `0usize`
45-
', $DIR/tests/scale_codec_ui/codec_duplicate_index.rs:9:40
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'Found variants that have duplicate indexes. Both `A` and `B` have the index `0`. Use different indexes for each variant.', $DIR/tests/scale_codec_ui/codec_duplicate_index.rs:9:40
4630
|
4731
= note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `::core::panic` (in Nightly builds, run with -Z macro-backtrace for more info)

0 commit comments

Comments
 (0)