Extend allocation lint for boxing expressions

This commit is contained in:
Seo Sanghyeon 2013-12-09 23:18:24 +09:00
parent e5f2021202
commit 3b14f25868
6 changed files with 62 additions and 23 deletions

View File

@ -428,7 +428,7 @@ fn len_and_str(s: &str) -> ~str {
} }
fn len_and_str_lit(l: ast::lit) -> ~str { fn len_and_str_lit(l: ast::lit) -> ~str {
len_and_str(pprust::lit_to_str(@l)) len_and_str(pprust::lit_to_str(&l))
} }
let cmh_items = attr::sort_meta_items(cmh_items); let cmh_items = attr::sort_meta_items(cmh_items);

View File

@ -330,7 +330,7 @@ pub fn main() {
}; };
debug!("Synthetic test module:\n{}\n", debug!("Synthetic test module:\n{}\n",
pprust::item_to_str(@item.clone(), cx.sess.intr())); pprust::item_to_str(&item, cx.sess.intr()));
return @item; return @item;
} }

View File

@ -1028,27 +1028,47 @@ fn check_unused_mut_pat(cx: &Context, p: &ast::Pat) {
} }
} }
enum Allocation {
VectorAllocation,
BoxAllocation
}
fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) { fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) {
// Warn if string and vector literals with sigils are immediately borrowed. // Warn if string and vector literals with sigils, or boxing expressions,
// Those can have the sigil removed. // are immediately borrowed.
match e.node { let allocation = match e.node {
ast::ExprVstore(e2, ast::ExprVstoreUniq) | ast::ExprVstore(e2, ast::ExprVstoreUniq) |
ast::ExprVstore(e2, ast::ExprVstoreBox) => { ast::ExprVstore(e2, ast::ExprVstoreBox) => {
match e2.node { match e2.node {
ast::ExprLit(@codemap::Spanned{node: ast::lit_str(..), ..}) | ast::ExprLit(@codemap::Spanned{node: ast::lit_str(..), ..}) |
ast::ExprVec(..) => {} ast::ExprVec(..) => VectorAllocation,
_ => return _ => return
} }
} }
ast::ExprUnary(_, ast::UnUniq, _) |
ast::ExprUnary(_, ast::UnBox(..), _) => BoxAllocation,
_ => return _ => return
} };
let report = |msg| {
cx.span_lint(unnecessary_allocation, e.span, msg);
};
match cx.tcx.adjustments.find_copy(&e.id) { match cx.tcx.adjustments.find_copy(&e.id) {
Some(@ty::AutoDerefRef(ty::AutoDerefRef { Some(@ty::AutoDerefRef(ty::AutoDerefRef { autoref, .. })) => {
autoref: Some(ty::AutoBorrowVec(..)), .. })) => { match (allocation, autoref) {
cx.span_lint(unnecessary_allocation, e.span, (VectorAllocation, Some(ty::AutoBorrowVec(..))) => {
"unnecessary allocation, the sigil can be removed"); report("unnecessary allocation, the sigil can be removed");
}
(BoxAllocation, Some(ty::AutoPtr(_, ast::MutImmutable))) => {
report("unnecessary allocation, use & instead");
}
(BoxAllocation, Some(ty::AutoPtr(_, ast::MutMutable))) => {
report("unnecessary allocation, use &mut instead");
}
_ => ()
}
} }
_ => () _ => ()

View File

@ -119,28 +119,28 @@ fn to_source(&self) -> @str {
impl<'self> ToSource for &'self str { impl<'self> ToSource for &'self str {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_str(self.to_managed(), ast::CookedStr)); let lit = dummy_spanned(ast::lit_str(self.to_managed(), ast::CookedStr));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
impl ToSource for int { impl ToSource for int {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i)); let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
impl ToSource for i8 { impl ToSource for i8 {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i8)); let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i8));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
impl ToSource for i16 { impl ToSource for i16 {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i16)); let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i16));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
@ -148,49 +148,49 @@ fn to_source(&self) -> @str {
impl ToSource for i32 { impl ToSource for i32 {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i32)); let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i32));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
impl ToSource for i64 { impl ToSource for i64 {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i64)); let lit = dummy_spanned(ast::lit_int(*self as i64, ast::ty_i64));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
impl ToSource for uint { impl ToSource for uint {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u)); let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
impl ToSource for u8 { impl ToSource for u8 {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u8)); let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u8));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
impl ToSource for u16 { impl ToSource for u16 {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u16)); let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u16));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
impl ToSource for u32 { impl ToSource for u32 {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u32)); let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u32));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }
impl ToSource for u64 { impl ToSource for u64 {
fn to_source(&self) -> @str { fn to_source(&self) -> @str {
let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u64)); let lit = dummy_spanned(ast::lit_uint(*self as u64, ast::ty_u64));
pprust::lit_to_str(@lit).to_managed() pprust::lit_to_str(&lit).to_managed()
} }
} }

View File

@ -1902,7 +1902,7 @@ pub fn print_meta_item(s: @ps, item: &ast::MetaItem) {
ast::MetaNameValue(name, value) => { ast::MetaNameValue(name, value) => {
word_space(s, name); word_space(s, name);
word_space(s, "="); word_space(s, "=");
print_literal(s, @value); print_literal(s, &value);
} }
ast::MetaList(name, ref items) => { ast::MetaList(name, ref items) => {
word(s.s, name); word(s.s, name);

View File

@ -0,0 +1,19 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deny(unnecessary_allocation)];
fn f(_: &int) {}
fn g(_: &mut int) {}
fn main() {
f(~1); //~ ERROR unnecessary allocation, use & instead
g(~1); //~ ERROR unnecessary allocation, use &mut instead
}