diff --git a/src/libcore/path.rs b/src/libcore/path.rs index d03de47fa95..1cfafd25740 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -169,7 +169,8 @@ fn splitext(p: path) -> (str, str) { let parts = str::split_char(p, '.'); if vec::len(parts) > 1u { let base = str::connect(vec::init(parts), "."); - let ext = "." + vec::last_total(parts); + // We just checked that parts is non-empty, so this is safe + let ext = "." + vec::last_unsafe(parts); fn is_dotfile(base: str) -> bool { str::is_empty(base) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index 310232dec9b..3737f9bac1d 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -200,14 +200,15 @@ pure fn last(v: [const T]) -> option { } /* -Function: last_total +Function: last_unsafe -Returns the last element of a non-empty vector `v` +Returns the last element of a `v`, failing if the vector is empty. -Predicates: - (v) */ -pure fn last_total(v: [const T]) -> T { v[len(v) - 1u] } +pure fn last_unsafe(v: [const T]) -> T { + if len(v) == 0u { fail "last_unsafe: empty vector" } + v[len(v) - 1u] +} /* Function: slice diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 767908339a1..6627b0fec21 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -270,7 +270,8 @@ fn splitext(p: path) -> (str, str) { let parts = str::split_char(p, '.'); if vec::len(parts) > 1u { let base = str::connect(vec::init(parts), "."); - let ext = "." + vec::last_total(parts); + // We just checked that parts is non-empty + let ext = "." + vec::last_unsafe(parts); fn is_dotfile(base: str) -> bool { str::is_empty(base) diff --git a/src/rustc/middle/ast_map.rs b/src/rustc/middle/ast_map.rs index d1c80090e8c..72a89feedd9 100644 --- a/src/rustc/middle/ast_map.rs +++ b/src/rustc/middle/ast_map.rs @@ -187,7 +187,9 @@ fn map_view_item(vi: @view_item, cx: ctx, _v: vt) { let (id, name) = alt vp.node { view_path_simple(nm, _, id) { (id, nm) } view_path_glob(pth, id) | view_path_list(pth, _, id) { - (id, vec::last_total(*pth)) + // should be a constraint on the type + assert (vec::is_not_empty(*pth)); + (id, vec::last_unsafe(*pth)) } }; cx.map.insert(id, node_export(vp, extend(cx, name))); diff --git a/src/rustc/middle/pat_util.rs b/src/rustc/middle/pat_util.rs index 08aa720be68..bc98c621a34 100644 --- a/src/rustc/middle/pat_util.rs +++ b/src/rustc/middle/pat_util.rs @@ -68,4 +68,7 @@ fn pat_binding_ids(dm: resolve::def_map, pat: @pat) -> [node_id] { ret found; } -fn path_to_ident(p: @path) -> ident { vec::last_total(p.node.idents) } +fn path_to_ident(p: @path) -> ident { + assert (vec::is_not_empty(p.node.idents)); // should be a constraint on path + vec::last_unsafe(p.node.idents) +} diff --git a/src/rustdoc/reexport_pass.rs b/src/rustdoc/reexport_pass.rs index 99f2e19149e..02ffa3337b4 100644 --- a/src/rustdoc/reexport_pass.rs +++ b/src/rustdoc/reexport_pass.rs @@ -161,7 +161,9 @@ fn build_reexport_path_map(srv: astsrv::srv, -def_map: def_map) -> path_map { let path = alt check ctxt.ast_map.get(exp_id) { ast_map::node_export(_, path) { path } }; - let name = alt check vec::last_total(*path) { + // should be a constraint on the node_export constructor + // that guarantees path is non-empty + let name = alt check vec::last_unsafe(*path) { ast_map::path_name(nm) { nm } }; let modpath = ast_map::path_to_str(vec::init(*path)); diff --git a/src/test/run-pass/zip-same-length.rs b/src/test/run-pass/zip-same-length.rs index d1950be9efa..787fd3e1c1e 100644 --- a/src/test/run-pass/zip-same-length.rs +++ b/src/test/run-pass/zip-same-length.rs @@ -19,5 +19,5 @@ fn main() { check (is_not_empty(ps)); assert (head(ps) == ('a', 1u)); - assert (last_total(ps) == (j as char, 10u)); + assert (last_unsafe(ps) == (j as char, 10u)); }