Skip to content

Commit

Permalink
auto merge of #6647 : alexcrichton/rust/unnecessary-alloc, r=graydon
Browse files Browse the repository at this point in the history
This adds a lint mode for detecting unnecessary allocations on the heap. This isn't super fancy, currently it only has two rules

1. For a function's arguments, if you allocate a `[~|@]str` literal, when the type of the argument is a `&str`, emit a warning.
2. For the same case, emit warnings for boxed vectors when slices are required.

After adding the lint, I rampaged through the libraries and removed all the unnecessary allocations I could find.
  • Loading branch information
bors committed May 21, 2013
2 parents d49a9db + 82fa001 commit 5a3e320
Show file tree
Hide file tree
Showing 100 changed files with 1,095 additions and 1,030 deletions.
2 changes: 1 addition & 1 deletion src/libcore/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ pub fn self_exe_path() -> Option<Path> {
* Otherwise, homedir returns option::none.
*/
pub fn homedir() -> Option<Path> {
return match getenv(~"HOME") {
return match getenv("HOME") {
Some(ref p) => if !str::is_empty(*p) {
Some(Path(*p))
} else {
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1808,7 +1808,7 @@ pub fn to_utf16(s: &str) -> ~[u16] {
ch -= 0x1_0000_u32;
let w1 = 0xD800_u16 | ((ch >> 10) as u16);
let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16);
u.push_all(~[w1, w2])
u.push_all([w1, w2])
}
}
u
Expand Down
4 changes: 2 additions & 2 deletions src/libcore/unstable/extfmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ pub mod ct {
i += 1;

if i >= lim {
err(~"unterminated conversion at end of string");
err("unterminated conversion at end of string");
} else if s[i] == '%' as u8 {
push_slice(&mut pieces, s, h, i);
i += 1;
Expand Down Expand Up @@ -309,7 +309,7 @@ pub mod ct {

pub fn parse_type(s: &str, i: uint, lim: uint, err: ErrorFn) ->
Parsed<Ty> {
if i >= lim { err(~"missing type in conversion"); }
if i >= lim { err("missing type in conversion"); }

// FIXME (#2249): Do we really want two signed types here?
// How important is it to be printf compatible?
Expand Down
43 changes: 21 additions & 22 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ pub mod write {
fmt!("%s/bin/arm-linux-androideabi-gcc", path)
}
&None => {
sess.fatal(~"need Android NDK path for building \
(--android-cross-path)")
sess.fatal("need Android NDK path for building \
(--android-cross-path)")
}
};
let mut cc_args = ~[];
Expand All @@ -403,7 +403,7 @@ pub mod write {
sess.err(fmt!("building with `%s` failed with code %d",
cc_prog, prog.status));
sess.note(fmt!("%s arguments: %s",
cc_prog, str::connect(cc_args, ~" ")));
cc_prog, str::connect(cc_args, " ")));
sess.note(prog.err + prog.out);
sess.abort_if_errors();
}
Expand Down Expand Up @@ -566,7 +566,7 @@ pub fn build_link_meta(sess: Session,
|| fmt!("output file name `%s` doesn't\
appear to have a stem",
output.to_str())).to_managed();
warn_missing(sess, ~"name", name);
warn_missing(sess, "name", name);
name
}
};
Expand All @@ -577,7 +577,7 @@ pub fn build_link_meta(sess: Session,
Some(v) => v,
None => {
let vers = @"0.0";
warn_missing(sess, ~"vers", vers);
warn_missing(sess, "vers", vers);
vers
}
};
Expand Down Expand Up @@ -618,9 +618,9 @@ pub fn symbol_hash(tcx: ty::ctxt,

symbol_hasher.reset();
write_string(symbol_hasher, link_meta.name);
write_string(symbol_hasher, ~"-");
write_string(symbol_hasher, "-");
write_string(symbol_hasher, link_meta.extras_hash);
write_string(symbol_hasher, ~"-");
write_string(symbol_hasher, "-");
write_string(symbol_hasher, encoder::encoded_ty(tcx, t));
let mut hash = truncated_hash_result(symbol_hasher);
// Prefix with _ so that it never blends into adjacent digits
Expand Down Expand Up @@ -770,8 +770,8 @@ pub fn link_binary(sess: Session,
fmt!("%s/bin/arm-linux-androideabi-gcc", path)
}
&None => {
sess.fatal(~"need Android NDK path for linking \
(--android-cross-path)")
sess.fatal("need Android NDK path for linking \
(--android-cross-path)")
}
}
} else if sess.targ_cfg.os == session::os_win32 {
Expand All @@ -798,21 +798,21 @@ pub fn link_binary(sess: Session,

debug!("output: %s", output.to_str());
let cc_args = link_args(sess, obj_filename, out_filename, lm);
debug!("%s link args: %s", cc_prog, str::connect(cc_args, ~" "));
debug!("%s link args: %s", cc_prog, str::connect(cc_args, " "));
// We run 'cc' here
let prog = run::program_output(cc_prog, cc_args);
if 0 != prog.status {
sess.err(fmt!("linking with `%s` failed with code %d",
cc_prog, prog.status));
sess.note(fmt!("%s arguments: %s",
cc_prog, str::connect(cc_args, ~" ")));
cc_prog, str::connect(cc_args, " ")));
sess.note(prog.err + prog.out);
sess.abort_if_errors();
}

// Clean up on Darwin
if sess.targ_cfg.os == session::os_macos {
run::run_program(~"dsymutil", ~[output.to_str()]);
run::run_program("dsymutil", [output.to_str()]);
}

// Remove the temporary object file if we aren't saving temps
Expand Down Expand Up @@ -920,27 +920,26 @@ pub fn link_args(sess: Session,
// On linux librt and libdl are an indirect dependencies via rustrt,
// and binutils 2.22+ won't add them automatically
if sess.targ_cfg.os == session::os_linux {
args.push_all(~[~"-lrt", ~"-ldl"]);
args.push_all([~"-lrt", ~"-ldl"]);

// LLVM implements the `frem` instruction as a call to `fmod`,
// which lives in libm. Similar to above, on some linuxes we
// have to be explicit about linking to it. See #2510
args.push(~"-lm");
}
else if sess.targ_cfg.os == session::os_android {
args.push_all(~[~"-ldl", ~"-llog", ~"-lsupc++",
~"-lgnustl_shared"]);
args.push_all([~"-ldl", ~"-llog", ~"-lsupc++", ~"-lgnustl_shared"]);
args.push(~"-lm");
}

if sess.targ_cfg.os == session::os_freebsd {
args.push_all(~[~"-pthread", ~"-lrt",
~"-L/usr/local/lib", ~"-lexecinfo",
~"-L/usr/local/lib/gcc46",
~"-L/usr/local/lib/gcc44", ~"-lstdc++",
~"-Wl,-z,origin",
~"-Wl,-rpath,/usr/local/lib/gcc46",
~"-Wl,-rpath,/usr/local/lib/gcc44"]);
args.push_all([~"-pthread", ~"-lrt",
~"-L/usr/local/lib", ~"-lexecinfo",
~"-L/usr/local/lib/gcc46",
~"-L/usr/local/lib/gcc44", ~"-lstdc++",
~"-Wl,-z,origin",
~"-Wl,-rpath,/usr/local/lib/gcc46",
~"-Wl,-rpath,/usr/local/lib/gcc44"]);
}

// OS X 10.6 introduced 'compact unwind info', which is produced by the
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/back/rpath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,9 @@ fn get_rpaths(os: session::os,
}
}

log_rpaths(~"relative", rel_rpaths);
log_rpaths(~"absolute", abs_rpaths);
log_rpaths(~"fallback", fallback_rpaths);
log_rpaths("relative", rel_rpaths);
log_rpaths("absolute", abs_rpaths);
log_rpaths("fallback", fallback_rpaths);

let mut rpaths = rel_rpaths;
rpaths.push_all(abs_rpaths);
Expand Down
109 changes: 64 additions & 45 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,7 @@ pub fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: &input,
match node {
pprust::node_expr(s, expr) => {
pp::space(s.s);
pp::word(s.s, ~"as");
pp::word(s.s, "as");
pp::space(s.s);
pp::word(s.s, ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr)));
pprust::pclose(s);
Expand Down Expand Up @@ -442,33 +442,33 @@ pub fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: &input,
}
pub fn get_os(triple: &str) -> Option<session::os> {
if str::contains(triple, ~"win32") ||
str::contains(triple, ~"mingw32") {
if str::contains(triple, "win32") ||
str::contains(triple, "mingw32") {
Some(session::os_win32)
} else if str::contains(triple, ~"darwin") {
} else if str::contains(triple, "darwin") {
Some(session::os_macos)
} else if str::contains(triple, ~"android") {
} else if str::contains(triple, "android") {
Some(session::os_android)
} else if str::contains(triple, ~"linux") {
} else if str::contains(triple, "linux") {
Some(session::os_linux)
} else if str::contains(triple, ~"freebsd") {
} else if str::contains(triple, "freebsd") {
Some(session::os_freebsd)
} else { None }
}

pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
if str::contains(triple, ~"i386") ||
str::contains(triple, ~"i486") ||
str::contains(triple, ~"i586") ||
str::contains(triple, ~"i686") ||
str::contains(triple, ~"i786") {
if str::contains(triple, "i386") ||
str::contains(triple, "i486") ||
str::contains(triple, "i586") ||
str::contains(triple, "i686") ||
str::contains(triple, "i786") {
Some(abi::X86)
} else if str::contains(triple, ~"x86_64") {
} else if str::contains(triple, "x86_64") {
Some(abi::X86_64)
} else if str::contains(triple, ~"arm") ||
str::contains(triple, ~"xscale") {
} else if str::contains(triple, "arm") ||
str::contains(triple, "xscale") {
Some(abi::Arm)
} else if str::contains(triple, ~"mips") {
} else if str::contains(triple, "mips") {
Some(abi::Mips)
} else { None }
}
Expand Down Expand Up @@ -508,6 +508,7 @@ pub fn build_target_config(sopts: @session::options,
return target_cfg;
}
#[cfg(stage0)]
pub fn host_triple() -> ~str {
// Get the host triple out of the build environment. This ensures that our
// idea of the host triple is the same as for the set of libraries we've
Expand All @@ -525,19 +526,37 @@ pub fn host_triple() -> ~str {
};
}

#[cfg(not(stage0))]
pub fn host_triple() -> ~str {
// Get the host triple out of the build environment. This ensures that our
// idea of the host triple is the same as for the set of libraries we've
// actually built. We can't just take LLVM's host triple because they
// normalize all ix86 architectures to i386.

// FIXME (#2400): Instead of grabbing the host triple we really should
// be grabbing (at compile time) the target triple that this rustc is
// built with and calling that (at runtime) the host triple.
let ht = env!("CFG_BUILD_TRIPLE");
return if ht != "" {
ht.to_owned()
} else {
fail!("rustc built without CFG_BUILD_TRIPLE")
};
}

pub fn build_session_options(binary: @~str,
matches: &getopts::Matches,
demitter: diagnostic::Emitter)
-> @session::options {
let crate_type = if opt_present(matches, ~"lib") {
let crate_type = if opt_present(matches, "lib") {
session::lib_crate
} else if opt_present(matches, ~"bin") {
} else if opt_present(matches, "bin") {
session::bin_crate
} else {
session::unknown_crate
};
let parse_only = opt_present(matches, ~"parse-only");
let no_trans = opt_present(matches, ~"no-trans");
let parse_only = opt_present(matches, "parse-only");
let no_trans = opt_present(matches, "no-trans");

let lint_levels = [lint::allow, lint::warn,
lint::deny, lint::forbid];
Expand All @@ -553,7 +572,7 @@ pub fn build_session_options(binary: @~str,
let flags = vec::append(getopts::opt_strs(matches, level_short),
getopts::opt_strs(matches, level_name));
for flags.each |lint_name| {
let lint_name = str::replace(*lint_name, ~"-", ~"_");
let lint_name = str::replace(*lint_name, "-", "_");
match lint_dict.find(&lint_name) {
None => {
early_error(demitter, fmt!("unknown %s flag: %s",
Expand All @@ -567,7 +586,7 @@ pub fn build_session_options(binary: @~str,
}

let mut debugging_opts = 0u;
let debug_flags = getopts::opt_strs(matches, ~"Z");
let debug_flags = getopts::opt_strs(matches, "Z");
let debug_map = session::debugging_opts_map();
for debug_flags.each |debug_flag| {
let mut this_bit = 0u;
Expand All @@ -589,31 +608,31 @@ pub fn build_session_options(binary: @~str,
let output_type =
if parse_only || no_trans {
link::output_type_none
} else if opt_present(matches, ~"S") &&
opt_present(matches, ~"emit-llvm") {
} else if opt_present(matches, "S") &&
opt_present(matches, "emit-llvm") {
link::output_type_llvm_assembly
} else if opt_present(matches, ~"S") {
} else if opt_present(matches, "S") {
link::output_type_assembly
} else if opt_present(matches, ~"c") {
} else if opt_present(matches, "c") {
link::output_type_object
} else if opt_present(matches, ~"emit-llvm") {
} else if opt_present(matches, "emit-llvm") {
link::output_type_bitcode
} else { link::output_type_exe };
let sysroot_opt = getopts::opt_maybe_str(matches, ~"sysroot");
let sysroot_opt = getopts::opt_maybe_str(matches, "sysroot");
let sysroot_opt = sysroot_opt.map(|m| @Path(*m));
let target_opt = getopts::opt_maybe_str(matches, ~"target");
let target_feature_opt = getopts::opt_maybe_str(matches, ~"target-feature");
let save_temps = getopts::opt_present(matches, ~"save-temps");
let target_opt = getopts::opt_maybe_str(matches, "target");
let target_feature_opt = getopts::opt_maybe_str(matches, "target-feature");
let save_temps = getopts::opt_present(matches, "save-temps");
let opt_level = {
if (debugging_opts & session::no_opt) != 0 {
No
} else if opt_present(matches, ~"O") {
if opt_present(matches, ~"opt-level") {
} else if opt_present(matches, "O") {
if opt_present(matches, "opt-level") {
early_error(demitter, ~"-O and --opt-level both provided");
}
Default
} else if opt_present(matches, ~"opt-level") {
match getopts::opt_str(matches, ~"opt-level") {
} else if opt_present(matches, "opt-level") {
match getopts::opt_str(matches, "opt-level") {
~"0" => No,
~"1" => Less,
~"2" => Default,
Expand Down Expand Up @@ -641,20 +660,20 @@ pub fn build_session_options(binary: @~str,
Some(s) => s
};

let addl_lib_search_paths = getopts::opt_strs(matches, ~"L").map(|s| Path(*s));
let linker = getopts::opt_maybe_str(matches, ~"linker");
let linker_args = getopts::opt_strs(matches, ~"link-args").flat_map( |a| {
let addl_lib_search_paths = getopts::opt_strs(matches, "L").map(|s| Path(*s));
let linker = getopts::opt_maybe_str(matches, "linker");
let linker_args = getopts::opt_strs(matches, "link-args").flat_map( |a| {
let mut args = ~[];
for str::each_split_char(*a, ' ') |arg| {
args.push(str::to_owned(arg));
}
args
});

let cfg = parse_cfgspecs(getopts::opt_strs(matches, ~"cfg"), demitter);
let test = opt_present(matches, ~"test");
let cfg = parse_cfgspecs(getopts::opt_strs(matches, "cfg"), demitter);
let test = opt_present(matches, "test");
let android_cross_path = getopts::opt_maybe_str(
matches, ~"android-cross-path");
matches, "android-cross-path");

let sopts = @session::options {
crate_type: crate_type,
Expand Down Expand Up @@ -732,9 +751,9 @@ pub fn parse_pretty(sess: Session, name: &str) -> pp_mode {
&"expanded,identified" => ppm_expanded_identified,
&"identified" => ppm_identified,
_ => {
sess.fatal(~"argument to `pretty` must be one of `normal`, \
`expanded`, `typed`, `identified`, \
or `expanded,identified`");
sess.fatal("argument to `pretty` must be one of `normal`, \
`expanded`, `typed`, `identified`, \
or `expanded,identified`");
}
}
}
Expand Down Expand Up @@ -875,7 +894,7 @@ pub fn build_output_filenames(input: &input,
}

if *odir != None {
sess.warn(~"ignoring --out-dir flag due to -o flag.");
sess.warn("ignoring --out-dir flag due to -o flag.");
}
}
}
Expand Down
Loading

0 comments on commit 5a3e320

Please sign in to comment.