mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 08:11:03 +00:00
make types within generate_solution_type macro explicit (#8447)
* make types within `generate_solution_type` macro explicit Closes #8444. Just changes the parsing logic for that macro; does not change any emitted code. The associated types associated with the macro now require explicit, keyword-style declaration. **Old**: ```rust sp_npos_elections::generate_solution_type!( #[compact] pub struct TestCompact::<VoterIndex, TargetIndex, PerU16>(16) ); ``` **New**: ```rust sp_npos_elections::generate_solution_type!( #[compact] pub struct TestCompact::<VoterIndex = VoterIndex, CandidateIndex = TargetIndex, Accuracy = PerU16>(16) ); ``` * un-ignore doc-tests * use new form in bin/node/runtime/ * rename CandidateIndex -> TargetIndex * add tests demonstrating some potential compile failures
This commit is contained in:
committed by
GitHub
parent
2af0de50c9
commit
c2dd5e21a4
@@ -19,3 +19,9 @@ syn = { version = "1.0.58", features = ["full", "visit"] }
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0.6"
|
||||
proc-macro-crate = "1.0.0"
|
||||
|
||||
[dev-dependencies]
|
||||
parity-scale-codec = "2.0.1"
|
||||
sp-arithmetic = { path = "../../arithmetic" }
|
||||
sp-npos-elections = { path = ".." }
|
||||
trybuild = "1.0.41"
|
||||
|
||||
@@ -52,8 +52,14 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error {
|
||||
/// For example, the following generates a public struct with name `TestSolution` with `u16` voter
|
||||
/// type, `u8` target type and `Perbill` accuracy with maximum of 8 edges per voter.
|
||||
///
|
||||
/// ```ignore
|
||||
/// generate_solution_type!(pub struct TestSolution<u16, u8, Perbill>::(8))
|
||||
/// ```
|
||||
/// # use sp_npos_elections_compact::generate_solution_type;
|
||||
/// # use sp_arithmetic::per_things::Perbill;
|
||||
/// generate_solution_type!(pub struct TestSolution::<
|
||||
/// VoterIndex = u16,
|
||||
/// TargetIndex = u8,
|
||||
/// Accuracy = Perbill,
|
||||
/// >(8));
|
||||
/// ```
|
||||
///
|
||||
/// The given struct provides function to convert from/to Assignment:
|
||||
@@ -65,11 +71,13 @@ pub(crate) fn syn_err(message: &'static str) -> syn::Error {
|
||||
/// lead to many 0s in the solution. If prefixed with `#[compact]`, then a custom compact encoding
|
||||
/// for numbers will be used, similar to how `parity-scale-codec`'s `Compact` works.
|
||||
///
|
||||
/// ```ignore
|
||||
/// ```
|
||||
/// # use sp_npos_elections_compact::generate_solution_type;
|
||||
/// # use sp_arithmetic::per_things::Perbill;
|
||||
/// generate_solution_type!(
|
||||
/// #[compact]
|
||||
/// pub struct TestSolutionCompact<u16, u8, Perbill>::(8)
|
||||
/// )
|
||||
/// pub struct TestSolutionCompact::<VoterIndex = u16, TargetIndex = u8, Accuracy = Perbill>(8)
|
||||
/// );
|
||||
/// ```
|
||||
#[proc_macro]
|
||||
pub fn generate_solution_type(item: TokenStream) -> TokenStream {
|
||||
@@ -386,7 +394,7 @@ fn check_compact_attr(input: ParseStream) -> Result<bool> {
|
||||
}
|
||||
}
|
||||
|
||||
/// #[compact] pub struct CompactName::<u32, u32, u32>()
|
||||
/// #[compact] pub struct CompactName::<VoterIndex = u32, TargetIndex = u32, Accuracy = u32>()
|
||||
impl Parse for SolutionDef {
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
// optional #[compact]
|
||||
@@ -405,9 +413,22 @@ impl Parse for SolutionDef {
|
||||
return Err(syn_err("Must provide 3 generic args."))
|
||||
}
|
||||
|
||||
let mut types: Vec<syn::Type> = generics.args.iter().map(|t|
|
||||
let expected_types = ["VoterIndex", "TargetIndex", "Accuracy"];
|
||||
|
||||
let mut types: Vec<syn::Type> = generics.args.iter().zip(expected_types.iter()).map(|(t, expected)|
|
||||
match t {
|
||||
syn::GenericArgument::Type(ty) => Ok(ty.clone()),
|
||||
syn::GenericArgument::Type(ty) => {
|
||||
// this is now an error
|
||||
Err(syn::Error::new_spanned(ty, format!("Expected binding: `{} = ...`", expected)))
|
||||
},
|
||||
syn::GenericArgument::Binding(syn::Binding{ident, ty, ..}) => {
|
||||
// check that we have the right keyword for this position in the argument list
|
||||
if ident == expected {
|
||||
Ok(ty.clone())
|
||||
} else {
|
||||
Err(syn::Error::new_spanned(ident, format!("Expected `{}`", expected)))
|
||||
}
|
||||
}
|
||||
_ => Err(syn_err("Wrong type of generic provided. Must be a `type`.")),
|
||||
}
|
||||
).collect::<Result<_>>()?;
|
||||
@@ -436,3 +457,12 @@ impl Parse for SolutionDef {
|
||||
fn field_name_for(n: usize) -> Ident {
|
||||
Ident::new(&format!("{}{}", PREFIX, n), Span::call_site())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn ui_fail() {
|
||||
let cases = trybuild::TestCases::new();
|
||||
cases.compile_fail("tests/ui/fail/*.rs");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
use sp_npos_elections_compact::generate_solution_type;
|
||||
|
||||
generate_solution_type!(pub struct TestSolution::<
|
||||
VoterIndex = u16,
|
||||
TargetIndex = u8,
|
||||
Perbill,
|
||||
>(8));
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: Expected binding: `Accuracy = ...`
|
||||
--> $DIR/missing_accuracy.rs:6:2
|
||||
|
|
||||
6 | Perbill,
|
||||
| ^^^^^^^
|
||||
@@ -0,0 +1,9 @@
|
||||
use sp_npos_elections_compact::generate_solution_type;
|
||||
|
||||
generate_solution_type!(pub struct TestSolution::<
|
||||
VoterIndex = u16,
|
||||
u8,
|
||||
Accuracy = Perbill,
|
||||
>(8));
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: Expected binding: `TargetIndex = ...`
|
||||
--> $DIR/missing_target.rs:5:2
|
||||
|
|
||||
5 | u8,
|
||||
| ^^
|
||||
@@ -0,0 +1,9 @@
|
||||
use sp_npos_elections_compact::generate_solution_type;
|
||||
|
||||
generate_solution_type!(pub struct TestSolution::<
|
||||
u16,
|
||||
TargetIndex = u8,
|
||||
Accuracy = Perbill,
|
||||
>(8));
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: Expected binding: `VoterIndex = ...`
|
||||
--> $DIR/missing_voter.rs:4:2
|
||||
|
|
||||
4 | u16,
|
||||
| ^^^
|
||||
@@ -0,0 +1,9 @@
|
||||
use sp_npos_elections_compact::generate_solution_type;
|
||||
|
||||
generate_solution_type!(pub struct TestSolution::<
|
||||
u16,
|
||||
u8,
|
||||
Perbill,
|
||||
>(8));
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: Expected binding: `VoterIndex = ...`
|
||||
--> $DIR/no_annotations.rs:4:2
|
||||
|
|
||||
4 | u16,
|
||||
| ^^^
|
||||
@@ -0,0 +1,9 @@
|
||||
use sp_npos_elections_compact::generate_solution_type;
|
||||
|
||||
generate_solution_type!(pub struct TestSolution::<
|
||||
TargetIndex = u16,
|
||||
VoterIndex = u8,
|
||||
Accuracy = Perbill,
|
||||
>(8));
|
||||
|
||||
fn main() {}
|
||||
@@ -0,0 +1,5 @@
|
||||
error: Expected `VoterIndex`
|
||||
--> $DIR/swap_voter_target.rs:4:2
|
||||
|
|
||||
4 | TargetIndex = u16,
|
||||
| ^^^^^^^^^^^
|
||||
Reference in New Issue
Block a user