Skip to content

Commit ce9494a

Browse files
committed
Changed impl to use symbols.
1 parent 00a5ef6 commit ce9494a

File tree

1 file changed

+45
-31
lines changed

1 file changed

+45
-31
lines changed

clippy_lints/src/checked_conversions.rs

Lines changed: 45 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
//! lint on manually implemented checked conversions that could be transformed into `try_from`
22
33
use if_chain::if_chain;
4+
use lazy_static::lazy_static;
45
use rustc::hir::*;
56
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
67
use rustc::{declare_lint_pass, declare_tool_lint};
78
use rustc_errors::Applicability;
89
use syntax::ast::LitKind;
9-
use crate::utils::{span_lint_and_sugg, snippet_with_applicability, SpanlessEq};
10+
use syntax::symbol::Symbol;
11+
12+
use crate::utils::{snippet_with_applicability, span_lint_and_sugg, sym, SpanlessEq};
1013

1114
declare_clippy_lint! {
1215
/// **What it does:** Checks for explicit bounds checking when casting.
@@ -101,7 +104,7 @@ fn double_check<'a>(cx: &LateContext<'_, '_>, left: &'a Expr, right: &'a Expr) -
101104
struct Conversion<'a> {
102105
cvt: ConversionType,
103106
expr_to_cast: &'a Expr,
104-
to_type: Option<String>,
107+
to_type: Option<Symbol>,
105108
}
106109

107110
/// The kind of conversion that is checked
@@ -137,8 +140,8 @@ impl<'a> Conversion<'a> {
137140
}
138141

