librustc: Remove some string allocations. rs=perf

This commit is contained in:
Patrick Walton 2013-01-05 19:33:37 -08:00
parent 1070cc0109
commit fa96740923
5 changed files with 97 additions and 85 deletions

View File

@ -105,12 +105,12 @@ impl lint : cmp::Eq {
pure fn ne(&self, other: &lint) -> bool { !(*self).eq(other) }
}
fn level_to_str(lv: level) -> ~str {
fn level_to_str(lv: level) -> &static/str {
match lv {
allow => ~"allow",
warn => ~"warn",
deny => ~"deny",
forbid => ~"forbid"
allow => "allow",
warn => "warn",
deny => "deny",
forbid => "forbid"
}
}
@ -126,7 +126,7 @@ impl level : cmp::Eq {
}
type lint_spec = @{lint: lint,
desc: ~str,
desc: &static/str,
default: level};
type lint_dict = HashMap<~str,lint_spec>;
@ -139,109 +139,109 @@ fn get_lint_dict() -> lint_dict {
let v = ~[
(~"ctypes",
@{lint: ctypes,
desc: ~"proper use of core::libc types in foreign modules",
desc: "proper use of core::libc types in foreign modules",
default: warn}),
(~"unused_imports",
@{lint: unused_imports,
desc: ~"imports that are never used",
desc: "imports that are never used",
default: allow}),
(~"while_true",
@{lint: while_true,
desc: ~"suggest using loop { } instead of while(true) { }",
desc: "suggest using loop { } instead of while(true) { }",
default: warn}),
(~"path_statement",
@{lint: path_statement,
desc: ~"path statements with no effect",
desc: "path statements with no effect",
default: warn}),
(~"unrecognized_lint",
@{lint: unrecognized_lint,
desc: ~"unrecognized lint attribute",
desc: "unrecognized lint attribute",
default: warn}),
(~"non_implicitly_copyable_typarams",
@{lint: non_implicitly_copyable_typarams,
desc: ~"passing non implicitly copyable types as copy type params",
desc: "passing non implicitly copyable types as copy type params",
default: warn}),
(~"vecs_implicitly_copyable",
@{lint: vecs_implicitly_copyable,
desc: ~"make vecs and strs not implicitly copyable \
desc: "make vecs and strs not implicitly copyable \
(only checked at top level)",
default: warn}),
(~"implicit_copies",
@{lint: implicit_copies,
desc: ~"implicit copies of non implicitly copyable data",
desc: "implicit copies of non implicitly copyable data",
default: warn}),
(~"deprecated_mode",
@{lint: deprecated_mode,
desc: ~"warn about deprecated uses of modes",
desc: "warn about deprecated uses of modes",
default: warn}),
(~"deprecated_pattern",
@{lint: deprecated_pattern,
desc: ~"warn about deprecated uses of pattern bindings",
desc: "warn about deprecated uses of pattern bindings",
default: allow}),
(~"non_camel_case_types",
@{lint: non_camel_case_types,
desc: ~"types, variants and traits should have camel case names",
desc: "types, variants and traits should have camel case names",
default: allow}),
(~"managed_heap_memory",
@{lint: managed_heap_memory,
desc: ~"use of managed (@ type) heap memory",
desc: "use of managed (@ type) heap memory",
default: allow}),
(~"owned_heap_memory",
@{lint: owned_heap_memory,
desc: ~"use of owned (~ type) heap memory",
desc: "use of owned (~ type) heap memory",
default: allow}),
(~"heap_memory",
@{lint: heap_memory,
desc: ~"use of any (~ type or @ type) heap memory",
desc: "use of any (~ type or @ type) heap memory",
default: allow}),
(~"structural_records",
@{lint: structural_records,
desc: ~"use of any structural records",
desc: "use of any structural records",
default: allow}),
(~"legacy modes",
@{lint: legacy_modes,
desc: ~"allow legacy modes",
desc: "allow legacy modes",
default: forbid}),
(~"type_limits",
@{lint: type_limits,
desc: ~"comparisons made useless by limits of the types involved",
desc: "comparisons made useless by limits of the types involved",
default: warn}),
(~"default_methods",
@{lint: default_methods,
desc: ~"allow default methods",
desc: "allow default methods",
default: deny}),
(~"deprecated_self",
@{lint: deprecated_self,
desc: ~"warn about deprecated uses of `self`",
desc: "warn about deprecated uses of `self`",
default: allow}),
/* FIXME(#3266)--make liveness warnings lintable
(~"unused_variable",
@{lint: unused_variable,
desc: ~"detect variables which are not used in any way",
desc: "detect variables which are not used in any way",
default: warn}),
(~"dead_assignment",
@{lint: dead_assignment,
desc: ~"detect assignments that will never be read",
desc: "detect assignments that will never be read",
default: warn}),
*/
];

View File

@ -33,6 +33,7 @@ use core::dvec::DVec;
use core::dvec;
use core::ops;
use core::option;
use core::ptr::to_unsafe_ptr;
use core::result::Result;
use core::result;
use core::to_bytes;
@ -304,18 +305,22 @@ impl creader_cache_key : to_bytes::IterBytes {
}
}
type intern_key = {sty: sty, o_def_id: Option<ast::def_id>};
type intern_key = {sty: *sty, o_def_id: Option<ast::def_id>};
impl intern_key : cmp::Eq {
pure fn eq(&self, other: &intern_key) -> bool {
(*self).sty == (*other).sty && (*self).o_def_id == (*other).o_def_id
unsafe {
*self.sty == *other.sty && self.o_def_id == other.o_def_id
}
}
pure fn ne(&self, other: &intern_key) -> bool { !(*self).eq(other) }
}
impl intern_key : to_bytes::IterBytes {
pure fn iter_bytes(&self, +lsb0: bool, f: to_bytes::Cb) {
to_bytes::iter_bytes_2(&self.sty, &self.o_def_id, lsb0, f);
unsafe {
to_bytes::iter_bytes_2(&*self.sty, &self.o_def_id, lsb0, f);
}
}
}
@ -1008,11 +1013,12 @@ fn mk_t(cx: ctxt, +st: sty) -> t { mk_t_with_id(cx, st, None) }
// Interns a type/name combination, stores the resulting box in cx.interner,
// and returns the box as cast to an unsafe ptr (see comments for t above).
fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
let key = {sty: st, o_def_id: o_def_id};
let key = {sty: to_unsafe_ptr(&st), o_def_id: o_def_id};
match cx.interner.find(key) {
Some(t) => unsafe { return cast::reinterpret_cast(&t); },
_ => ()
}
let mut flags = 0u;
fn rflags(r: Region) -> uint {
(has_regions as uint) | {
@ -1028,42 +1034,46 @@ fn mk_t_with_id(cx: ctxt, +st: sty, o_def_id: Option<ast::def_id>) -> t {
substs.self_r.iter(|r| f |= rflags(*r));
return f;
}
match st {
ty_estr(vstore_slice(r)) => {
match &st {
&ty_estr(vstore_slice(r)) => {
flags |= rflags(r);
}
ty_evec(mt, vstore_slice(r)) => {
&ty_evec(ref mt, vstore_slice(r)) => {
flags |= rflags(r);
flags |= get(mt.ty).flags;
}
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) |
ty_opaque_box | ty_err => (),
ty_param(_) => flags |= has_params as uint,
ty_infer(_) => flags |= needs_infer as uint,
ty_self => flags |= has_self as uint,
ty_enum(_, ref substs) | ty_struct(_, ref substs)
| ty_trait(_, ref substs, _) => {
&ty_nil | &ty_bot | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
&ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
&ty_opaque_box | &ty_err => (),
&ty_param(_) => flags |= has_params as uint,
&ty_infer(_) => flags |= needs_infer as uint,
&ty_self => flags |= has_self as uint,
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
&ty_trait(_, ref substs, _) => {
flags |= sflags(substs);
}
ty_box(m) | ty_uniq(m) | ty_evec(m, _) |
ty_ptr(m) | ty_unboxed_vec(m) => {
&ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
&ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
flags |= get(m.ty).flags;
}
ty_rptr(r, m) => {
&ty_rptr(r, ref m) => {
flags |= rflags(r);
flags |= get(m.ty).flags;
}
ty_rec(flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
ty_tup(ts) => for ts.each |tt| { flags |= get(*tt).flags; },
ty_fn(ref f) => {
&ty_rec(ref flds) => for flds.each |f| { flags |= get(f.mt.ty).flags; },
&ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
&ty_fn(ref f) => {
flags |= rflags(f.meta.region);
for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
flags |= get(f.sig.output).flags;
}
}
let t = @{sty: st, id: cx.next_id, flags: flags, o_def_id: o_def_id};
cx.interner.insert(key, t);
let t = @{sty: move st, id: cx.next_id, flags: flags, o_def_id: o_def_id};
let key = {sty: to_unsafe_ptr(&t.sty), o_def_id: o_def_id};
cx.interner.insert(move key, t);
cx.next_id += 1u;
unsafe { cast::reinterpret_cast(&t) }
}

View File

@ -54,6 +54,8 @@
// terms of error reporting, although we do not do that properly right
// now.
#[warn(vecs_implicitly_copyable)];
use middle::ty;
use middle::ty::{FnTyBase, FnMeta, FnSig};
use middle::typeck::infer::sub::Sub;

View File

@ -69,16 +69,16 @@ fn explain_region_and_span(cx: ctxt, region: ty::Region)
re_scope(node_id) => {
match cx.items.find(node_id) {
Some(ast_map::node_block(ref blk)) => {
explain_span(cx, ~"block", (*blk).span)
explain_span(cx, "block", (*blk).span)
}
Some(ast_map::node_expr(expr)) => {
match expr.node {
ast::expr_call(*) => explain_span(cx, ~"call", expr.span),
ast::expr_call(*) => explain_span(cx, "call", expr.span),
ast::expr_method_call(*) => {
explain_span(cx, ~"method call", expr.span)
explain_span(cx, "method call", expr.span)
},
ast::expr_match(*) => explain_span(cx, ~"match", expr.span),
_ => explain_span(cx, ~"expression", expr.span)
ast::expr_match(*) => explain_span(cx, "match", expr.span),
_ => explain_span(cx, "expression", expr.span)
}
}
Some(_) | None => {
@ -99,7 +99,7 @@ fn explain_region_and_span(cx: ctxt, region: ty::Region)
match cx.items.find(id) {
Some(ast_map::node_block(ref blk)) => {
let (msg, opt_span) = explain_span(cx, ~"block", (*blk).span);
let (msg, opt_span) = explain_span(cx, "block", (*blk).span);
(fmt!("%s %s", prefix, msg), opt_span)
}
Some(_) | None => {
@ -118,7 +118,7 @@ fn explain_region_and_span(cx: ctxt, region: ty::Region)
}
};
fn explain_span(cx: ctxt, heading: ~str, span: span)
fn explain_span(cx: ctxt, heading: &str, span: span)
-> (~str, Option<span>)
{
let lo = cx.sess.codemap.lookup_char_pos_adj(span.lo);
@ -128,17 +128,17 @@ fn explain_region_and_span(cx: ctxt, region: ty::Region)
}
fn bound_region_to_str(cx: ctxt, br: bound_region) -> ~str {
bound_region_to_str_adorned(cx, ~"&", br, ~"")
bound_region_to_str_adorned(cx, "&", br, "")
}
fn bound_region_to_str_adorned(cx: ctxt, prefix: ~str,
br: bound_region, sep: ~str) -> ~str {
fn bound_region_to_str_adorned(cx: ctxt, prefix: &str,
br: bound_region, sep: &str) -> ~str {
if cx.sess.verbose() { return fmt!("%s%?%s", prefix, br, sep); }
match br {
br_named(id) => fmt!("%s%s%s", prefix, cx.sess.str_of(id), sep),
br_self => fmt!("%sself%s", prefix, sep),
br_anon(_) => prefix,
br_anon(_) => prefix.to_str(),
br_cap_avoid(_, br) => bound_region_to_str_adorned(cx, prefix,
*br, sep)
}
@ -188,11 +188,11 @@ fn re_scope_id_to_str(cx: ctxt, node_id: ast::node_id) -> ~str {
// you should use `explain_region()` or, better yet,
// `note_and_explain_region()`
fn region_to_str(cx: ctxt, region: Region) -> ~str {
region_to_str_adorned(cx, ~"&", region, ~"")
region_to_str_adorned(cx, "&", region, "")
}
fn region_to_str_adorned(cx: ctxt, prefix: ~str,
region: Region, sep: ~str) -> ~str {
fn region_to_str_adorned(cx: ctxt, prefix: &str,
region: Region, sep: &str) -> ~str {
if cx.sess.verbose() {
return fmt!("%s%?%s", prefix, region, sep);
}
@ -202,24 +202,24 @@ fn region_to_str_adorned(cx: ctxt, prefix: ~str,
// to fit that into a short string. Hence the recommendation to use
// `explain_region()` or `note_and_explain_region()`.
match region {
re_scope(_) => prefix,
re_scope(_) => prefix.to_str(),
re_bound(br) => bound_region_to_str_adorned(cx, prefix, br, sep),
re_free(_, br) => bound_region_to_str_adorned(cx, prefix, br, sep),
re_infer(ReSkolemized(_, br)) => {
bound_region_to_str_adorned(cx, prefix, br, sep)
}
re_infer(ReVar(_)) => prefix,
re_infer(ReVar(_)) => prefix.to_str(),
re_static => fmt!("%sstatic%s", prefix, sep)
}
}
fn mt_to_str(cx: ctxt, m: mt) -> ~str {
let mstr = match m.mutbl {
ast::m_mutbl => ~"mut ",
ast::m_imm => ~"",
ast::m_const => ~"const "
ast::m_mutbl => "mut ",
ast::m_imm => "",
ast::m_const => "const "
};
return mstr + ty_to_str(cx, m.ty);
return fmt!("%s%s", mstr, ty_to_str(cx, m.ty));
}
fn vstore_to_str(cx: ctxt, vs: ty::vstore) -> ~str {
@ -243,12 +243,12 @@ fn vstore_ty_to_str(cx: ctxt, ty: ~str, vs: ty::vstore) -> ~str {
}
}
fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto) -> ~str {
fn proto_ty_to_str(_cx: ctxt, proto: ast::Proto) -> &static/str {
match proto {
ast::ProtoBare => ~"",
ast::ProtoBox => ~"@",
ast::ProtoBorrowed => ~"&",
ast::ProtoUniq => ~"~",
ast::ProtoBare => "",
ast::ProtoBox => "@",
ast::ProtoBorrowed => "&",
ast::ProtoUniq => "~",
}
}
@ -278,11 +278,11 @@ fn ty_to_str(cx: ctxt, typ: t) -> ~str {
m == ty::default_arg_mode_for_ty(cx, ty) {
~""
} else {
mode_to_str(ast::expl(m)) + ":"
mode_to_str(ast::expl(m)) + ~":"
}
}
};
modestr + ty_to_str(cx, ty)
fmt!("%s%s", modestr, ty_to_str(cx, ty))
}
fn fn_to_str(cx: ctxt,
proto: ast::Proto,
@ -442,7 +442,7 @@ fn parameterized(cx: ctxt,
if vec::len(tps) > 0u {
let strs = vec::map(tps, |t| ty_to_str(cx, *t));
fmt!("%s%s<%s>", base, r_str, str::connect(strs, ~","))
fmt!("%s%s<%s>", base, r_str, str::connect(strs, ","))
} else {
fmt!("%s%s", base, r_str)
}

View File

@ -178,15 +178,15 @@ fn get_name_value_str_pair(item: @ast::meta_item) -> Option<(~str, ~str)> {
/* Searching */
/// Search a list of attributes and return only those with a specific name
fn find_attrs_by_name(attrs: ~[ast::attribute], name: ~str) ->
fn find_attrs_by_name(attrs: ~[ast::attribute], name: &str) ->
~[ast::attribute] {
let filter = (
fn@(a: &ast::attribute) -> Option<ast::attribute> {
if get_attr_name(*a) == name {
option::Some(*a)
} else { option::None }
let filter: &fn(a: &ast::attribute) -> Option<ast::attribute> = |a| {
if name == get_attr_name(*a) {
option::Some(*a)
} else {
option::None
}
);
};
return vec::filter_map(attrs, filter);
}