about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2012-07-11 23:42:26 -0700
committerMichael Sullivan <sully@msully.net>2012-07-12 16:52:26 -0700
commit2ea9c8df0f7c9ee72913883128b37d0a80d2f4f6 (patch)
treeb3e4acbf2912f804cb45f87e8819a5e4847ec213
parentacb86921a62ba01726fd922f55d0176fa6c1df7c (diff)
downloadrust-2ea9c8df0f7c9ee72913883128b37d0a80d2f4f6.tar.gz
rust-2ea9c8df0f7c9ee72913883128b37d0a80d2f4f6.zip
Accept prefix notation for writing the types of str/~ and friends.
-rw-r--r--doc/tutorial.md2
-rw-r--r--src/fuzzer/fuzzer.rs4
-rw-r--r--src/libcore/task.rs16
-rw-r--r--src/libcore/to_bytes.rs2
-rw-r--r--src/libcore/unsafe.rs4
-rw-r--r--src/libstd/json.rs8
-rw-r--r--src/libstd/map.rs4
-rw-r--r--src/libstd/rope.rs16
-rw-r--r--src/libsyntax/ast.rs6
-rw-r--r--src/libsyntax/attr.rs8
-rw-r--r--src/libsyntax/codemap.rs6
-rw-r--r--src/libsyntax/ext/auto_serialize.rs25
-rw-r--r--src/libsyntax/ext/simplext.rs2
-rw-r--r--src/libsyntax/ext/tt/transcribe.rs4
-rw-r--r--src/libsyntax/parse.rs18
-rw-r--r--src/libsyntax/parse/comments.rs2
-rw-r--r--src/libsyntax/parse/eval.rs2
-rw-r--r--src/libsyntax/parse/lexer.rs14
-rw-r--r--src/libsyntax/parse/parser.rs31
-rw-r--r--src/libsyntax/parse/token.rs2
-rw-r--r--src/libsyntax/print/pp.rs2
-rw-r--r--src/rustc/back/link.rs22
-rw-r--r--src/rustc/metadata/common.rs2
-rw-r--r--src/rustc/metadata/creader.rs2
-rw-r--r--src/rustc/metadata/cstore.rs12
-rw-r--r--src/rustc/metadata/decoder.rs8
-rw-r--r--src/rustc/metadata/loader.rs2
-rw-r--r--src/rustc/metadata/tyencode.rs2
-rw-r--r--src/rustc/middle/lint.rs5
-rw-r--r--src/rustc/middle/resolve3.rs17
-rw-r--r--src/rustc/middle/trans/tvec.rs2
-rw-r--r--src/rustc/middle/ty.rs2
-rw-r--r--src/rustc/middle/typeck/astconv.rs79
-rw-r--r--src/test/auxiliary/issue-2631-a.rs2
-rw-r--r--src/test/compile-fail/unsendable-class.rs4
-rw-r--r--src/test/run-fail/unwind-lambda.rs2
-rw-r--r--src/test/run-fail/unwind-misc-1.rs4
37 files changed, 198 insertions, 147 deletions
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 813ef7f9bc5..3f5c22f3404 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -1347,7 +1347,7 @@ imply ownership. Pointers may be borrowed from any type, in which case
 the pointer is guaranteed not to outlive the value it points to.
 
 ~~~~
-# fn work_with_foo_by_pointer(f: &str) { }
+# fn work_with_foo_by_pointer(f: &str/~) { }
 let foo = "foo";
 work_with_foo_by_pointer(&foo);
 ~~~~
diff --git a/src/fuzzer/fuzzer.rs b/src/fuzzer/fuzzer.rs
index d7d1e147d0b..a0621bf257f 100644
--- a/src/fuzzer/fuzzer.rs
+++ b/src/fuzzer/fuzzer.rs
@@ -418,7 +418,7 @@ fn check_compiling(filename: str) -> happiness {
 }
 
 