139142
/// Try to construct a new conversion if the conversion type is valid
140-
fn try_new<'b>(expr_to_cast: &'a Expr, from_type: &'b str, to_type: String) -> Option<Conversion<'a>> {
141-
ConversionType::try_new(from_type, &to_type).map(|cvt| Conversion {
143+
fn try_new<'b>(expr_to_cast: &'a Expr, from_type: Symbol, to_type: Symbol) -> Option<Conversion<'a>> {
144+
ConversionType::try_new(from_type, to_type).map(|cvt| Conversion {
142145
cvt,
143146
expr_to_cast,
144147
to_type: Some(to_type),
@@ -157,13 +160,13 @@ impl<'a> Conversion<'a> {
157160

158161
impl ConversionType {
159162
/// Creates a conversion type if the type is allowed & conversion is valid
160-
fn try_new(from: &str, to: &str) -> Option<Self> {
161-
if UNSIGNED_TYPES.contains(&from) {
163+
fn try_new(from: Symbol, to: Symbol) -> Option<Self> {
164+
if UINTS.contains(&from) {
162165
Some(ConversionType::FromUnsigned)
163-
} else if SIGNED_TYPES.contains(&from) {
164-
if UNSIGNED_TYPES.contains(&to) {
166+
} else if SINTS.contains(&from) {
167+
if UINTS.contains(&to) {
165168
Some(ConversionType::SignedToUnsigned)
166-
} else if SIGNED_TYPES.contains(&to) {
169+
} else if SINTS.contains(&to) {
167170
Some(ConversionType::SignedToSigned)
168171
} else {
169172
None
@@ -179,10 +182,10 @@ fn check_upper_bound(expr: &Expr) -> Option<Conversion<'_>> {
179182
if_chain! {
180183
if let ExprKind::Binary(ref op, ref left, ref right) = &expr.node;
181184
if let Some((candidate, check)) = normalize_le_ge(op, left, right);
182-
if let Some((from, to)) = get_types_from_cast(check, "max_value", INT_TYPES);
185+
if let Some((from, to)) = get_types_from_cast(check, *sym::max_value, &*INTS);
183186

184187
then {
185-
Conversion::try_new(candidate, &from, to)
188+
Conversion::try_new(candidate, from, to)
186189
} else {
187190
None
188191
}
@@ -219,31 +222,31 @@ fn check_lower_bound_zero<'a>(candidate: &'a Expr, check: &'a Expr) -> Option<Co
219222

220223
/// Check for `expr >= (to_type::min_value() as from_type)`
221224
fn check_lower_bound_min<'a>(candidate: &'a Expr, check: &'a Expr) -> Option<Conversion<'a>> {
222-
if let Some((from, to)) = get_types_from_cast(check, "min_value", SIGNED_TYPES) {
223-
Conversion::try_new(candidate, &from, to)
225+
if let Some((from, to)) = get_types_from_cast(check, *sym::min_value, &*SINTS) {
226+
Conversion::try_new(candidate, from, to)
224227
} else {
225228
None
226229
}
227230
}
228231

229232
/// Tries to extract the from- and to-type from a cast expression
230-
fn get_types_from_cast(expr: &Expr, func: &str, types: &[&str]) -> Option<(String, String)> {
233+
fn get_types_from_cast(expr: &Expr, func: Symbol, types: &[Symbol]) -> Option<(Symbol, Symbol)> {
231234
// `to_type::maxmin_value() as from_type`
232-
let call_from_cast: Option<(&Expr, String)> = if_chain! {
235+
let call_from_cast: Option<(&Expr, Symbol)> = if_chain! {
233236
// to_type::maxmin_value(), from_type
234237
if let ExprKind::Cast(ref limit, ref from_type) = &expr.node;
235238
if let TyKind::Path(ref from_type_path) = &from_type.node;
236-
if let Some(from_type_str) = int_ty_to_str(from_type_path);
239+
if let Some(from_sym) = int_ty_to_sym(from_type_path);
237240

238241
then {
239-
Some((limit, from_type_str.to_string()))
242+
Some((limit, from_sym))
240243
} else {
241244
None
242245
}
243246
};
244247

245248
// `from_type::from(to_type::maxmin_value())`
246-
let limit_from: Option<(&Expr, String)> = call_from_cast.or_else(|| {
249+
let limit_from: Option<(&Expr, Symbol)> = call_from_cast.or_else(|| {
247250
if_chain! {
248251
// `from_type::from, to_type::maxmin_value()`
249252
if let ExprKind::Call(ref from_func, ref args) = &expr.node;
@@ -252,10 +255,10 @@ fn get_types_from_cast(expr: &Expr, func: &str, types: &[&str]) -> Option<(Strin
252255
if let limit = &args[0];
253256
// `from_type::from`
254257
if let ExprKind::Path(ref path) = &from_func.node;
255-
if let Some(from_type) = get_implementing_type(path, INT_TYPES, "from");
258+
if let Some(from_sym) = get_implementing_type(path, &*INTS, *sym::from);
256259

257260
then {
258-
Some((limit, from_type))
261+
Some((limit, from_sym))
259262
} else {
260263
None
261264
}
@@ -282,33 +285,33 @@ fn get_types_from_cast(expr: &Expr, func: &str, types: &[&str]) -> Option<(Strin
282285
}
283286

284287
/// Gets the type which implements the called function
285-
fn get_implementing_type(path: &QPath, candidates: &[&str], function: &str) -> Option<String> {
288+
fn get_implementing_type(path: &QPath, candidates: &[Symbol], function: Symbol) -> Option<Symbol> {
286289
if_chain! {
287290
if let QPath::TypeRelative(ref ty, ref path) = &path;
288291
if path.ident.name == function;
289292
if let TyKind::Path(QPath::Resolved(None, ref tp)) = &ty.node;
290293
if let [int] = &*tp.segments;
291-
let name = int.ident.as_str().get();
294+
let name = int.ident.name;
292295
if candidates.contains(&name);
293296

294297
then {
295-
Some(name.to_string())
298+
Some(name)
296299
} else {
297300
None
298301
}
299302
}
300303
}
301304

302305
/// Gets the type as a string, if it is a supported integer
303-
fn int_ty_to_str(path: &QPath) -> Option<&str> {
306+
fn int_ty_to_sym(path: &QPath) -> Option<Symbol> {
304307
if_chain! {
305308
if let QPath::Resolved(_, ref path) = *path;
306309
if let [ty] = &*path.segments;
307310

308311
then {
309-
INT_TYPES
312+
INTS
310313
.iter()
311-
.find(|c| (&ty.ident.name) == *c)
314+
.find(|c| ty.ident.name == **c)
312315
.cloned()
313316
} else {
314317
None
@@ -333,8 +336,19 @@ fn normalize_le_ge<'a>(op: &'a BinOp, left: &'a Expr, right: &'a Expr) -> Option
333336
}
334337
}
335338

336-
const UNSIGNED_TYPES: &[&str] = &["u8", "u16", "u32", "u64", "u128", "usize"];
337-
const SIGNED_TYPES: &[&str] = &["i8", "i16", "i32", "i64", "i128", "isize"];
338-
const INT_TYPES: &[&str] = &[
339-
"u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", "isize",
340-
];
339+
lazy_static! {
340+
static ref UINTS: [Symbol; 5] = [*sym::u8, *sym::u16, *sym::u32, *sym::u64, *sym::usize];
341+
static ref SINTS: [Symbol; 5] = [*sym::i8, *sym::i16, *sym::i32, *sym::i64, *sym::isize];
342+
static ref INTS: [Symbol; 10] = [
343+
*sym::u8,
344+
*sym::u16,
345+
*sym::u32,
346+
*sym::u64,
347+
*sym::usize,
348+
*sym::i8,
349+
*sym::i16,
350+
*sym::i32,
351+
*sym::i64,
352+
*sym::isize
353+
];
354+
}

0 commit comments

Comments
 (0)