Skip to content

Commit ea7c464

Browse files
authored
Fix clippy expect_used complains for derive(FromRow) macro (scylladb#1077)
Get rid of `.expect` usage in `FromRow` macro by using arrays to detect problems during compile time.
1 parent 582d48e commit ea7c464

File tree

2 files changed

+36
-18
lines changed

2 files changed

+36
-18
lines changed

scylla-cql/src/frame/response/cql_to_rust.rs

+15
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,11 @@ mod tests {
935935
);
936936
}
937937

938+
// Enabling `expect_used` clippy lint,
939+
// validates that `derive(FromRow)` macro definition does do not violates such rule under the hood.
940+
// Could be removed after such rule will be applied for the whole crate.
941+
// <https://rust-lang.github.io/rust-clippy/master/index.html#/expect_used>
942+
#[deny(clippy::expect_used)]
938943
#[test]
939944
fn struct_from_row() {
940945
#[derive(FromRow)]
@@ -959,6 +964,11 @@ mod tests {
959964
assert_eq!(my_row.c, Some(vec![1, 2]));
960965
}
961966

967+
// Enabling `expect_used` clippy lint,
968+
// validates that `derive(FromRow)` macro definition does do not violates such rule under the hood.
969+
// Could be removed after such rule will be applied for the whole crate.
970+
// <https://rust-lang.github.io/rust-clippy/master/index.html#/expect_used>
971+
#[deny(clippy::expect_used)]
962972
#[test]
963973
fn struct_from_row_wrong_size() {
964974
#[derive(FromRow, PartialEq, Eq, Debug)]
@@ -998,6 +1008,11 @@ mod tests {
9981008
);
9991009
}
10001010

1011+
// Enabling `expect_used` clippy lint,
1012+
// validates that `derive(FromRow)` macro definition does do not violates such rule under the hood.
1013+
// Could be removed after such rule will be applied for the whole crate.
1014+
// <https://rust-lang.github.io/rust-clippy/master/index.html#/expect_used>
1015+
#[deny(clippy::expect_used)]
10011016
#[test]
10021017
fn unnamed_struct_from_row() {
10031018
#[derive(FromRow)]

scylla-macros/src/from_row.rs

+21-18
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,20 @@ pub(crate) fn from_row_derive(tokens_input: TokenStream) -> Result<TokenStream,
1414
// Generates a token that sets the values of struct fields: field_type::from_cql(...)
1515
let (fill_struct_code, fields_count) = match struct_fields {
1616
crate::parser::StructFields::Named(fields) => {
17-
let set_fields_code = fields.named.iter().map(|field| {
17+
let set_fields_code = fields.named.iter().enumerate().map(|(col_ix, field)| {
1818
let field_name = &field.ident;
1919
let field_type = &field.ty;
2020

2121
quote_spanned! {field.span() =>
2222
#field_name: {
23-
let (col_ix, col_value) = vals_iter
24-
.next()
25-
.expect("BUG: Size validated iterator did not contain the expected number of values");
23+
// To avoid unnecessary copy `std::mem::take` is used.
24+
// Using explicit indexing operation is safe because `row_columns` is an array and `col_ix` is a litteral.
25+
// <https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/builtin/static.UNCONDITIONAL_PANIC.html>
26+
let col_value = ::std::mem::take(&mut row_columns[#col_ix]);
2627
<#field_type as FromCqlVal<::std::option::Option<CqlValue>>>::from_cql(col_value)
2728
.map_err(|e| FromRowError::BadCqlVal {
2829
err: e,
29-
column: col_ix,
30+
column: #col_ix,
3031
})?
3132
},
3233
}
@@ -39,19 +40,19 @@ pub(crate) fn from_row_derive(tokens_input: TokenStream) -> Result<TokenStream,
3940
(fill_struct_code, fields.named.len())
4041
}
4142
crate::parser::StructFields::Unnamed(fields) => {
42-
let set_fields_code = fields.unnamed.iter().map(|field| {
43+
let set_fields_code = fields.unnamed.iter().enumerate().map(|(col_ix, field)| {
4344
let field_type = &field.ty;
4445

4546
quote_spanned! {field.span() =>
4647
{
47-
let (col_ix, col_value) = vals_iter
48-
.next()
49-
.expect("BUG: Size validated iterator did not contain the expected number of values");
50-
48+
// To avoid unnecessary copy `std::mem::take` is used.
49+
// Using explicit indexing operation is safe because `row_columns` is an array and `col_ix` is a litteral.
50+
// <https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/builtin/static.UNCONDITIONAL_PANIC.html>
51+
let col_value = ::std::mem::take(&mut row_columns[#col_ix]);
5152
<#field_type as FromCqlVal<::std::option::Option<CqlValue>>>::from_cql(col_value)
5253
.map_err(|e| FromRowError::BadCqlVal {
5354
err: e,
54-
column: col_ix,
55+
column: #col_ix,
5556
})?
5657
},
5758
}
@@ -71,15 +72,17 @@ pub(crate) fn from_row_derive(tokens_input: TokenStream) -> Result<TokenStream,
7172
-> ::std::result::Result<Self, #path::FromRowError> {
7273
use #path::{CqlValue, FromCqlVal, FromRow, FromRowError};
7374
use ::std::result::Result::{Ok, Err};
75+
use ::std::convert::TryInto;
7476
use ::std::iter::{Iterator, IntoIterator};
7577

76-
if #fields_count != row.columns.len() {
77-
return Err(FromRowError::WrongRowSize {
78-
expected: #fields_count,
79-
actual: row.columns.len(),
80-
});
81-
}
82-
let mut vals_iter = row.columns.into_iter().enumerate();
78+
79+
let row_columns_len = row.columns.len();
80+
// An array used, to enable [uncoditional paniking](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/builtin/static.UNCONDITIONAL_PANIC.html)
81+
// for "index out of range" issues and be able to catch them during the compile time.
82+
let mut row_columns: [_; #fields_count] = row.columns.try_into().map_err(|_| FromRowError::WrongRowSize {
83+
expected: #fields_count,
84+
actual: row_columns_len,
85+
})?;
8386

8487
Ok(#struct_name #fill_struct_code)
8588
}

0 commit comments

Comments
 (0)