@@ -79,6 +79,7 @@ pub enum lint {
79
79
unused_variable,
80
80
dead_assignment,
81
81
unused_mut,
82
+ unnecessary_allocation,
82
83
}
83
84
84
85
pub fn level_to_str ( lv : level ) -> & ' static str {
@@ -242,6 +243,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
242
243
desc : "detect mut variables which don't need to be mutable" ,
243
244
default : warn
244
245
} ) ,
246
+
247
+ ( "unnecessary_allocation" ,
248
+ LintSpec {
249
+ lint : unnecessary_allocation,
250
+ desc : "detects unnecessary allocations that can be eliminated" ,
251
+ default : warn
252
+ } ) ,
245
253
] ;
246
254
247
255
/*
@@ -881,6 +889,67 @@ fn lint_session(cx: @mut Context) -> visit::vt<()> {
881
889
} )
882
890
}
883
891
892
+ fn lint_unnecessary_allocations( cx: @mut Context ) -> visit:: vt<( ) > {
893
+ // If the expression `e` has an allocated type, but `t` dictates that it's
894
+ // something like a slice (doesn't need allocation), emit a warning with the
895
+ // specified span.
896
+ //
897
+ // Currently, this only applies to string and vector literals with sigils in
898
+ // front. Those can have the sigil removed to get a borrowed pointer
899
+ // automatically.
900
+ fn check ( cx : @mut Context , e : @ast:: expr , t : ty:: t ) {
901
+ match e. node {
902
+ ast:: expr_vstore( e2, ast:: expr_vstore_uniq) |
903
+ ast:: expr_vstore( e2, ast:: expr_vstore_box) => {
904
+ match e2. node {
905
+ ast:: expr_lit( @codemap:: spanned {
906
+ node : ast:: lit_str( * ) , _} ) |
907
+ ast:: expr_vec( * ) => { }
908
+ _ => return
909
+ }
910
+ }
911
+
912
+ _ => return
913
+ }
914
+
915
+ match ty:: get ( t) . sty {
916
+ ty:: ty_estr( ty:: vstore_slice( * ) ) |
917
+ ty:: ty_evec( _, ty:: vstore_slice( * ) ) => {
918
+ cx. span_lint ( unnecessary_allocation,
919
+ e. span , "unnecessary allocation, the sigil can be \
920
+ removed") ;
921
+ }
922
+
923
+ _ => ( )
924
+ }
925
+ }
926
+
927
+ let visit_expr: @fn ( @ast:: expr ) = |e| {
928
+ match e. node {
929
+ ast:: expr_call( c, ref args, _) => {
930
+ let t = ty:: node_id_to_type ( cx. tcx , c. id ) ;
931
+ let s = ty:: ty_fn_sig ( t) ;
932
+ for vec:: each2( * args, s. inputs) |e, t| {
933
+ check( cx, * e, * t) ;
934
+ }
935
+ }
936
+ ast:: expr_method_call ( _, _, _, ref args, _) => {
937
+ let t = ty:: node_id_to_type ( cx. tcx , e. callee_id ) ;
938
+ let s = ty:: ty_fn_sig ( t) ;
939
+ for vec:: each2( * args, s. inputs) |e, t| {
940
+ check( cx, * e, * t) ;
941
+ }
942
+ }
943
+ _ => { }
944
+ }
945
+ } ;
946
+
947
+ visit:: mk_simple_visitor ( @visit:: SimpleVisitor {
948
+ visit_expr : visit_expr,
949
+ .. * visit:: default_simple_visitor ( )
950
+ } )
951
+ }
952
+
884
953
pub fn check_crate( tcx: ty:: ctxt, crate : @ast:: crate) {
885
954
let cx = @mut Context {
886
955
dict : @get_lint_dict ( ) ,
@@ -908,6 +977,7 @@ pub fn check_crate(tcx: ty::ctxt, crate: @ast::crate) {
908
977
cx. add_lint ( lint_unused_unsafe ( cx) ) ;
909
978
cx. add_lint ( lint_unused_mut ( cx) ) ;
910
979
cx. add_lint ( lint_session ( cx) ) ;
980
+ cx. add_lint ( lint_unnecessary_allocations ( cx) ) ;
911
981
912
982
// type inference doesn't like this being declared below, we need to tell it
913
983
// what the type of this first function is...
0 commit comments