-fn parse_and_print(code: @str) -> str {
+fn parse_and_print(code: @str/~) -> str {
     let filename = "tmp.rs";
     let sess = parse::new_parse_sess(option::none);
     write_file(filename, *code);
@@ -501,7 +501,7 @@ fn file_might_not_converge(filename: str) -> bool {
     ret false;
 }
 
-fn check_roundtrip_convergence(code: @str, maxIters: uint) {
+fn check_roundtrip_convergence(code: @str/~, maxIters: uint) {
 
     let mut i = 0u;
     let mut newv = code;
diff --git a/src/libcore/task.rs b/src/libcore/task.rs
index 3d05611aa98..3ba11243155 100644
--- a/src/libcore/task.rs
+++ b/src/libcore/task.rs
@@ -1300,7 +1300,7 @@ fn test_unkillable_nested() {
 
 #[test]
 fn test_tls_multitask() unsafe {
-    fn my_key(+_x: @str) { }
+    fn my_key(+_x: @str/~) { }
     local_data_set(my_key, @"parent data");
     do task::spawn {
         assert local_data_get(my_key) == none; // TLS shouldn't carry over.
@@ -1316,7 +1316,7 @@ fn test_tls_multitask() unsafe {
 
 #[test]
 fn test_tls_overwrite() unsafe {
-    fn my_key(+_x: @str) { }
+    fn my_key(+_x: @str/~) { }
     local_data_set(my_key, @"first data");
     local_data_set(my_key, @"next data"); // Shouldn't leak.
     assert *(local_data_get(my_key).get()) == "next data";
@@ -1324,7 +1324,7 @@ fn test_tls_overwrite() unsafe {
 
 #[test]
 fn test_tls_pop() unsafe {
-    fn my_key(+_x: @str) { }
+    fn my_key(+_x: @str/~) { }
     local_data_set(my_key, @"weasel");
     assert *(local_data_pop(my_key).get()) == "weasel";
     // Pop must remove the data from the map.
@@ -1333,7 +1333,7 @@ fn test_tls_pop() unsafe {
 
 #[test]
 fn test_tls_modify() unsafe {
-    fn my_key(+_x: @str) { }
+    fn my_key(+_x: @str/~) { }
     local_data_modify(my_key, |data| {
         alt data {
             some(@val) { fail "unwelcome value: " + val }
@@ -1357,7 +1357,7 @@ fn test_tls_crust_automorestack_memorial_bug() unsafe {
     // jump over to the rust stack, which causes next_c_sp to get recorded as
     // something within a rust stack segment. Then a subsequent upcall (esp.
     // for logging, think vsnprintf) would run on a stack smaller than 1 MB.
-    fn my_key(+_x: @str) { }
+    fn my_key(+_x: @str/~) { }
     do task::spawn {
         unsafe { local_data_set(my_key, @"hax"); }
     }
@@ -1365,7 +1365,7 @@ fn test_tls_crust_automorestack_memorial_bug() unsafe {
 
 #[test]
 fn test_tls_multiple_types() unsafe {
-    fn str_key(+_x: @str) { }
+    fn str_key(+_x: @str/~) { }
     fn box_key(+_x: @@()) { }
     fn int_key(+_x: @int) { }
     do task::spawn {
@@ -1377,7 +1377,7 @@ fn test_tls_multiple_types() unsafe {
 
 #[test]
 fn test_tls_overwrite_multiple_types() unsafe {
-    fn str_key(+_x: @str) { }
+    fn str_key(+_x: @str/~) { }
     fn box_key(+_x: @@()) { }
     fn int_key(+_x: @int) { }
     do task::spawn {
@@ -1393,7 +1393,7 @@ fn test_tls_overwrite_multiple_types() unsafe {
 #[should_fail]
 #[ignore(cfg(windows))]
 fn test_tls_cleanup_on_failure() unsafe {
-    fn str_key(+_x: @str) { }
+    fn str_key(+_x: @str/~) { }
     fn box_key(+_x: @@()) { }
     fn int_key(+_x: @int) { }
     local_data_set(str_key, @"parent data");
diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs
index 4bfd16344cb..3c56a6fd4f1 100644
--- a/src/libcore/to_bytes.rs
+++ b/src/libcore/to_bytes.rs
@@ -14,6 +14,6 @@ impl of to_bytes for str {
     fn to_bytes() -> ~[u8] { str::bytes(self) }
 }
 
-impl of to_bytes for @str {
+impl of to_bytes for @(str/~) {
     fn to_bytes() -> ~[u8] { str::bytes(*self) }
 }
diff --git a/src/libcore/unsafe.rs b/src/libcore/unsafe.rs
index b07c9465df7..0a62e77c410 100644
--- a/src/libcore/unsafe.rs
+++ b/src/libcore/unsafe.rs
@@ -61,8 +61,8 @@ mod tests {
             let box = @"box box box";       // refcount 1
             bump_box_refcount(box);         // refcount 2
             let ptr: *int = transmute(box); // refcount 2
-            let _box1: @str = reinterpret_cast(ptr);
-            let _box2: @str = reinterpret_cast(ptr);
+            let _box1: @str/~ = reinterpret_cast(ptr);
+            let _box2: @str/~ = reinterpret_cast(ptr);
             assert *_box1 == "box box box";
             assert *_box2 == "box box box";
             // Will destroy _box1 and _box2. Without the bump, this would
diff --git a/src/libstd/json.rs b/src/libstd/json.rs
index 9f51ab157b7..da86b9d4df0 100644
--- a/src/libstd/json.rs
+++ b/src/libstd/json.rs
@@ -29,7 +29,7 @@ export null;
 /// Represents a json value
 enum json {
     num(float),
-    string(@str),
+    string(@str/~),
     boolean(bool),
     list(@~[json]),
     dict(map::hashmap<str, json>),
@@ -39,7 +39,7 @@ enum json {
 type error = {
     line: uint,
     col: uint,
-    msg: @str,
+    msg: @str/~,
 };
 
 /// Serializes a json value into a io::writer
@@ -324,7 +324,7 @@ impl parser for parser {
         ok(res)
     }
 
-    fn parse_str() -> result<@str, error> {
+    fn parse_str() -> result<@str/~, error> {
         let mut escape = false;
         let mut res = "";
 
@@ -579,7 +579,7 @@ impl of to_json for str {
     fn to_json() -> json { string(@copy self) }
 }
 
-impl of to_json for @str {
+impl of to_json for @str/~ {
     fn to_json() -> json { string(self) }
 }
 
diff --git a/src/libstd/map.rs b/src/libstd/map.rs
index 8a2089c6f2b..cc88a91bcf2 100644
--- a/src/libstd/map.rs
+++ b/src/libstd/map.rs
@@ -310,8 +310,8 @@ fn str_hash<V: copy>() -> hashmap<str, V> {
 }
 
 /// Construct a hashmap for boxed string keys
-fn box_str_hash<V: copy>() -> hashmap<@str, V> {
-    ret hashmap(|x: @str| str::hash(*x), |x,y| str::eq(*x,*y));
+fn box_str_hash<V: copy>() -> hashmap<@str/~, V> {
+    ret hashmap(|x: @str/~| str::hash(*x), |x,y| str::eq(*x,*y));
 }
 
 /// Construct a hashmap for byte string keys
diff --git a/src/libstd/rope.rs b/src/libstd/rope.rs
index 4dc5116b509..91f63fe938c 100644
--- a/src/libstd/rope.rs
+++ b/src/libstd/rope.rs
@@ -53,7 +53,7 @@ fn empty() -> rope {
  * * this operation does not copy the string;
  * * the function runs in linear time.
  */
-fn of_str(str: @str) -> rope {
+fn of_str(str: @str/~) -> rope {
     ret of_substr(str, 0u, str::len(*str));
 }
 
@@ -79,7 +79,7 @@ fn of_str(str: @str) -> rope {
  * * this function does _not_ check the validity of the substring;
  * * this function fails if `byte_offset` or `byte_len` do not match `str`.
  */
-fn of_substr(str: @str, byte_offset: uint, byte_len: uint) -> rope {
+fn of_substr(str: @str/~, byte_offset: uint, byte_len: uint) -> rope {
     if byte_len == 0u { ret node::empty; }
     if byte_offset + byte_len  > str::len(*str) { fail; }
     ret node::content(node::of_substr(str, byte_offset, byte_len));
@@ -107,7 +107,7 @@ fn append_char(rope: rope, char: char) -> rope {
  *
  * * this function executes in near-linear time
  */
-fn append_str(rope: rope, str: @str) -> rope {
+fn append_str(rope: rope, str: @str/~) -> rope {
     ret append_rope(rope, of_str(str))
 }
 
@@ -127,7 +127,7 @@ fn prepend_char(rope: rope, char: char) -> rope {
  * # Performance note
  * * this function executes in near-linear time
  */
-fn prepend_str(rope: rope, str: @str) -> rope {
+fn prepend_str(rope: rope, str: @str/~) -> rope {
     ret append_rope(of_str(str), rope)
 }
 
@@ -567,7 +567,7 @@ mod node {
         byte_offset: uint,
         byte_len:    uint,
         char_len:   uint,
-        content:    @str
+        content:    @str/~
     };
 
     /**
@@ -627,7 +627,7 @@ mod node {
      * Performance note: The complexity of this function is linear in
      * the length of `str`.
      */
-    fn of_str(str: @str) -> @node {
+    fn of_str(str: @str/~) -> @node {
         ret of_substr(str, 0u, str::len(*str));
     }
 
@@ -648,7 +648,7 @@ mod node {
      * Behavior is undefined if `byte_start` or `byte_len` do not represent
      * valid positions in `str`
      */
-    fn of_substr(str: @str, byte_start: uint, byte_len: uint) -> @node {
+    fn of_substr(str: @str/~, byte_start: uint, byte_len: uint) -> @node {
         ret of_substr_unsafer(str, byte_start, byte_len,
                               str::count_chars(*str, byte_start, byte_len));
     }
@@ -674,7 +674,7 @@ mod node {
      * * Behavior is undefined if `char_len` does not accurately represent the
      *   number of chars between byte_start and byte_start+byte_len
      */
-    fn of_substr_unsafer(str: @str, byte_start: uint, byte_len: uint,
+    fn of_substr_unsafer(str: @str/~, byte_start: uint, byte_len: uint,
                           char_len: uint) -> @node {
         assert(byte_start + byte_len <= str::len(*str));
         let candidate = @leaf({
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index f7e990b1025..10a29453c1e 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -32,7 +32,7 @@ fn deserialize_span<D>(_d: D) -> span {
 type spanned<T> = {node: T, span: span};
 
 #[auto_serialize]
-type ident = @str;
+type ident = @str/~;
 
 // Functions may or may not have names.
 #[auto_serialize]
@@ -427,11 +427,11 @@ type lit = spanned<lit_>;
 
 #[auto_serialize]
 enum lit_ {
-    lit_str(@str),
+    lit_str(@str/~),
     lit_int(i64, int_ty),
     lit_uint(u64, uint_ty),
     lit_int_unsuffixed(i64),
-    lit_float(@str, float_ty),
+    lit_float(@str/~, float_ty),
     lit_nil,
     lit_bool(bool),
 }
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 43a6183b4d5..aac0b1f4d76 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -124,7 +124,7 @@ fn get_meta_item_name(meta: @ast::meta_item) -> ast::ident {
  * Gets the string value if the meta_item is a meta_name_value variant
  * containing a string, otherwise none
  */
-fn get_meta_item_value_str(meta: @ast::meta_item) -> option<@str> {
+fn get_meta_item_value_str(meta: @ast::meta_item) -> option<@str/~> {
     alt meta.node {
       ast::meta_name_value(_, v) {
         alt v.node {
@@ -154,7 +154,7 @@ fn get_meta_item_list(meta: @ast::meta_item) -> option<~[@ast::meta_item]> {
  */
 fn get_name_value_str_pair(
     item: @ast::meta_item
-) -> option<(ast::ident, @str)> {
+) -> option<(ast::ident, @str/~)> {
     alt attr::get_meta_item_value_str(item) {
       some(value) {
         let name = attr::get_meta_item_name(item);
@@ -239,7 +239,7 @@ fn attrs_contains_name(attrs: ~[ast::attribute], +name: str) -> bool {
 }
 
 fn first_attr_value_str_by_name(attrs: ~[ast::attribute], +name: str)
-    -> option<@str> {
+    -> option<@str/~> {
     let mattrs = find_attrs_by_name(attrs, name);
     if vec::len(mattrs) > 0u {
         ret get_meta_item_value_str(attr_meta(mattrs[0]));
@@ -258,7 +258,7 @@ fn last_meta_item_by_name(
 fn last_meta_item_value_str_by_name(
     items: ~[@ast::meta_item],
     +name: str
-) -> option<@str> {
+) -> option<@str/~> {
     alt last_meta_item_by_name(items, name) {
       some(item) {
         alt attr::get_meta_item_value_str(item) {
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs
index 3daf9106b06..867d2d7e45a 100644
--- a/src/libsyntax/codemap.rs
+++ b/src/libsyntax/codemap.rs
@@ -45,7 +45,7 @@ enum file_substr {
 }
 
 type filemap =
-    @{name: filename, substr: file_substr, src: @str,
+    @{name: filename, substr: file_substr, src: @str/~,
       start_pos: file_pos, mut lines: ~[file_pos]};
 
 type codemap = @{files: dvec<filemap>};
@@ -55,7 +55,7 @@ type loc = {file: filemap, line: uint, col: uint};
 fn new_codemap() -> codemap { @{files: dvec()} }
 
 fn new_filemap_w_substr(+filename: filename, +substr: file_substr,
-                        src: @str,
+                        src: @str/~,
                         start_pos_ch: uint, start_pos_byte: uint)
    -> filemap {
     ret @{name: filename, substr: substr, src: src,
@@ -63,7 +63,7 @@ fn new_filemap_w_substr(+filename: filename, +substr: file_substr,
           mut lines: ~[{ch: start_pos_ch, byte: start_pos_byte}]};
 }
 
-fn new_filemap(+filename: filename, src: @str,
+fn new_filemap(+filename: filename, src: @str/~,
                start_pos_ch: uint, start_pos_byte: uint)
     -> filemap {
     ret new_filemap_w_substr(filename, fss_none, src,
diff --git a/src/libsyntax/ext/auto_serialize.rs b/src/libsyntax/ext/auto_serialize.rs
index 0de49367b17..e32ebf4eae5 100644
--- a/src/libsyntax/ext/auto_serialize.rs
+++ b/src/libsyntax/ext/auto_serialize.rs
@@ -218,7 +218,7 @@ impl helpers for ext_ctxt {
                 ast::expr_alt(v, arms, ast::alt_exhaustive)))
     }
 
-    fn lit_str(span: span, s: @str) -> @ast::expr {
+    fn lit_str(span: span, s: @str/~) -> @ast::expr {
         self.expr(
             span,
             ast::expr_lit(
@@ -343,8 +343,19 @@ fn ser_lambda(cx: ext_ctxt, tps: ser_tps_map, ty: @ast::ty,
     cx.lambda(cx.blk(ty.span, ser_ty(cx, tps, ty, s, v)))
 }
 
+fn is_vec_or_str(ty: @ast::ty) -> bool {
+    alt ty.node {
+      ast::ty_vec(_) { true }
+      // This may be wrong if the user has shadowed (!) str
+      ast::ty_path(@{span: _, global: _, idents: ids,
+                             rp: none, types: _}, _)
+      if ids == ~[@"str"] { true }
+      _ { false }
+    }
+}
+
 fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
-                ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
+          ty: @ast::ty, -s: @ast::expr, -v: @ast::expr)
     -> ~[@ast::stmt] {
 
     let ext_cx = cx; // required for #ast{}
@@ -365,6 +376,11 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
         ~[#ast(stmt){$(s).emit_box($(l));}]
       }
 
+      // For unique evecs/estrs, just pass through to underlying vec or str
+      ast::ty_uniq(mt) if is_vec_or_str(mt.ty) {
+        ser_ty(cx, tps, mt.ty, s, v)
+      }
+
       ast::ty_uniq(mt) {
         let l = ser_lambda(cx, tps, mt.ty, cx.clone(s), #ast{ *$(v) });
         ~[#ast(stmt){$(s).emit_uniq($(l));}]
@@ -612,6 +628,11 @@ fn deser_ty(cx: ext_ctxt, tps: deser_tps_map,
         #ast{ @$(d).read_box($(l)) }
       }
 
+      // For unique evecs/estrs, just pass through to underlying vec or str
+      ast::ty_uniq(mt) if is_vec_or_str(mt.ty) {
+        deser_ty(cx, tps, mt.ty, d)
+      }
+
       ast::ty_uniq(mt) {
         let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
         #ast{ ~$(d).read_uniq($(l)) }
diff --git a/src/libsyntax/ext/simplext.rs b/src/libsyntax/ext/simplext.rs
index c9355f05e38..0d415ccfc43 100644
--- a/src/libsyntax/ext/simplext.rs
+++ b/src/libsyntax/ext/simplext.rs
@@ -679,7 +679,7 @@ fn add_new_extension(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
                      _body: ast::mac_body) -> base::macro_def {
     let args = get_mac_args_no_max(cx, sp, arg, 0u, "macro");
 
-    let mut macro_name: option<@str> = none;
+    let mut macro_name: option<@str/~> = none;
     let mut clauses: ~[@clause] = ~[];
     for args.each |arg| {
         alt arg.node {
diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs
index 8924c5820a9..113fdea42e4 100644
--- a/src/libsyntax/ext/tt/transcribe.rs
+++ b/src/libsyntax/ext/tt/transcribe.rs
@@ -24,7 +24,7 @@ type tt_frame = @{
 
 type tt_reader = @{
     sp_diag: span_handler,
-    interner: @interner<@str>,
+    interner: @interner<@str/~>,
     mut cur: tt_frame,
     /* for MBE-style macro transcription */
     interpolations: std::map::hashmap<ident, @arb_depth>,
@@ -38,7 +38,7 @@ type tt_reader = @{
 /** This can do Macro-By-Example transcription. On the other hand, if
  *  `src` contains no `tt_dotdotdot`s and `tt_interpolate`s, `interp` can (and
  *  should) be none. */
-fn new_tt_reader(sp_diag: span_handler, itr: @interner<@str>,
+fn new_tt_reader(sp_diag: span_handler, itr: @interner<@str/~>,
                  interp: option<std::map::hashmap<ident,@arb_depth>>,
                  src: ~[ast::token_tree])
     -> tt_reader {
diff --git a/src/libsyntax/parse.rs b/src/libsyntax/parse.rs
index 4d6bd53d8df..7ccc9c5a438 100644
--- a/src/libsyntax/parse.rs
+++ b/src/libsyntax/parse.rs
@@ -25,7 +25,7 @@ type parse_sess = @{
     cm: codemap::codemap,
     mut next_id: node_id,
     span_diagnostic: span_handler,
-    interner: @interner::interner<@str>,
+    interner: @interner::interner<@str/~>,
     // these two must be kept up to date
     mut chpos: uint,
     mut byte_pos: uint
@@ -36,7 +36,7 @@ fn new_parse_sess(demitter: option<emitter>) -> parse_sess {
     ret @{cm: cm,
           mut next_id: 1,
           span_diagnostic: mk_span_handler(mk_handler(demitter), cm),
-          interner: @interner::mk::<@str>(|x| str::hash(*x),
+          interner: @interner::mk::<@str/~>(|x| str::hash(*x),
                                           |x,y| str::eq(*x, *y)),
           mut chpos: 0u, mut byte_pos: 0u};
 }
@@ -46,7 +46,7 @@ fn new_parse_sess_special_handler(sh: span_handler, cm: codemap::codemap)
     ret @{cm: cm,
           mut next_id: 1,
           span_diagnostic: sh,
-          interner: @interner::mk::<@str>(|x| str::hash(*x),
+          interner: @interner::mk::<@str/~>(|x| str::hash(*x),
                                           |x,y| str::eq(*x, *y)),
           mut chpos: 0u, mut byte_pos: 0u};
 }
@@ -97,7 +97,7 @@ fn parse_crate_from_source_file(input: str, cfg: ast::crate_cfg,
     ret r;
 }
 
-fn parse_crate_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
+fn parse_crate_from_source_str(name: str, source: @str/~, cfg: ast::crate_cfg,
                                sess: parse_sess) -> @ast::crate {
     let (p, rdr) = new_parser_etc_from_source_str(sess, cfg, name,
                                                   codemap::fss_none, source);
@@ -107,7 +107,7 @@ fn parse_crate_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
     ret r;
 }
 
-fn parse_expr_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
+fn parse_expr_from_source_str(name: str, source: @str/~, cfg: ast::crate_cfg,
                               sess: parse_sess) -> @ast::expr {
     let (p, rdr) = new_parser_etc_from_source_str(sess, cfg, name,
                                                   codemap::fss_none, source);
@@ -117,7 +117,7 @@ fn parse_expr_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
     ret r;
 }
 
-fn parse_item_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
+fn parse_item_from_source_str(name: str, source: @str/~, cfg: ast::crate_cfg,
                               +attrs: ~[ast::attribute],
                               vis: ast::visibility,
                               sess: parse_sess) -> option<@ast::item> {
@@ -131,7 +131,7 @@ fn parse_item_from_source_str(name: str, source: @str, cfg: ast::crate_cfg,
 
 fn parse_from_source_str<T>(f: fn (p: parser) -> T,
                             name: str, ss: codemap::file_substr,
-                            source: @str, cfg: ast::crate_cfg,
+                            source: @str/~, cfg: ast::crate_cfg,
                             sess: parse_sess)
     -> T
 {
@@ -156,7 +156,7 @@ fn next_node_id(sess: parse_sess) -> node_id {
 
 fn new_parser_etc_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
                                   +name: str, +ss: codemap::file_substr,
-                                  source: @str) -> (parser, string_reader) {
+                                  source: @str/~) -> (parser, string_reader) {
     let ftype = parser::SOURCE_FILE;
     let filemap = codemap::new_filemap_w_substr
         (name, ss, source, sess.chpos, sess.byte_pos);
@@ -168,7 +168,7 @@ fn new_parser_etc_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
 
 fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
                               +name: str, +ss: codemap::file_substr,
-                              source: @str) -> parser {
+                              source: @str/~) -> parser {
     let (p, _) = new_parser_etc_from_source_str(sess, cfg, name, ss, source);
     ret p;
 }
diff --git a/src/libsyntax/parse/comments.rs b/src/libsyntax/parse/comments.rs
index e05887d28b4..aa3e808f63e 100644
--- a/src/libsyntax/parse/comments.rs
+++ b/src/libsyntax/parse/comments.rs
@@ -275,7 +275,7 @@ fn gather_comments_and_literals(span_diagnostic: diagnostic::span_handler,
                                 srdr: io::reader) ->
    {cmnts: ~[cmnt], lits: ~[lit]} {
     let src = @str::from_bytes(srdr.read_whole_stream());
-    let itr = @interner::mk::<@str>(
+    let itr = @interner::mk::<@str/~>(
         |x| str::hash(*x),
         |x,y| str::eq(*x, *y)
     );
diff --git a/src/libsyntax/parse/eval.rs b/src/libsyntax/parse/eval.rs
index 883aedb75a6..54a2abf20c9 100644
--- a/src/libsyntax/parse/eval.rs
+++ b/src/libsyntax/parse/eval.rs
@@ -78,7 +78,7 @@ fn parse_companion_mod(cx: ctx, prefix: str, suffix: option<str>)
     }
 }
 
-fn cdir_path_opt(id: ast::ident, attrs: ~[ast::attribute]) -> @str {
+fn cdir_path_opt(id: ast::ident, attrs: ~[ast::attribute]) -> @str/~ {
     alt ::attr::first_attr_value_str_by_name(attrs, "path") {
       some(d) {
         ret d;
diff --git a/src/libsyntax/parse/lexer.rs b/src/libsyntax/parse/lexer.rs
index b3ba35dea2e..d7f9fc12840 100644
--- a/src/libsyntax/parse/lexer.rs
+++ b/src/libsyntax/parse/lexer.rs
@@ -14,20 +14,20 @@ iface reader {
     fn next_token() -> {tok: token::token, sp: span};
     fn fatal(str) -> !;
     fn span_diag() -> span_handler;
-    fn interner() -> @interner<@str>;
+    fn interner() -> @interner<@str/~>;
     fn peek() -> {tok: token::token, sp: span};
     fn dup() -> reader;
 }
 
 type string_reader = @{
     span_diagnostic: span_handler,
-    src: @str,
+    src: @str/~,
     mut col: uint,
     mut pos: uint,
     mut curr: char,
     mut chpos: uint,
     filemap: codemap::filemap,
-    interner: @interner<@str>,
+    interner: @interner<@str/~>,
     /* cached: */
     mut peek_tok: token::token,
     mut peek_span: span
@@ -35,7 +35,7 @@ type string_reader = @{
 
 fn new_string_reader(span_diagnostic: span_handler,
                      filemap: codemap::filemap,
-                     itr: @interner<@str>) -> string_reader {
+                     itr: @interner<@str/~>) -> string_reader {
     let r = new_low_level_string_reader(span_diagnostic, filemap, itr);
     string_advance_token(r); /* fill in peek_* */
     ret r;
@@ -44,7 +44,7 @@ fn new_string_reader(span_diagnostic: span_handler,
 /* For comments.rs, which hackily pokes into 'pos' and 'curr' */
 fn new_low_level_string_reader(span_diagnostic: span_handler,
                                filemap: codemap::filemap,
-                               itr: @interner<@str>)
+                               itr: @interner<@str/~>)
     -> string_reader {
     let r = @{span_diagnostic: span_diagnostic, src: filemap.src,
               mut col: 0u, mut pos: 0u, mut curr: -1 as char,
@@ -79,7 +79,7 @@ impl string_reader_as_reader of reader for string_reader {
         self.span_diagnostic.span_fatal(copy self.peek_span, m)
     }
     fn span_diag() -> span_handler { self.span_diagnostic }
-    fn interner() -> @interner<@str> { self.interner }
+    fn interner() -> @interner<@str/~> { self.interner }
     fn peek() -> {tok: token::token, sp: span} {
         {tok: self.peek_tok, sp: self.peek_span}
     }
@@ -101,7 +101,7 @@ impl tt_reader_as_reader of reader for tt_reader {
         self.sp_diag.span_fatal(copy self.cur_span, m);
     }
     fn span_diag() -> span_handler { self.sp_diag }
-    fn interner() -> @interner<@str> { self.interner }
+    fn interner() -> @interner<@str/~> { self.interner }
     fn peek() -> {tok: token::token, sp: span} {
         { tok: self.cur_tok, sp: self.cur_span }
     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index f4681ba2619..9d8458c9c60 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -230,7 +230,7 @@ class parser {
     fn warn(m: str) {
         self.sess.span_diagnostic.span_warn(copy self.span, m)
     }
-    fn get_str(i: token::str_num) -> @str {
+    fn get_str(i: token::str_num) -> @str/~ {
         interner::get(*self.reader.interner(), i)
     }
     fn get_id() -> node_id { next_node_id(self.sess) }
@@ -394,7 +394,7 @@ class parser {
         }
     }
 
-    fn region_from_name(s: option<@str>) -> @region {
+    fn region_from_name(s: option<@str/~>) -> @region {
         let r = alt s {
           some (string) { re_named(string) }
           none { re_anon }
@@ -461,22 +461,10 @@ class parser {
             }
         } else if self.token == token::AT {
             self.bump();
-            // HACK: turn @[...] into a @-evec
-            alt self.parse_mt() {
-              {ty: t @ @{node: ty_vec(_), _}, mutbl: m_imm} {
-                ty_vstore(t, vstore_box)
-              }
-              mt { ty_box(mt) }
-            }
+            ty_box(self.parse_mt())
         } else if self.token == token::TILDE {
             self.bump();
-            // HACK: turn ~[...] into a ~-evec
-            alt self.parse_mt() {
-              {ty: t @ @{node: ty_vec(_), _}, mutbl: m_imm} {
-                ty_vstore(t, vstore_uniq)
-              }
-              mt { ty_uniq(mt) }
-            }
+            ty_uniq(self.parse_mt())
         } else if self.token == token::BINOP(token::STAR) {
             self.bump();
             ty_ptr(self.parse_mt())
@@ -506,13 +494,8 @@ class parser {
         } else if self.token == token::BINOP(token::AND) {
             self.bump();
             let region = self.parse_region_dot();
-            // HACK: turn &a.[...] into a &a-evec
-            alt self.parse_mt() {
-              {ty: t @ @{node: ty_vec(_), _}, mutbl: m_imm} {
-                ty_vstore(t, vstore_slice(region))
-              }
-              mt { ty_rptr(region, mt) }
-            }
+            let mt = self.parse_mt();
+            ty_rptr(region, mt)
         } else if self.eat_keyword("pure") {
             self.parse_ty_fn(ast::pure_fn)
         } else if self.eat_keyword("unsafe") {
@@ -2742,7 +2725,7 @@ class parser {
                       config: self.cfg});
     }
 
-    fn parse_str() -> @str {
+    fn parse_str() -> @str/~ {
         alt copy self.token {
           token::LIT_STR(s) { self.bump(); self.get_str(s) }
           _ {
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index bcfb9289086..2c7b14cfe11 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -115,7 +115,7 @@ fn binop_to_str(o: binop) -> str {
     }
 }
 
-fn to_str(in: interner<@str>, t: token) -> str {
+fn to_str(in: interner<@str/~>, t: token) -> str {
     alt t {
       EQ { "=" }
       LT { "<" }
diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs
index 58f5ac85d48..09754d27e67 100644
--- a/src/libsyntax/print/pp.rs
+++ b/src/libsyntax/print/pp.rs
@@ -59,7 +59,7 @@ type break_t = {offset: int, blank_space: int};
 
 type begin_t = {offset: int, breaks: breaks};
 
-enum token { STRING(@str, int), BREAK(break_t), BEGIN(begin_t), END, EOF, }
+enum token { STRING(@str/~, int), BREAK(break_t), BEGIN(begin_t), END, EOF, }
 
 fn tok_str(++t: token) -> str {
     alt t {
diff --git a/src/rustc/back/link.rs b/src/rustc/back/link.rs
index 0d399bd6303..10042ea85d2 100644
--- a/src/rustc/back/link.rs
+++ b/src/rustc/back/link.rs
@@ -291,14 +291,14 @@ fn build_link_meta(sess: session, c: ast::crate, output: str,
                    sha: sha1) -> link_meta {
 
     type provided_metas =
-        {name: option<@str>,
-         vers: option<@str>,
+        {name: option<@str/~>,
+         vers: option<@str/~>,
          cmh_items: ~[@ast::meta_item]};
 
     fn provided_link_metas(sess: session, c: ast::crate) ->
        provided_metas {
-        let mut name: option<@str> = none;
-        let mut vers: option<@str> = none;
+        let mut name: option<@str/~> = none;
+        let mut vers: option<@str/~> = none;
         let mut cmh_items: ~[@ast::meta_item] = ~[];
         let linkage_metas = attr::find_linkage_metas(c.node.attrs);
         attr::require_unique_names(sess.diagnostic(), linkage_metas);
@@ -321,7 +321,7 @@ fn build_link_meta(sess: session, c: ast::crate, output: str,
     // This calculates CMH as defined above
     fn crate_meta_extras_hash(sha: sha1, _crate: ast::crate,
                               metas: provided_metas,
-                              dep_hashes: ~[@str]) -> str {
+                              dep_hashes: ~[@str/~]) -> str {
         fn len_and_str(s: str) -> str {
             ret #fmt["%u_%s", str::len(s), s];
         }
@@ -362,7 +362,7 @@ fn build_link_meta(sess: session, c: ast::crate, output: str,
     }
 
     fn crate_meta_name(sess: session, _crate: ast::crate,
-                       output: str, metas: provided_metas) -> @str {
+                       output: str, metas: provided_metas) -> @str/~ {
         ret alt metas.name {
               some(v) { v }
               none {
@@ -384,7 +384,7 @@ fn build_link_meta(sess: session, c: ast::crate, output: str,
     }
 
     fn crate_meta_vers(sess: session, _crate: ast::crate,
-                       metas: provided_metas) -> @str {
+                       metas: provided_metas) -> @str/~ {
         ret alt metas.vers {
               some(v) { v }
               none {
@@ -490,7 +490,7 @@ fn mangle(ss: path) -> str {
     n
 }
 
-fn exported_name(path: path, hash: @str, vers: @str) -> str {
+fn exported_name(path: path, hash: @str/~, vers: @str/~) -> str {
     ret mangle(
         vec::append_one(vec::append_one(path, path_name(hash)),
                         path_name(vers)));
@@ -502,7 +502,7 @@ fn mangle_exported_name(ccx: @crate_ctxt, path: path, t: ty::t) -> str {
 }
 
 fn mangle_internal_name_by_type_only(ccx: @crate_ctxt,
-                                     t: ty::t, name: @str) ->
+                                     t: ty::t, name: @str/~) ->
    str {
     let s = @util::ppaux::ty_to_short_str(ccx.tcx, t);
     let hash = get_symbol_hash(ccx, t);
@@ -510,7 +510,7 @@ fn mangle_internal_name_by_type_only(ccx: @crate_ctxt,
 }
 
 fn mangle_internal_name_by_path_and_seq(ccx: @crate_ctxt, path: path,
-                                        flav: @str) -> str {
+                                        flav: @str/~) -> str {
     ret mangle(vec::append_one(path, path_name(@ccx.names(*flav))));
 }
 
@@ -518,7 +518,7 @@ fn mangle_internal_name_by_path(_ccx: @crate_ctxt, path: path) -> str {
     ret mangle(path);
 }
 
-fn mangle_internal_name_by_seq(ccx: @crate_ctxt, flav: @str) -> str {
+fn mangle_internal_name_by_seq(ccx: @crate_ctxt, flav: @str/~) -> str {
     ret ccx.names(*flav);
 }
 
diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs
index 4d9a3d3e467..b6883097a5b 100644
--- a/src/rustc/metadata/common.rs
+++ b/src/rustc/metadata/common.rs
@@ -133,5 +133,5 @@ fn hash_path(&&s: str) -> uint {
     ret h;
 }
 
-type link_meta = {name: @str, vers: @str, extras_hash: str};
+type link_meta = {name: @str/~, vers: @str/~, extras_hash: str};
 
diff --git a/src/rustc/metadata/creader.rs b/src/rustc/metadata/creader.rs
index c755235f4e8..13a1d3543c5 100644
--- a/src/rustc/metadata/creader.rs
+++ b/src/rustc/metadata/creader.rs
@@ -38,7 +38,7 @@ fn read_crates(diag: span_handler, crate: ast::crate,
 type cache_entry = {
     cnum: int,
     span: span,
-    hash: @str,
+    hash: @str/~,
     metas: @~[@ast::meta_item]
 };
 
diff --git a/src/rustc/metadata/cstore.rs b/src/rustc/metadata/cstore.rs
index 21506a59f56..f805d8d16cd 100644
--- a/src/rustc/metadata/cstore.rs
+++ b/src/rustc/metadata/cstore.rs
@@ -37,7 +37,7 @@ type cnum_map = map::hashmap<ast::crate_num, ast::crate_num>;
 // Multiple items may have the same def_id in crate metadata. They may be
 // renamed imports or reexports. This map keeps the "real" module path
 // and def_id.
-type mod_path_map = map::hashmap<ast::def_id, @str>;
+type mod_path_map = map::hashmap<ast::def_id, @str/~>;
 
 type crate_metadata = @{name: str,
                         data: @~[u8],
@@ -83,12 +83,12 @@ fn get_crate_data(cstore: cstore, cnum: ast::crate_num) -> crate_metadata {
     ret p(cstore).metas.get(cnum);
 }
 
-fn get_crate_hash(cstore: cstore, cnum: ast::crate_num) -> @str {
+fn get_crate_hash(cstore: cstore, cnum: ast::crate_num) -> @str/~ {
     let cdata = get_crate_data(cstore, cnum);
     ret decoder::get_crate_hash(cdata.data);
 }
 
-fn get_crate_vers(cstore: cstore, cnum: ast::crate_num) -> @str {
+fn get_crate_vers(cstore: cstore, cnum: ast::crate_num) -> @str/~ {
     let cdata = get_crate_data(cstore, cnum);
     ret decoder::get_crate_vers(cdata.data);
 }
@@ -153,8 +153,8 @@ fn find_use_stmt_cnum(cstore: cstore,
 
 // returns hashes of crates directly used by this crate. Hashes are
 // sorted by crate name.
-fn get_dep_hashes(cstore: cstore) -> ~[@str] {
-    type crate_hash = {name: @str, hash: @str};
+fn get_dep_hashes(cstore: cstore) -> ~[@str/~] {
+    type crate_hash = {name: @str/~, hash: @str/~};
     let mut result = ~[];
 
     for p(cstore).use_crate_map.each_value |cnum| {
@@ -171,7 +171,7 @@ fn get_dep_hashes(cstore: cstore) -> ~[@str] {
     for sorted.each |x| {
         #debug("  hash[%s]: %s", *x.name, *x.hash);
     }
-    fn mapper(ch: crate_hash) -> @str { ret ch.hash; }
+    fn mapper(ch: crate_hash) -> @str/~ { ret ch.hash; }
     ret vec::map(sorted, mapper);
 }
 
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index fd2eb10d8d5..9e915ff1e07 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -775,7 +775,7 @@ fn list_meta_items(meta_items: ebml::doc, out: io::writer) {
     }
 }
 
-fn list_crate_attributes(md: ebml::doc, hash: @str, out: io::writer) {
+fn list_crate_attributes(md: ebml::doc, hash: @str/~, out: io::writer) {
     out.write_str(#fmt("=Crate Attributes (%s)=\n", *hash));
 
     for get_attributes(md).each |attr| {
@@ -790,7 +790,7 @@ fn get_crate_attributes(data: @~[u8]) -> ~[ast::attribute] {
 }
 
 type crate_dep = {cnum: ast::crate_num, name: ast::ident,
-                  vers: @str, hash: @str};
+                  vers: @str/~, hash: @str/~};
 
 fn get_crate_deps(data: @~[u8]) -> ~[crate_dep] {
     let mut deps: ~[crate_dep] = ~[];
@@ -821,13 +821,13 @@ fn list_crate_deps(data: @~[u8], out: io::writer) {
     out.write_str("\n");
 }
 
-fn get_crate_hash(data: @~[u8]) -> @str {
+fn get_crate_hash(data: @~[u8]) -> @str/~ {
     let cratedoc = ebml::doc(data);
     let hashdoc = ebml::get_doc(cratedoc, tag_crate_hash);
     ret @str::from_bytes(ebml::doc_data(hashdoc));
 }
 
-fn get_crate_vers(data: @~[u8]) -> @str {
+fn get_crate_vers(data: @~[u8]) -> @str/~ {
     let attrs = decoder::get_crate_attributes(data);
     ret alt attr::last_meta_item_value_str_by_name(
         attr::find_linkage_metas(attrs), "vers") {
diff --git a/src/rustc/metadata/loader.rs b/src/rustc/metadata/loader.rs
index d92154eb891..8a67de39c2b 100644
--- a/src/rustc/metadata/loader.rs
+++ b/src/rustc/metadata/loader.rs
@@ -116,7 +116,7 @@ fn find_library_crate_aux(cx: ctxt,
     }
 }
 
-fn crate_name_from_metas(metas: ~[@ast::meta_item]) -> @str {
+fn crate_name_from_metas(metas: ~[@ast::meta_item]) -> @str/~ {
     let name_items = attr::find_meta_items_by_name(metas, "name");
     alt vec::last_opt(name_items) {
       some(i) {
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs
index 57a696094e8..026f06bc8b0 100644
--- a/src/rustc/metadata/tyencode.rs
+++ b/src/rustc/metadata/tyencode.rs
@@ -29,7 +29,7 @@ type ctxt = {
 // Compact string representation for ty.t values. API ty_str & parse_from_str.
 // Extra parameters are for converting to/from def_ids in the string rep.
 // Whatever format you choose should not contain pipe characters.
-type ty_abbrev = {pos: uint, len: uint, s: @str};
+type ty_abbrev = {pos: uint, len: uint, s: @str/~};
 
 enum abbrev_ctxt { ac_no_abbrevs, ac_use_abbrevs(hashmap<ty::t, ty_abbrev>), }
 
diff --git a/src/rustc/middle/lint.rs b/src/rustc/middle/lint.rs
index 5b55fe5a61f..2e33fe8dd9a 100644
--- a/src/rustc/middle/lint.rs
+++ b/src/rustc/middle/lint.rs
@@ -462,7 +462,10 @@ fn check_item_old_vecs(cx: ty::ctxt, it: @ast::item) {
                     old_strs, t.id, it.id,
                     t.span, "deprecated str type");
               }
-              ast::ty_vstore(inner, _) {
+              ast::ty_vstore(inner, _) |
+              ast::ty_box({ty: inner, _}) |
+              ast::ty_uniq({ty: inner, _}) |
+              ast::ty_rptr(_, {ty: inner, _}) {
                 uses_vstore.insert(inner.id, true);
               }
               _ { }
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index 9c129dd673b..640d2b3cb7e 100644
--- a/src/rustc/middle/resolve3.rs
+++ b/src/rustc/middle/resolve3.rs
@@ -202,18 +202,18 @@ fn Atom(n: uint) -> Atom {
 }
 
 class AtomTable {
-    let atoms: hashmap<@str,Atom>;
-    let strings: dvec<@str>;
+    let atoms: hashmap<@str/~,Atom>;
+    let strings: dvec<@str/~>;
     let mut atom_count: uint;
 
     new() {
-        self.atoms = hashmap::<@str,Atom>(|x| str::hash(*x),
+        self.atoms = hashmap::<@str/~,Atom>(|x| str::hash(*x),
                                           |x, y| str::eq(*x, *y));
         self.strings = dvec();
         self.atom_count = 0u;
     }
 
-    fn intern(string: @str) -> Atom {
+    fn intern(string: @str/~) -> Atom {
         alt self.atoms.find(string) {
             none { /* fall through */ }
             some(atom) { ret atom; }
@@ -227,11 +227,11 @@ class AtomTable {
         ret atom;
     }
 
-    fn atom_to_str(atom: Atom) -> @str {
+    fn atom_to_str(atom: Atom) -> @str/~ {
         ret self.strings.get_elt(atom);
     }
 
-    fn atoms_to_strs(atoms: ~[Atom], f: fn(@str) -> bool) {
+    fn atoms_to_strs(atoms: ~[Atom], f: fn(@str/~) -> bool) {
         for atoms.each |atom| {
             if !f(self.atom_to_str(atom)) {
                 ret;
@@ -239,7 +239,7 @@ class AtomTable {
         }
     }
 
-    fn atoms_to_str(atoms: ~[Atom]) -> @str {
+    fn atoms_to_str(atoms: ~[Atom]) -> @str/~ {
         // XXX: str::connect should do this.
         let mut result = "";
         let mut first = true;
@@ -577,7 +577,8 @@ class PrimitiveTypeTable {
         self.intern(atom_table, @"u64",     ty_uint(ty_u64));
     }
 
-    fn intern(atom_table: @AtomTable, string: @str, primitive_type: prim_ty) {
+    fn intern(atom_table: @AtomTable, string: @str/~,
+              primitive_type: prim_ty) {
         let atom = (*atom_table).intern(string);
         self.primitive_types.insert(atom, primitive_type);
     }
diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs
index f7725cdb077..33aecc473b3 100644
--- a/src/rustc/middle/trans/tvec.rs
+++ b/src/rustc/middle/trans/tvec.rs
@@ -266,7 +266,7 @@ fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t)
     }
 }
 
-fn trans_estr(bcx: block, s: @str, vstore: ast::vstore,
+fn trans_estr(bcx: block, s: @str/~, vstore: ast::vstore,
               dest: dest) -> block {
     let _icx = bcx.insn_ctxt("tvec::trans_estr");
     let ccx = bcx.ccx();
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index da8919c96fd..3bd19805e91 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -253,7 +253,7 @@ type ctxt =
       freevars: freevars::freevar_map,
       tcache: type_cache,
       rcache: creader_cache,
-      short_names_cache: hashmap<t, @str>,
+      short_names_cache: hashmap<t, @str/~>,
       needs_drop_cache: hashmap<t, bool>,
       needs_unwind_cleanup_cache: hashmap<t, bool>,
       kind_cache: hashmap<t, kind>,
diff --git a/src/rustc/middle/typeck/astconv.rs b/src/rustc/middle/typeck/astconv.rs
index d1ae74cffc0..975d1efe4e7 100644
--- a/src/rustc/middle/typeck/astconv.rs
+++ b/src/rustc/middle/typeck/astconv.rs
@@ -160,12 +160,17 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
         ret {ty: ast_ty_to_ty(self, rscope, mt.ty), mutbl: mt.mutbl};
     }
 
-    fn mk_vstore<AC: ast_conv, RS: region_scope copy>(
-        self: AC, rscope: RS, a_seq_ty: @ast::ty, vst: ty::vstore) -> ty::t {
+    // Handle @, ~, and & being able to mean estrs and evecs.
+    // If a_seq_ty is a str or a vec, make it an estr/evec
+    fn mk_maybe_vstore<AC: ast_conv, RS: region_scope copy>(
+        self: AC, rscope: RS, a_seq_ty: ast::mt, vst: ty::vstore,
+        constr: fn(ty::mt) -> ty::t) -> ty::t {
 
         let tcx = self.tcx();
 
-        alt a_seq_ty.node {
+        alt a_seq_ty.ty.node {
+          // to convert to an e{vec,str}, there can't be a mutability argument
+          _ if a_seq_ty.mutbl != ast::m_imm {}
           ast::ty_vec(mt) {
             ret ty::mk_evec(tcx, ast_mt_to_mt(self, rscope, mt), vst);
           }
@@ -181,13 +186,8 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
           _ {}
         }
 
-        // Get the type, just for the error message
-        let seq_ty = ast_ty_to_ty(self, rscope, a_seq_ty);
-        tcx.sess.span_err(
-            a_seq_ty.span,
-            #fmt["bound not allowed on a %s",
-                 ty::ty_sort_str(tcx, seq_ty)]);
-        ret seq_ty;
+        let seq_ty = ast_mt_to_mt(self, rscope, a_seq_ty);
+        ret constr(seq_ty);
     }
 
     fn check_path_args(tcx: ty::ctxt,
@@ -227,10 +227,12 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
       ast::ty_nil { ty::mk_nil(tcx) }
       ast::ty_bot { ty::mk_bot(tcx) }
       ast::ty_box(mt) {
-        ty::mk_box(tcx, ast_mt_to_mt(self, rscope, mt))
+        mk_maybe_vstore(self, rscope, mt, ty::vstore_box,
+                        |tmt| ty::mk_box(tcx, tmt))
       }
       ast::ty_uniq(mt) {
-        ty::mk_uniq(tcx, ast_mt_to_mt(self, rscope, mt))
+        mk_maybe_vstore(self, rscope, mt, ty::vstore_uniq,
+                        |tmt| ty::mk_uniq(tcx, tmt))
       }
       ast::ty_vec(mt) {
         ty::mk_vec(tcx, ast_mt_to_mt(self, rscope, mt))
@@ -240,8 +242,9 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
       }
       ast::ty_rptr(region, mt) {
         let r = ast_region_to_region(self, rscope, ast_ty.span, region);
-        let mt = ast_mt_to_mt(self, in_anon_rscope(rscope, r), mt);
-        ty::mk_rptr(tcx, r, mt)
+        mk_maybe_vstore(self, in_anon_rscope(rscope, r), mt,
+                        ty::vstore_slice(r),
+                        |tmt| ty::mk_rptr(tcx, r, tmt))
       }
       ast::ty_tup(fields) {
         let flds = vec::map(fields, |t| ast_ty_to_ty(self, rscope, t));
@@ -318,24 +321,64 @@ fn ast_ty_to_ty<AC: ast_conv, RS: region_scope copy>(
           }
         }
       }
+      // This is awful and repetitive but will go away
       ast::ty_vstore(a_t, ast::vstore_slice(a_r)) {
         let r = ast_region_to_region(self, rscope, ast_ty.span, a_r);
-        mk_vstore(self, in_anon_rscope(rscope, r), a_t, ty::vstore_slice(r))
+        mk_maybe_vstore(self, in_anon_rscope(rscope, r),
+                        {ty: a_t, mutbl: ast::m_imm},
+                        ty::vstore_slice(r),
+                        |ty| {
+                            tcx.sess.span_err(
+                                a_t.span,
+                                #fmt["bound not allowed on a %s",
+                                     ty::ty_sort_str(tcx, ty.ty)]);
+                            ty.ty
+                        })
+
       }
       ast::ty_vstore(a_t, ast::vstore_uniq) {
-        mk_vstore(self, rscope, a_t, ty::vstore_uniq)
+        mk_maybe_vstore(self, rscope, {ty: a_t, mutbl: ast::m_imm},
+                        ty::vstore_uniq,
+                        |ty| {
+                            tcx.sess.span_err(
+                                a_t.span,
+                                #fmt["bound not allowed on a %s",
+                                     ty::ty_sort_str(tcx, ty.ty)]);
+                            ty.ty
+                        })
       }
       ast::ty_vstore(a_t, ast::vstore_box) {
-        mk_vstore(self, rscope, a_t, ty::vstore_box)
+        mk_maybe_vstore(self, rscope, {ty: a_t, mutbl: ast::m_imm},
+                        ty::vstore_box,
+                        |ty| {
+                            tcx.sess.span_err(
+                                a_t.span,
+                                #fmt["bound not allowed on a %s",
+                                     ty::ty_sort_str(tcx, ty.ty)]);
+                            ty.ty
+                        })
       }
       ast::ty_vstore(a_t, ast::vstore_fixed(some(u))) {
-        mk_vstore(self, rscope, a_t, ty::vstore_fixed(u))
+        mk_maybe_vstore(self, rscope, {ty: a_t, mutbl: ast::m_imm},
+                        ty::vstore_fixed(u),
+                        |ty| {
+                            tcx.sess.span_err(
+                                a_t.span,
+                                #fmt["bound not allowed on a %s",
+                                     ty::ty_sort_str(tcx, ty.ty)]);
+                            ty.ty
+                        })
       }
       ast::ty_vstore(_, ast::vstore_fixed(none)) {
         tcx.sess.span_bug(
             ast_ty.span,
             "implied fixed length for bound");
       }
+/*
+      ast::ty_vstore(_, _) {
+        tcx.sess.span_bug(ast_ty.span, "some BS");
+      }
+*/
       ast::ty_constr(t, cs) {
         let mut out_cs = ~[];
         for cs.each |constr| {
diff --git a/src/test/auxiliary/issue-2631-a.rs b/src/test/auxiliary/issue-2631-a.rs
index c2503bde277..049988863be 100644
--- a/src/test/auxiliary/issue-2631-a.rs
+++ b/src/test/auxiliary/issue-2631-a.rs
@@ -7,7 +7,7 @@ import dvec::*;
 import dvec::dvec;
 import std::map::hashmap;
 
-type header_map = hashmap<str, @dvec<@str>>;
+type header_map = hashmap<str, @dvec<@str/~>>;
 
 // the unused ty param is necessary so this gets monomorphized
 fn request<T: copy>(req: header_map) {
diff --git a/src/test/compile-fail/unsendable-class.rs b/src/test/compile-fail/unsendable-class.rs
index de5715321e8..11384408ad8 100644
--- a/src/test/compile-fail/unsendable-class.rs
+++ b/src/test/compile-fail/unsendable-class.rs
@@ -3,8 +3,8 @@
 
 class foo {
   let i: int;
-  let j: @str;
-  new(i:int, j: @str) { self.i = i; self.j = j; }
+  let j: @str/~;
+  new(i:int, j: @str/~) { self.i = i; self.j = j; }
 }
 
 fn main() {
diff --git a/src/test/run-fail/unwind-lambda.rs b/src/test/run-fail/unwind-lambda.rs
index cc516c550a2..360d9cdeba3 100644
--- a/src/test/run-fail/unwind-lambda.rs
+++ b/src/test/run-fail/unwind-lambda.rs
@@ -4,7 +4,7 @@ fn main() {
     let cheese = "roquefort";
     let carrots = @"crunchy";
 
-    fn@(tasties: @str, macerate: fn(str)) {
+    fn@(tasties: @str/~, macerate: fn(str)) {
         macerate(*tasties);
     } (carrots, |food| {
         let mush = food + cheese;
diff --git a/src/test/run-fail/unwind-misc-1.rs b/src/test/run-fail/unwind-misc-1.rs
index 7dc9b112f23..9eb7f88caee 100644
--- a/src/test/run-fail/unwind-misc-1.rs
+++ b/src/test/run-fail/unwind-misc-1.rs
@@ -7,11 +7,11 @@ import uint;
 
 fn main() {
     let count = @mut 0u;
-    fn hash(&&s: ~[@str]) -> uint {
+    fn hash(&&s: ~[@str/~]) -> uint {
         if (vec::len(s) > 0u && str::eq(*s[0], "boom")) { fail; }
         ret 10u;
     }
-    fn eq(&&s: ~[@str], &&t: ~[@str]) -> bool {
+    fn eq(&&s: ~[@str/~], &&t: ~[@str/~]) -> bool {
         ret s == t;
     }