diff options
Diffstat (limited to 'components/plugins/lints.rs')
-rw-r--r-- | components/plugins/lints.rs | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/components/plugins/lints.rs b/components/plugins/lints.rs index 3cb4cb91e1f..ce744b47150 100644 --- a/components/plugins/lints.rs +++ b/components/plugins/lints.rs @@ -21,6 +21,8 @@ declare_lint!(PRIVATIZE, Deny, "Allows to enforce private fields for struct definitions") declare_lint!(INHERITANCE_INTEGRITY, Deny, "Ensures that struct fields are properly laid out for inheritance to work") +declare_lint!(STR_TO_STRING, Deny, + "Warn when a String could use into_string() instead of to_string()") /// Lint for auditing transmutes /// @@ -51,6 +53,11 @@ pub struct PrivatizePass; /// which itself is a DOM struct (in which case it must be the first field). pub struct InheritancePass; +/// Prefer str.into_string() over str.to_string() +/// +/// The latter creates a `Formatter` and is 5x slower than the former +pub struct StrToStringPass; + impl LintPass for TransmutePass { fn get_lints(&self) -> LintArray { lint_array!(TRANSMUTE_TYPE_LINT) @@ -332,3 +339,34 @@ impl LintPass for InheritancePass { } } } + +impl LintPass for StrToStringPass { + fn get_lints(&self) -> LintArray { + lint_array!(STR_TO_STRING) + } + + fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) { + match expr.node { + ast::ExprMethodCall(ref method, _, ref args) + if method.node.as_str() == "to_string" + && is_str(cx, &*args[0]) => { + cx.span_lint(STR_TO_STRING, expr.span, + "str.into_string() is more efficient than str.to_string(), please use it instead"); + }, + _ => () + } + + fn is_str(cx: &Context, expr: &ast::Expr) -> bool { + fn walk_ty<'t>(ty: ty::t) -> ty::t { + match ty::get(ty).sty { + ty::ty_ptr(ref tm) | ty::ty_rptr(_, ref tm) => walk_ty(tm.ty), + _ => ty + } + } + match ty::get(walk_ty(expr_ty(cx.tcx, expr))).sty { + ty::ty_str => true, + _ => false + } + } + } +} |